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
claudeyou 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
jqto 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:
claude update
claude -p "explain this function" --model sonnet- First line:
claudeis the program,updateis the command (a sub-action, exits after running). - Second line:
claudeisn't followed by a command, directly entering the session logic;-pand--modelare both flags, and"explain this function"after-pis 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 udpatewill printDid 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:
# 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:
# 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:
# 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:
# 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 statusThe 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 (-crecognizes recent,-rresumes by name), Maintenance accounts (update/install/auth);-cand-rare 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.
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:
claude --model sonnet
claude --model opus
claude --model claude-sonnet-4-6 # Can also write the full nameYou 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:
claude --permission-mode planThe options given officially are these:
Accepts
default,acceptEdits,plan,auto,dontAsk, orbypassPermissions. OverridesdefaultModein 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:
claude --dangerously-skip-permissionsAdd 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:
claude --add-dir ../apps ../libTypical 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:
claude -p "summarize this project" --output-format jsonThree 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):
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:
# 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 —
-poutputs results without entering interactive,--modelswitches models,--permission-modesets permission tightness,--add-dirlooks at more directories,--output-format jsongets structured results,--allowedToolspre-allows tools; if you're afraid scripts will go out of control, add--max-turns/--max-budget-usdas 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:
cat build-error.txt | claude -p 'concisely explain the root cause of this build error' > output.txtThis 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:
{
"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):
# 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:
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:
gh pr diff "$1" | claude -p \
--append-system-prompt "You are a security engineer. Review for vulnerabilities." \
--output-format jsonYou 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:
| Dimension | Interactive 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 permissions | Stops to ask you before acting | Set in advance via --allowedTools / --permission-mode |
| Typical scenarios | Daily dev, conversational work | CI, batch processing, acting as linter, stuffing into scripts |
💡 One-sentence summary:
claude -pturns Claude into a command-line part that can connect to pipes —cat ... | claude -p ... > out.txtfor stringing pipelines,--output-format jsonwithjqto grab fields,--baremakes 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:
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 / Situation | Exit Code | Meaning |
|---|---|---|
claude auth status logged in | 0 | Currently logged in |
claude auth status not logged in | 1 | Currently not logged in |
claude -p --max-turns N reached limit | Non-0 (Error) | Exceeded turn limit, exited with error |
| Pipe stdin exceeds 10MB | Non-0 | Input too large, reports clear error and non-zero exit |
claude daemon status supervisor not running | 1 | Background 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:
# 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" —
0success, non-0problems;claude auth statususes0/1to report login status,--max-turnsexceeding 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 --helpdoes 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
| Flag | Shorthand | What it does |
|---|---|---|
--print | -p | Don't enter interactive, print result and exit (headless foundation) |
--continue | -c | Continue most recent conversation in current directory |
--resume | -r | Resume specific session by ID / name, or popup list |
--name | -n | Give session a display name, convenient for --resume <name> later |
--fork-session | — | Create new session ID when resuming, don't reuse original (pair with -r/-c) |
--session-id | — | Specify a session ID (must be a valid UUID) |
Models & Permissions
| Flag | What it does |
|---|---|
--model | Which model to use this trip (alias sonnet/opus or full name), overrides default |
--fallback-model | Automatically fallback to specified model when default is overloaded/unavailable (effective in -p and background sessions, ignored in interactive) |
--permission-mode | Which permission mode to start from (default/acceptEdits/plan/auto/dontAsk/bypassPermissions) |
--allowedTools | Tools allowed directly without prompting |
--disallowedTools | Deny rules |
--dangerously-skip-permissions | Skip all permission prompts (equivalent to --permission-mode bypassPermissions, use with caution) |
Directories & Configuration
| Flag | What it does |
|---|---|
--add-dir | Give read/write rights to extra directories (only gives file access, doesn't load config there) |
--settings | Specify settings JSON file or inline JSON, overrides same keys for this session |
--setting-sources | Which setting sources to load (user/project/local) |
--mcp-config | Load MCP server from JSON file / string |
--bare | Minimal mode: skips auto-discovery of hooks/skills/plugins/MCP/memory/CLAUDE.md, faster startup |
Headless Output & Control (Most only effective with -p)
| Flag | What it does |
|---|---|
--output-format | Output format: text (default) / json / stream-json |
--input-format | Input format: text / stream-json |
--max-turns | Limit max turns, error and exit if exceeded (unlimited by default) |
--max-budget-usd | Stop if API cost exceeds this USD amount |
--verbose | Detailed logs, show complete turn-by-turn output |
--append-system-prompt | Append custom text to the end of default system prompt |
--system-prompt | Replace entire default system prompt with custom text |
Misc
| Flag | Shorthand | What it does |
|---|---|---|
--version | -v | Output version number |
--ide | — | If exactly one IDE is available on startup, auto-connect |
--debug | — | Turn 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";
--helpis 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
-pcall 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):
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:
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
claude -p "Introduce what Python language is in one sentence" --output-format jsonExpected: 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:
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
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
-pfor result, pipecat | claude -pfor feeding material,--output-format json | jqfor 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 do | Use what | Key points |
|---|---|---|
| Distinguish commands & flags | Commands are sub-actions, flags are checkboxes | update/mcp are commands, -p/--model are flags |
| Start / Resume | claude / -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-mode | Overrides default settings, only for this trip |
| Stuff it into command line | Pipe + --output-format json + jq | cat ... | claude -p ... | jq to string pipelines |
| Script judge success or failure | Exit code | 0 success, non-0 trouble, caught by $? or || |
| Look up a certain flag | Section 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.