Skip to content

CLI Reference Manual: Commands and All Flags

📚 Series Navigation: The previous article 33 Hooks taught you how to automatically pull the trigger on fixed events and install guardrails for Claude. This article returns to the most unadorned place — how many tricks can be attached to that line of claude you type in the terminal. Commands, flags, pipes, exit codes, check them all in one article, accompanied by a reference table you can flip to anytime.

"You can put parameters after this claude? I've always just typed a bare claude in there."

"Sure you can, there are tons. Have a script run a claude -p 'summarize this PR', and the result spits directly into a file, never even entering the interactive interface."

"Wait a minute — what is -p? I rummaged through claude --help for ages and didn't see it all."

This kind of conversation is quite common. Many people use Claude Code for half a year and always only know how to type a bare claude to enter interactive mode, having no idea there are dozens of flags hanging behind this command. You can't really blame anyone for this — the official documentation itself wrote a sentence: claude --help does not list every flag. If you only grope around relying on --help, you are destined to miss a large swath.

To put it plainly, over the past thirty or so articles we've been spinning around in "interactive mode": enter, chat, it works. But claude is fundamentally a command-line tool, and the gameplay of command-line tools goes far beyond "opening an interface" — it can connect to pipes, be stuffed into scripts, and judge success or failure based on exit codes. Today's article is exactly that "instruction manual": spreading out claude's commands, flags, pipe usages, and exit codes all at once, so you can directly flip to the table whenever you want to look something up.

After reading this article, you will get:

  • A list of core commands for claude: starting, starting with initial prompt, pipes, continuing / resuming sessions, updating, logging in, and what they each do
  • The most commonly used batch of flags (-p / --model / -c / --resume / --permission-mode / --add-dir, etc.) explained one by one, paired with a complete reference table
  • Headless and pipe usages: how to stuff Claude into scripts, use it as a linter, and connect to jq to process output
  • How to read exit codes: how to rely on it in scripts to judge "whether it succeeded or failed"
  • A complete headless pipeline you can follow through: bare calls, pipe feeding, structured output, and exit code judgment

01 First Distinguish Two Terms: Commands vs. Flags

Before rolling up your sleeves to check the tables, first nail down the two terms that are easiest to confuse. The entire line you type in the terminal consists of two things when broken down: commands and flags.

Analogy: Filling out a courier slip. claude is the action of "sending a package" itself; what follows like update, mcp are sub-actions (commands), telling the system you aren't sending a normal package today, you want to "update" or "configure MCP"; those -p, --model further back are the checkboxes (flags) on the slip, fine-tuning how you're sending this trip — Expedited? Insured? Which model to use for delivery? You pick one action, but you can check a whole bunch of checkboxes.

Down to specifics:

bash
claude update
claude -p "explain this function" --model sonnet
  • First line: claude is the program, update is the command (a sub-action, exits after running).
  • Second line: claude isn't followed by a command, directly entering the session logic; -p and --model are both flags, and "explain this function" after -p is the initial prompt for this trip.

Why do these two need to be distinguished? Because they are listed in two separate tables in the documentation, you need to know which table you're looking up when you check. If you want to know "how to update / how to log in / how to configure MCP" — check the command table; if you want to know "how to change models / how to get results without entering interactive mode / how to tell it not to ask for permissions first" — check the flag table.

There's also a thoughtful detail worth remembering first: it will prompt you if you type the wrong command. The official text says it very clearly —

If you enter an incorrect subcommand, Claude Code will suggest the closest match and exit without starting a session. For example, claude udpate will print Did you mean claude update?.

Typing claude udpate too fast is a common occurrence, and every time it honestly asks you "Did you mean to type claude update", it won't foolishly use the typo to start a session. This little consideration saves a lot of "huh, why is there no response" confusion.

💡 One-sentence summary: A line of command breaks down into two things — commands are sub-actions (update, mcp, exit after running), flags are checkboxes (-p, --model, fine-tune how this trip is run); think clearly about which table you want to check in the docs first.


02 Core Commands: The Several Postures for Starting a Session

Let's look at the commands first. There are really only a few you'll actually type on a daily basis. I'll group them by "purpose", each with the standard syntax given officially.

Group 1: Starting a Session (Most Common)

This group is what you'll be using 90% of the time:

bash
# 1. Bare start, enter interactive mode
claude

# 2. Start with an initial prompt (it answers this first after entering)
claude "explain this project"

# 3. Don't enter interactive, directly output the result and exit (headless / print mode)
claude -p "explain this function"

You are already familiar with the first two. The third one claude -p is the "alternative way of living" to be highlighted in this article — it doesn't open that chat interface, directly prints the answer to the terminal and then exits, specifically for scripts and pipes. Section 04 will elaborate.

Group 2: Picking Up Where You Left Off (Don't Let It Get Amnesia)

Remember what was said in article 19? — Every time you start a new session, Claude is an "amnesiac new intern", it forgets entirely where you left off last time. These two commands are the cure for amnesia:

bash
# Continue the most recent conversation in the "current directory"
claude -c
# (--continue is its full name, -c is the shorthand)

# Resume a "specific" conversation by ID or name
claude -r "auth-refactor" "wrap up this PR"
# (--resume is the full name, -r is the shorthand)

The difference between the two is just one word: "Recent" or "Specific".

  • -c (--continue): Only recognizes the "most recent one in the current directory", you don't have to remember the ID, it's the easiest.
  • -r (--resume): Names specifically which one you want — provide the session ID or the name you gave it previously with --name; if you don't provide one, an interactive list will pop up for you to pick.

Analogy: Continuing a chat with a colleague. -c is "let's continue what we were just talking about" — it defaults to the most recent matter, no need to explain which one; -r is "that thing about the login refactor last Wednesday, let's continue" — you have to clearly specify which matter it is, so the other party can dig up that memory.

A handy habit: Use -c when you only have one thread of work going on, to save remembering names; only when you have several stalls open at the same time (this one checking bugs, that one writing tests) do you use -r to resume by name — the premise is that you gave each stall a name with --name (shorthand -n) when starting, otherwise you won't be able to tell a bunch of UUIDs apart. A complete flow looks like this:

bash
# Give it a recognizable name when starting
claude -n "login-refactor"

# Come back a few days later, directly resume this stall by name
claude -r "login-refactor"

The official explanation for --name is straightforward — the display name it sets will appear in the /resume list and the terminal title, so you can use claude --resume <name> to resume it later. When pushing three or four tasks at the same time, relying solely on this name to identify them is vastly better than staring at a string of 550e8400-... UUIDs.

There's also a combination worth pointing out separately: -c and -p can be stacked. claude -c -p "check if there are type errors" means "continue the most recent conversation, but go headless this time, exit after outputting the result" — it carries the previous context, but doesn't enter the interactive interface. When a script wants to "advance the same task in several steps, running each step automatically", this combination is particularly handy (the example of consecutive --continue in section 04 is strung together this way).

Group 3: Maintenance and Accounts

You won't type this remaining group often, but you need to know they're there:

bash
# Update to the latest version
claude update

# Install / reinstall the local binary (can specify version: 2.1.118 / stable / latest)
claude install stable

# Log in to Anthropic account
claude auth login

# Check login status (exit code 0 if logged in, exit code 1 if not)
claude auth status

The detail that claude install can be followed by a version number is a lifesaver in critical moments: officially it says it accepts specific version numbers like 2.1.118, as well as stable, latest. Imagine a situation — after a new version update, a certain behavior changes and becomes unsuitable, using claude install 2.1.x to rollback and pin it to the last stable version, waiting for the issue to be fixed before opening it up, is much more comfortable than just waiting.

The phrase "exit code 0 if logged in, exit code 1 if not" for claude auth status should be remembered first. We will come back to it in section 05 when talking about exit codes — this is the standard trick for judging "is it currently logged in or not" in scripts.

These commands require internet access. If accessing the Anthropic account system (login, updating packages) is blocked domestically, turn on "magic internet" (VPN) before typing.

💡 One-sentence summary: Remember commands in three groups — Starting a session (claude / claude "prompt" / claude -p), Picking up where you left off (-c recognizes recent, -r resumes by name), Maintenance accounts (update / install / auth); -c and -r are the two medicines for curing "session amnesia".


03 The Most Commonly Used Batch of Flags: Explained One by One

Now that we know the commands, the main event is the flags. There are dozens of flags, but you really only use seven or eight frequently on a daily basis — I'll explain these thoroughly first, and then give you a whole table to fall back on (section 06 attaches the complete reference table, that is for "looking up", this section is for "understanding").

-p / --print: Don't Enter Interactive, Result Directly

The most important one, bar none. Add -p, and Claude won't open the chat interface — it reads your prompt, does the work, prints the result to the terminal, and exits, all without anyone watching.

bash
claude -p "what does the auth module of this project do"

It is the switch for headless mode (meaning no interactive interface, running purely in the command line), and also the foundation for all the "stuffing into scripts" and "connecting to pipes" gameplay later on. Section 04 will expand on this specifically.

--model: Which Model to Use This Trip

Temporarily specify which model to use for this session trip, overriding the default model in your settings:

bash
claude --model sonnet
claude --model opus
claude --model claude-sonnet-4-6   # Can also write the full name

You can use aliases (sonnet, opus pointing to their respective latest versions), or you can write the full model name. How to choose models and what positioning each tier has was discussed in article 05, here we only care about "how to switch temporarily in the command line".

--permission-mode: Which Permission Mode to Start From This Trip

Directly determines "whether Claude asks you before taking action on this trip". Remember that "permission rein" from article 20? — This flag is to set the tightness of the rein right at the moment of starting:

bash
claude --permission-mode plan

The options given officially are these:

Accepts default, acceptEdits, plan, auto, dontAsk, or bypassPermissions. Overrides defaultMode in the settings file.

Simply put: plan (only plans, no action), acceptEdits (automatically approves editing files), bypassPermissions (allow everything, use with caution) are the most commonly used. What tempers these modes have will be taken apart specifically in the next article (article 35). Here you just need to know "using this flag can select the mode in one step when starting".

--dangerously-skip-permissions: That Switch with "dangerous" in its Name

This flag is singled out, because beginners love to ask about it the most, and it's also the easiest to misuse. Its function is to skip all permission prompts — the official statement is crystal clear, it is equivalent to --permission-mode bypassPermissions:

bash
claude --dangerously-skip-permissions

Add it, and Claude will no longer stop to ask you when modifying files or running commands, just keeping its head down and working to the end. The name literally says dangerously (dangerously), which is Anthropic reminding you to weigh it carefully. Articles 20 and 21 repeatedly emphasized that "permission rein" — this switch is equivalent to letting go of the rein completely.

There is a red line here that should be held: Only use it in environments that are "explicitly isolated and don't matter if they break" — like one-off containers, toy repositories, or temporary sandboxes in CI. In your real project directories, especially places where you can touch production data, don't even touch it. If you want fewer permission prompts in headless batch processing, prioritize using --allowedTools to precisely allow a few tools, or use --permission-mode acceptEdits to only open up "modifying files" — it's much safer than a one-size-fits-all approach.

--add-dir: Let It Look at One More Directory

By default, Claude can only read / modify the directory you were in when you started it. --add-dir gives it access rights to a few extra directories:

bash
claude --add-dir ../apps ../lib

Typical scenario: Your project and another library it depends on are split into two folders, and you want Claude to be able to touch both sides at the same time. Note a reminder from the official docs

Grants file access; most .claude/ configurations will not be discovered from these directories.

That is to say: --add-dir only grants " read and write files" permissions, it will not incidentally load the CLAUDE.md, Skills, and other configurations in that directory. Don't expect that adding a directory will inherit their set of configurations.

--output-format: What Format to Spit the Result In

Only makes sense under -p print mode, controlling what the result looks like:

bash
claude -p "summarize this project" --output-format json

Three options: text (default, pure text), json (structured result with metadata like session ID, cost, etc.), stream-json (one JSON event per line, real-time streaming). If you want to get "how much this trip cost" and "what the session ID is" in a script, you have to use json — section 04 will demonstrate feeding it to jq.

--allowedTools / --disallowedTools: Whitelist / Blacklist

Pre-allow (or deny) certain tools to avoid headless runs getting stuck halfway on a permission prompt (a script without anyone watching is useless if it gets stuck):

bash
claude -p "run tests and fix failures" --allowedTools "Bash,Read,Edit"

Tools listed in --allowedTools are allowed directly without prompting; --disallowedTools conversely denies. They both use permission rule syntax (detailed in article 20), such as "Bash(git diff *)" to only allow commands starting with git diff.

Note the difference with --tools--tools directly deletes a certain tool from the model's context, making it completely unable to use it; --allowedTools just skips the permission prompt, the tool itself is still there.

A Few Headless-exclusive "Fuses"

These only take effect in -p mode, but are very practical, specifically preventing scripts from going out of control:

bash
# Limit the maximum number of turns, error and exit if exceeded (unlimited by default)
claude -p --max-turns 3 "query"

# Stop once the API cost exceeds this amount (in USD)
claude -p --max-budget-usd 5.00 "query"

There's a small pitfall hidden here in --max-turns: If you forget to add it when writing automated scripts, what if Claude happens to fall into an endless loop of trial and error once, the number of turns skyrockets, and the cost follows suit, burning money for nothing if nobody is watching. A sound approach is to fix a --max-turns to all batch scripts, equivalent to setting a hard upper limit of "at most toss around for a few rounds", if it exceeds it, it errors out and exits, which is actually more reassuring.

💡 One-sentence summary: Memorize these high-frequency flags — -p outputs results without entering interactive, --model switches models, --permission-mode sets permission tightness, --add-dir looks at more directories, --output-format json gets structured results, --allowedTools pre-allows tools; if you're afraid scripts will go out of control, add --max-turns / --max-budget-usd as fuses.


04 Headless and Pipes: Stuffing Claude into the Command Line

This section is where claude -p truly shines. In the previous dozens of articles, Claude was "you open a window and chat with it", in this section it becomes "a part in the command line that can connect to pipes" — it can be fed data by other commands, and it can also spit results to the next command.

Analogy: A workstation on an assembly line. Interactive mode is like you sitting at a workbench making things by hand piece by piece; headless mode is soldering Claude onto an assembly line — The previous process (like cat, git diff) sends the material in, Claude processes it, and the result flows directly to the next process (like writing to a file, feeding to jq). You don't have to watch beside it, the whole line runs itself.

Pipes: Feeding Data In

Non-interactive mode reads stdin (standard input), so you can treat it like any command-line tool, use | to pipe data into it:

bash
cat build-error.txt | claude -p 'concisely explain the root cause of this build error' > output.txt

This command did three things: cat spits out the log content → pipes it into claude -p → after it finishes explaining, > writes the result into output.txt. The whole process didn't enter any interface, suitable for stuffing into any automated workflow.

Here is a hard limit explicitly stated by the official docs worth remembering: Since v2.1.128, the upper limit for content fed through the pipe is 10MB, if it exceeds, Claude Code will report a clear error and exit with a non-zero status. To process larger inputs, write the content into a file and reference the file path in the prompt, don't pipe it directly.

Using it as a Project-exclusive Linter

Wrap the headless call in a script, and Claude becomes your project's "exclusive reviewer". This package.json example given officially is very typical — feed the diff against main to Claude, let it pick out typos:

json
{
  "scripts": {
    "lint:claude": "git diff main | claude -p \"you are a typo linter. for each typo in this diff, report filename:line on one line and the issue on the next. return nothing else.\""
  }
}

Afterward, npm run lint:claude will run it. The advantage of piping diffs: Claude doesn't need Bash permissions to read the diff itself, the material is fed in by you.

Connecting to jq to Process Structured Output

If you only want to extract the result text or grab the session ID in a script, use --output-format json paired with jq (a command-line JSON processing tool):

bash
# Only extract result text
claude -p "summarize this project" --output-format json | jq -r '.result'

The json format spits out an object with metadata — the result text is in the .result field, session ID in .session_id, and also total_cost_usd for how much this trip cost. For a script to string together multiple rounds of conversation, it relies on grabbing the session_id first and then --resume:

bash
session_id=$(claude -p "start review" --output-format json | jq -r '.session_id')
claude -p "continue that review" --resume "$session_id"

Giving This Script Call a "Temporary Identity"

When running headless batch jobs, we often want Claude to play a specific role for this trip — like "you are a security engineer, specifically look for vulnerabilities". Use --append-system-prompt to append this instruction to the end of the default system prompt, this official example feeds a PR's diff to it for security review:

bash
gh pr diff "$1" | claude -p \
  --append-system-prompt "You are a security engineer. Review for vulnerabilities." \
  --output-format json

You need to distinguish between two flags here, don't mix them up: --append-system-prompt is "append after the default prompt", Claude still retains its original set of programming assistant skills and security instructions, you are just adding an extra requirement; --system-prompt is "replace entirely" the default prompt — tool usage and security constraints are all gone, you have to be responsible for everything that remains yourself. 90% of scenarios you want is append (append), not system-prompt (replace); only use replace when Claude's default identity of "programming assistant" doesn't fit your task at all.

--bare: Faster Startup in Scripts

There's another flag born specifically for scripts, --bare (bare mode). Official words:

Minimal mode: Skips auto-discovery of hooks, skills, plugins, MCP servers, memory, and CLAUDE.md so scripted invocations start faster.

In plain words, a normal claude -p will load that entire set of context for interactive sessions (your CLAUDE.md, installed Skills, configured MCPs); --bare skips all these, only leaving the three basic capabilities of Bash, reading files, and writing files. It starts fast and produces consistent results on every machine (won't be influenced by private stuff in someone's ~/.claude). It's especially useful in CI and scripts. The official documentation also clearly states: --bare will become the default for -p in future versions, getting into this habit now is quite worthwhile.

The difference between interactive mode and headless mode is clearest when seen side-by-side:

DimensionInteractive Mode (claude)Headless Mode (claude -p)
Has chat interface✅ Yes, you type back and forth❌ No, exits after result
Unattended✅ You are sitting in front❌ Unattended, script runs automatically
Can connect to pipes❌ Cannot✅ Can, reads stdin, can be redirected
What about permissionsStops to ask you before actingSet in advance via --allowedTools / --permission-mode
Typical scenariosDaily dev, conversational workCI, batch processing, acting as linter, stuffing into scripts

💡 One-sentence summary: claude -p turns Claude into a command-line part that can connect to pipes — cat ... | claude -p ... > out.txt for stringing pipelines, --output-format json with jq to grab fields, --bare makes scripts start faster and cleaner; for unattended tasks, permissions must be granted in advance with flags.


05 Exit Codes: How Scripts Know "Success or Failure"

This section is short, but anyone writing scripts cannot avoid it.

Analogy: A single number for "Pass / Fail" in an exam. In the command-line world, every command leaves an "exit code" after running — a number, 0 represents success, non-0 represents some kind of problem occurred. It's not for you to see, it's for the "upper layer script" to see: the script relies on this number to judge "did this step succeed, should I continue downwards".

You can check the exit code of the command that just ran in the terminal like this:

bash
claude auth status
echo $?

echo $? prints the exit code of the previous command ($? is the variable in the shell that stores the "exit code of the last command").

The official documentation explicitly provides exit codes for commands, here are a few you'll find useful:

Command / SituationExit CodeMeaning
claude auth status logged in0Currently logged in
claude auth status not logged in1Currently not logged in
claude -p --max-turns N reached limitNon-0 (Error)Exceeded turn limit, exited with error
Pipe stdin exceeds 10MBNon-0Input too large, reports clear error and non-zero exit
claude daemon status supervisor not running1Background session management process not running

How is this actually used? For example, in CI if you want to "first confirm logged in, if not logged in directly fail the pipeline", rely on the exit code of claude auth status:

bash
# Not logged in (exit code non-zero) then error and exit, don't continue running down
claude auth status || { echo "Not logged in, terminating"; exit 1; }

The meaning of || is "if the previous command fails (exit code non-zero), then execute the following block". In a script that runs regularly every day, you can do this — first probe with claude auth status at the beginning. If the token has expired, the script immediately stops here and alerts, rather than foolishly running halfway down and realizing it's not logged in, wasting half a day for nothing.

Just remember this simple convention: 0 = succeed and move on, non-0 = something went wrong and should stop. Every command in Claude Code obeys it, look for this number when judging success or failure in your scripts.

💡 One-sentence summary: Exit codes are "report cards for scripts to see" — 0 success, non-0 problems; claude auth status uses 0/1 to report login status, --max-turns exceeding limits and pipes exceeding 10MB both exit non-zero, scripts rely on $? or || to catch it.


06 Flag Full Table: The Page for "Looking Up"

The previous sections explained the high-frequency ones thoroughly, this section is a fallback — organizing the flags you'll encounter daily in the official documentation into a single table, specifically for "looking up". Dozens of flags don't need to be memorized, just save it and flip to it anytime.

A reminder in official words: claude --help does not list every flag, so if a certain flag doesn't appear in --help, it doesn't mean it can't be used — rely on the official CLI reference documentation.

I've categorized them by "what they are used for", convenient for you to find by need:

Startup & Sessions

FlagShorthandWhat it does
--print-pDon't enter interactive, print result and exit (headless foundation)
--continue-cContinue most recent conversation in current directory
--resume-rResume specific session by ID / name, or popup list
--name-nGive session a display name, convenient for --resume <name> later
--fork-sessionCreate new session ID when resuming, don't reuse original (pair with -r/-c)
--session-idSpecify a session ID (must be a valid UUID)

Models & Permissions

FlagWhat it does
--modelWhich model to use this trip (alias sonnet/opus or full name), overrides default
--fallback-modelAutomatically fallback to specified model when default is overloaded/unavailable (effective in -p and background sessions, ignored in interactive)
--permission-modeWhich permission mode to start from (default/acceptEdits/plan/auto/dontAsk/bypassPermissions)
--allowedToolsTools allowed directly without prompting
--disallowedToolsDeny rules
--dangerously-skip-permissionsSkip all permission prompts (equivalent to --permission-mode bypassPermissions, use with caution)

Directories & Configuration

FlagWhat it does
--add-dirGive read/write rights to extra directories (only gives file access, doesn't load config there)
--settingsSpecify settings JSON file or inline JSON, overrides same keys for this session
--setting-sourcesWhich setting sources to load (user/project/local)
--mcp-configLoad MCP server from JSON file / string
--bareMinimal mode: skips auto-discovery of hooks/skills/plugins/MCP/memory/CLAUDE.md, faster startup

Headless Output & Control (Most only effective with -p)

FlagWhat it does
--output-formatOutput format: text (default) / json / stream-json
--input-formatInput format: text / stream-json
--max-turnsLimit max turns, error and exit if exceeded (unlimited by default)
--max-budget-usdStop if API cost exceeds this USD amount
--verboseDetailed logs, show complete turn-by-turn output
--append-system-promptAppend custom text to the end of default system prompt
--system-promptReplace entire default system prompt with custom text

Misc

FlagShorthandWhat it does
--version-vOutput version number
--ideIf exactly one IDE is available on startup, auto-connect
--debugTurn on debug mode, filterable by category (like "api,mcp")

This table covers the vast majority of flags you will use in the early stages. If you really want to check the complete set (there are dozens of obscure ones, like background sessions, agent teams, remote control related), go flip through the official CLI reference page — that is the "complete instruction manual", this section is a "quick reference for common ones".

💡 One-sentence summary: Flags are quickest to find categorized by "startup sessions / models permissions / directories configs / headless output / misc"; --help is incomplete, rely on official CLI reference; this table covers common ones, for obscure ones flip through the official complete set.


07 Hands-on: Connecting claude -p to the Command Line Pipe

Just looking at the table doesn't count as knowing it, you have to actually run headless once. The following set is completely done in the terminal, without entering any interactive interface — personally experience what it feels like for "Claude to be a command line part". Use minimal examples, not depending on your existing complex projects.

These steps require internet access and will consume a little quota (each -p call is a real request). If API is blocked domestically, turn on "magic internet" first.

Step 1: The most unadorned -p call

Just find any directory, and type in the terminal (not in a claude session):

bash
claude -p "Explain the core difference between git rebase and git merge in one sentence"

Expected: The terminal directly prints a sentence of answer and then exits, that chat interface never pops up throughout the process. Seeing the result flash by and the prompt return = headless mode ran successfully.

Step 2: Connect it to a pipe, feed data in

Create a small file as "input material", and pipe it to Claude:

bash
printf 'def add(a, b):\n    return a - b\n' > buggy.py
cat buggy.py | claude -p "There is a bug in this code, point it out in one sentence"

Expected: Claude reads the code fed in by the pipe, and replies something like "The function name is add but what it actually does is subtraction (a - b)". Seeing that it can answer based on "the content you fed in" = the pipe is connected — it didn't even use a tool to read the file, the material was fed into its mouth by cat.

Step 3: Want structured output, connect jq to extract fields

bash
claude -p "Introduce what Python language is in one sentence" --output-format json

Expected: What spits out this time isn't pure text, but a big chunk of JSON, containing fields like result (result text), session_id, total_cost_usd, etc. If you have jq installed on your machine, try this again to only extract the result:

bash
claude -p "Introduce Python in one sentence" --output-format json | jq -r '.result'

Expected: This time only that clean line of result text is printed out, the outer JSON is stripped off by jq. This is the standard way to grab "only that sentence of answer, no metadata" in a script.

Step 4: Use exit codes to judge success or failure

bash
claude auth status
echo $?

Expected: If you are already logged in, echo $? prints 0; if not logged in, it prints 1. This number is the basis for the script to judge "should I continue downwards" — that line claude auth status || ... in section 05 catches it.

By running through these four steps, you've personally walked through the complete headless chain of "single call → pipe feeding → structured output connecting jq → exit code judgment". In the future, stuffing Claude into any script, CI, or scheduled task is essentially a permutation and combination of these parts.

💡 One-sentence summary: Walk through headless with four hands-on steps — bare -p for result, pipe cat | claude -p for feeding material, --output-format json | jq for extracting fields, auth status + $? for judging success or failure; these four pieces pieced together are the foundation of all automation.


08 Summary

This article completely spread out that line of claude you type every day — upgrading from "only knowing how to type a bare claude to enter the interface" to "knowing everything about commands, flags, pipes, and exit codes".

Stringing the core points together for review:

What you want to doUse whatKey points
Distinguish commands & flagsCommands are sub-actions, flags are checkboxesupdate/mcp are commands, -p/--model are flags
Start / Resumeclaude / -c / -r-c recognizes recent, -r resumes by name, cures session amnesia
Get result without interactive-p (--print)Headless foundation, for scripts and pipes
Temp switch model / Set permissions--model / --permission-modeOverrides default settings, only for this trip
Stuff it into command linePipe + --output-format json + jqcat ... | claude -p ... | jq to string pipelines
Script judge success or failureExit code0 success, non-0 trouble, caught by $? or ||
Look up a certain flagSection 06 quick reference / Official complete set--help is incomplete, rely on official CLI reference

You should now be able to: Looking at any line of claude xxx --yyy, clearly break down "which is the command, which is the flag, and what they each do"; know whether to use -c or -r when wanting to resume a previous conversation; when you have to stuff Claude into a script, know how to use -p paired with pipes and --output-format json, and also know how to use exit codes to judge if this step succeeded; when encountering a flag you haven't seen before, know which table to check in, and also know --help is unreliable and you have to flip through the official complete set. This set of command-line skills is the watershed for you to truly turn Claude Code from "a chat window" into "an orchestrable part in your development workflow".

The person at the beginning who only typed claude, after learning -p plus pipes, could write the few checks they ran manually every day into a script — that feeling is like suddenly inviting Claude from the "passenger seat" onto the "assembly line". This article was exactly intended to give you that moment too.


Next article 35 "Control and Modes" — I repeatedly mentioned in this article that --permission-mode can select tiers like plan, acceptEdits, bypassPermissions, but I've been holding back on explaining what exact temper each tier has, how many times it asks you before acting, and what scenario should switch to which tier. The next article will specifically break down these modes, and thoroughly explain how to easily switch them with shortcut keys in a session. Think about it: similarly asking Claude to modify a bunch of files, "asking you once for every file modified" versus "modifying everything head down before showing you" can make a difference of ten streets in efficiency and sense of security — grasping this balance, see you in the next article.