Claude Code — commands, settings, flags
Hi!
This is a reference. Not a story about how to work with the agent properly — I have a separate article for that — but a list: what you can type, what you can put in the settings, what each of those does and how it looks in practice.
Current as of August 2026. The lists of commands, keys and flags were taken off build 2.1.251, and whatever could be checked by running it was checked on 2.1.252. For a technical article the version matters more than usual: between adjacent builds commands vanish, get renamed and swap places. If you're on a different version, /help and claude --help are always right, and I'm only right as of the time of writing.
The console output in the examples is real: it was either taken off a running build or from the official documentation. Where I couldn't find real output, there is none at all, and what happens after a command is described in words — there will be no invented screens in this article.
Three places where commands are entered
Before you page through the tables, it helps to understand that there are three surfaces and they don't overlap.
Slash commands are typed inside a running session, with a / at the start of the line. They drive the conversation: switch the model, compact the context, roll back edits, kick off a review. In the terminal they do nothing.
settings.json is a file on disk. It defines how Claude Code starts up: which model, what permissions the tools get, which hooks, what to show in the status line. A large share of the settings exist only here and have no command equivalent.
Terminal claude commands are typed in an ordinary shell, before a session or alongside it: installation, authentication, MCP servers, plugins, background agents, non-interactive runs for scripts.
The split isn't decorative. Half of the "why isn't this working" questions come down to someone typing /model in the terminal or --effort in the settings file. There is, though, one pleasant exception: in non-interactive mode claude -p slash commands do work inside the prompt text — more on that separately below.
Slash commands
Typed inside a running session, with a / at the start of the line. For every command below everything is gathered in one place: the arguments with all their values, the fine print and examples.
Markers: [Skill] — a built-in skill, that is, a ready-made prompt scenario; [Workflow] — a built-in multi-agent workflow; [extra cost] — paid for in credits separately from the subscription; [not on every plan] — availability depends on the plan, the organization or the provider; [undocumented] — present in the build, but not described in any public source.
About the examples. The blocks show what you actually type, with real arguments, not the bare command name. Output is shown where I could take it off a running build or from the official documentation; it's in English, because that's how it prints. Where there was no trustworthy output, there is none here either, and what will appear on screen and what you'll have to choose between is told in words in the command's description. There will be no invented screens in this article.
Commands that are disabled or removed entirely in this build get no sections of their own — they're collected in a table at the end of this section.
Sessions and the conversation
The four commands in this group do similar things, and people mix them up constantly. The difference is what gets copied and where the result shows up:
| Command | What gets copied | Where the work happens | Where the result lands |
|---|---|---|---|
/branch | the whole conversation | right here, you carry on in the branch | in the branch; the original is left untouched |
/fork | the whole conversation | in a background session, in parallel with you | in a separate session you attach to later |
/subtask | the whole context, one-off | in a subagent | back into this same conversation, as a single message |
/background | nothing gets copied | this very session moves to the background | the same one, when you come back to it |
/clear [name]
Start a new conversation with a clean context. Aliases: /reset, /new. You reach for it when moving on to a different task: the old context stops helping and starts getting in the way — the model keeps dragging details of the previous job into its answers.
The old conversation isn't deleted — it stays on disk and opens through /resume. The optional argument labels it in the list: without a label, a week later you'll be staring at a dozen nameless rows.
If you cleared by accident, it can be undone within the same process: the /rewind menu has an entry for the previous session, and it looks like /resume <id> (previous session).
Worth remembering the price too: /clear costs nothing, whereas /compact is a big request carrying the whole context. If the conversation is no longer needed, clearing is cheaper than compacting by the entire window.
/clear # a new conversation with a clean context/clear queue experiment, didn't pan out # same, but the old conversation is labelled with this phrase/resume [id or search phrase]
Go back to an earlier conversation. Alias: /continue. You need it when work got interrupted and you'd rather not start from scratch but keep all the context you'd built up — or when you need to dig up an old discussion to recall where you left off.
| What you passed | What happens |
|---|---|
| nothing | An interactive list of this folder's recent sessions opens |
| a session id | It opens straight away, with no list |
| arbitrary text | A search across the contents of your conversations; you pick from the matches |
The list is tied to the working folder: a conversation from another project won't appear in it. By id, though, a session opens from any folder on the machine — before version 2.1.223 the search covered only the current project and its worktrees. That's handy for scripts: grab session_id out of claude -p --output-format json and carry on from anywhere.
Transcripts are cleaned up according to cleanupPeriodDays, thirty days by default. If you expect to come back to old conversations, raise the value in advance — there's nowhere to restore deleted ones from.
Terminal equivalents: claude -c continues the folder's last conversation with no picker (skipping background sessions), claude -r opens the same picker before the session starts, claude -r <id> --fork-session continues an old conversation under a new id, leaving the original untouched.
In the list you pick which past conversation to continue: each row is a separate session of this folder, with its own label and time. The one you pick opens in full, with all the messages and context, and you carry on writing into it as if nothing had happened.
/resume # pick from this folder's recent conversations/resume 8f3c1d2e-4b5a-... # open straight away by id, no picker/resume deadlock in pool # search by content; pick from the matching conversations/branch [name]
Branch the conversation off the current point; the original is kept whole.
This is "save before the boss fight". You're at a point where it's unclear which of two approaches is better; you branch off, try the first, and if it didn't work out you go back to the original through /resume and try the second, without dragging the failed attempt along in the context. The name is optional, but with one it's easier to find the right branch in the list later.
After the command you end up in the branch and write on inside it; the original conversation stays intact and opens through /resume.
/branch # branch off from the current point/branch try-via-the-queue # same, with the branch labelled with this name/fork [task]
Copy the conversation into a background session that works on the task in parallel with you.
This is "let somebody else deal with that while I get on with mine". The copy inherits all the context you've built up; you collect the result by attaching to it with claude attach or from the claude agents screen. Starting with 2.1.221 the copy is also told to create its own git worktree before touching code — so two agents don't step on each other's toes in one tree.
Careful with advice written elsewhere. In versions from 2.1.161 through 2.1.211, what is now called /subtask was called /fork, and the names swapped places in 2.1.212. An article or a script written before that means exactly the opposite. Plus one special case: if the agents screen is disabled, /fork falls back to the old behaviour and acts as a subagent.
Mind the spend as well: the copy is a full second session with its own context, and while it runs your limit is being burned by both at once.
The copy is created immediately and gets its own id — which is what you'll need to attach to it later. Given a task it gets to work at once; without one it simply waits for instructions.
/fork put together release notes from the commits since the last tag # the copy works in parallel with you/fork # the copy waits for instructions/subtask <task>
Send off a subagent carrying your context; the result comes back into this same conversation.
This is "go and have a look, then come back". The difference from /fork is fundamental: the noisy part of the work — reading twenty files, walls of output — stays in the subagent's context, and only the answer reaches you. The main way to keep recon from clogging your main context.
Requires version 2.1.212; before that this command was called /fork. Unavailable when the agents screen is disabled.
What it saves is your context window, not your spend: the subagent reads and thinks on your own limit, it just leaves no litter in the conversation.
The conversation doesn't stall: while the subagent reads you carry on writing, and when it finishes a single message from it appears in the thread with the result.
/subtask find every call to this method # recon without littering the context/subtask read a month of migrations and tell me what changed in the order schema # same for a long read/background [prompt]
Move the current session into the background and free up the terminal. Alias: /bg.
Nothing gets copied — this very session goes to the background and the work carries on. With an argument you also hand it a task for the road. To come back later — claude attach or the claude agents screen; to stop it — /stop or claude stop <id>. You reach for it when the task is long and you need the terminal right now.
The terminal is freed immediately, while the session lives on in the background under its own id — and that's what you use to get back to it.
/background # go to the background and free the terminal/bg catch up with the build and fix the linter # same, plus a task for the road/rename [name]
Rename the session. Alias: /name [undocumented]. The point is purely practical: once you have a lot of open and background conversations, you tell them apart by their label, not by their id.
The name is visible in the input line, in the /resume list and in the terminal tab's title. Without an argument it's generated from the topic of the conversation.
Three things happen to a name you type in: control and invisible characters are replaced with spaces, the length is trimmed to two hundred characters, and if nothing is left after the cleanup the name is rejected as empty. If that name is already taken by another live session on this machine, a variant of it is applied — not an error, the name just ends up slightly different.
The terminal title changes if terminalTitleFromRename is on (it is by default); to forbid touching the title altogether, use the CLAUDE_CODE_DISABLE_TERMINAL_TITLE variable.
/rename # the name is made up from the topic of the conversation/rename payment refactor # the name is set by hand/cd <path>
Move the session to a different working folder. Handy when the work has moved to a neighbouring service or repository and you don't want to abandon the conversation.
The new folder's settings, hooks, MCP servers, skills and agents take effect immediately rather than after a restart, and the new folder's env block is layered over the old one. That's what makes /cd different from /add-dir, which grants access to files but not to configuration.
/cd ../backend # move to the neighbouring repository along with its configuration/recap
Squeeze the whole session into a one-line summary — a quick way to recall what it was about. Useful after a break and in a long conversation where the beginning has scrolled off the screen. The context isn't touched: this is just a short digest in a reply, not the compaction of the conversation that /compact does.
/recap # what this conversation is about and what it arrived at/btw [question]
Ask a short side question without polluting the main context: the answer isn't mixed into the work that follows. This is for "hang on, what is this thing even called" in the middle of a task — so that ten messages later the model isn't building its reasoning around a question you asked in passing.
With no question it opens your past side questions so you can page through the answers; before version 2.1.212 the question was mandatory.
/btw how is grpc-web different from grpc # the answer is for you, but bypasses the rest of the context/btw # go back to past side questions/export [file]
Dump the conversation to a file or to the clipboard. Usually what you want in order to attach the exchange to a ticket, forward it to a colleague, or save an analysis you'll come back to.
With no argument the whole conversation goes to the clipboard; with an argument it's written to a file; ~ is expanded. The format is text, with the roles marked up: it's a transcript for a human or for handing to another tool, not a machine format for importing back.
/export # the whole conversation to the clipboard/export ~/logs/session.md # same, but to a file/copy [N]
Copy a single reply to the clipboard: with no argument the last one, with a number the Nth from the end. You need it when you want to lift a chunk out of a big answer into an editor or a ticket and don't fancy selecting half a screen with the mouse.
What gets counted is assistant replies, not lines on the screen, so /copy 2 means "the reply before last". Little known: if the reply contains code blocks, a picker opens — you can take a single block instead of the whole message. And right there the w key writes the selection to a file instead of the clipboard; over SSH, where the clipboard is useless, that's the only thing that works.
The choice in that list is between the whole message and any single code block from it; the selection goes straight to the clipboard, or with w to a file.
/copy # the last reply to the clipboard/copy 2 # the one before last; if it has code, you'll be asked to pick a block first/stop
Stop the current background session. The transcript and the worktree are kept. You need it when the background work went off the rails or is no longer wanted: the session really does stop working, rather than merely detaching as with /exit. From outside, claude stop <id> does the same thing.
/stop # stop the background session; the transcript and the worktree stay/exit
Quit the CLI. Alias: /quit. In a background session it detaches, and the session itself carries on working.
/exit # quit the CLI; in a background session it only detachesContext and memory
/context [all]
Shows what's filling the context as a colored grid, plus hints about what you could unload. The all argument expands the details: exactly which files, and how much each takes. Worth reaching for when the session has grown noticeably heavy or is about to slide into auto-compaction: the command shows who exactly ate the window, and the cure depends on that. Don't confuse it with /usage: that one is about your plan's limits, this one is about the current session's window.
Every cell of the grid is a slice of the context window, colored by source. The point isn't decoration: different sources behave differently, and each is cured differently.
| What it shows | Where it comes from | How to shrink it |
|---|---|---|
| System prompt | Claude Code itself | almost nothing does; --bare and --restricted trim it |
| Tool descriptions | built-ins plus MCP servers | turn off the servers you don't need |
| Skill listing | descriptions of every available skill | skillOverrides, skillListingBudgetFraction |
| Memory files | CLAUDE.md and auto-memory | shorten them, or exclude via claudeMdExcludes |
| Conversation history | your messages and the replies | /compact, /clear |
| Files read and command output | tools | /clear, and hand the exploration to /subtask |
The practical value is in all: there's almost always a file or two, or one chatty MCP server, that ate more than all the useful work put together.
Then comes the fork. History bloated — /compact. File reads bloated — /clear and start over. Tool and skill descriptions bloated — that's cured by settings, not by commands: the next session would start out exactly as swollen.
/context # what's taking up the context right now
Context UsageOpus 5 (1M context)claude-opus-5[1m]138.8k/1m tokens (14%)
Estimated usage by category System prompt: 4.4k tokens (0.4%) System tools: 21k tokens (2.1%) MCP tools: 265 tokens (0.0%) Memory files: 3.2k tokens (0.3%) Skills: 6.2k tokens (0.6%) Messages: 104.2k tokens (10.4%) Free space: 860.7k (86.1%)
MCP tools · /mcp (loaded on-demand)└ 126 tools · 265 tokens
Memory files · /memory└ 1 file · 3.2k tokens
Skills · /skills└ 48 skills · 6.2k tokens
/context all to expand
Suggestions ℹ File reads using 76.1k tokens (8%) → save ~22.8k If you are re-reading files, consider referencing earlier reads. Use offset/limit for large files.
/context all # the same, broken down file by fileThe output above is a verbatim snapshot of a real session on Opus 5 with a million-token window.
/compact [instructions]
Compacts the conversation history into a summary, freeing up room. The argument isn't a flag and isn't a filter — it's an instruction to whoever writes the summary: what to pay attention to, what must not be lost. You need it when the window is nearly full but it's too early to drop the conversation: work continues from the same place, but from here on it leans on a retelling.
Compaction is loss. The summary is written by the model, it's inevitably shorter than the original, and anything left out of the emphasis is reproduced approximately or disappears. A thought-out argument isn't politeness — it's how you control what exactly you agree to lose.
The command asks nothing, folds up the history and reports in a single line; the summary itself is collapsed by default and expands with a separate keypress. With an argument nothing changes on the outside — the difference is only in what the summary held on to.
Compaction is itself an expensive request: the entire context goes into it. /clear costs nothing. If you no longer need the conversation, the second command is cheaper than the first by a whole window.
The threshold at which the context compacts itself is controlled by /autocompact.
/compact # compact the history however it comes out
⎿ Compacted (ctrl+o to see full summary)
/compact keep the DB schema decisions # compact, but don't lose this thread
/compact keep only what concerns the payment moduleThe report line is quoted verbatim, captured on build 2.1.220.
/autocompact [auto|<tokens>]
Sets how full the context has to get before it starts compacting itself. The command appeared in 2.1.221. The threshold is a trade-off: the higher it is, the longer the full history survives, but the closer you are to the ceiling of the window; the lower it is, the more often the conversation turns into a retelling. You reach for the command when compaction fires at the wrong moment — too early and it carries off what you needed, too late and it slams into the ceiling.
| Argument | What it does |
|---|---|
| no argument | Show the current value |
auto | The threshold is picked automatically |
| a number from 100000 to 1000000 | Compact once that many tokens are reached |
Values outside the range are rejected. The persistent equivalent is the autoCompactWindow key; auto-compaction is switched off entirely with autoCompactEnabled: false, and there's a launch flag --autocompact taking the same values. A separate setting, precomputeCompactionEnabled, prepares the compaction ahead of time while ordinary work goes on — so when the threshold is reached the pause is shorter; it only works with auto-compaction enabled.
The command opens no dialog: with no argument it just shows the threshold in force, with an argument it accepts a new one or refuses if the number falls outside the allowed range.
/autocompact # check the current threshold
/autocompact auto # let it pick for itself
/autocompact 400000 # compact on reaching 400k tokens/memory
Opens the memory files for editing and lets you manage them. Memory is mixed into the context of every session, so it's both the main lever on the agent's behavior and a standing tax on the window: everything sitting there is paid for on every single request. First you pick which file to edit — the project one or your personal one — and it opens in the editor.
What exactly gets loaded out of them is shown by /context, and /doctor knows how to tidy them up: it clears out duplicates, moves rarely needed material into separate files loaded on demand, and cuts whatever the agent would work out from the code anyway.
/memory # open the memory files for editing/init
Creates CLAUDE.md: the agent looks the repository over and describes its structure and commands. [Skill] Worth reaching for on a repository the agent hasn't worked with yet; an already existing file is usually faster to fix by hand through /memory than to regenerate.
CLAUDE.md is an instructions file that gets mixed into the context of every session.
On success the command prints nothing. The documentation suggests checking the result in the next session: call /context and make sure CLAUDE.md has shown up under Memory files.
A little-known variable: CLAUDE_CODE_NEW_INIT=1 turns on an interactive version that walks you through not only the project instructions but skills, hooks and personal memory files as well. And if the folder turns out to hold another coding agent's configuration that /import knows how to carry over, you'll be offered to take it.
/init # generate CLAUDE.md from the repositoryCLAUDE_CODE_NEW_INIT=1 claude # interactive /init with skills and hooks/add-dir <path>
Adds another working directory so the agent can see files outside the project folder. You need it when the work doesn't fit into one repository: a neighboring service, a shared schema, an extracted library — without this the agent simply won't read them.
An important subtlety: it grants access to files, not to configuration — that folder's hooks and settings are not picked up. The single exception is skills and commands: those are taken from the added folder. Moving the session into another folder wholesale, along with its settings and hooks, is /cd, not /add-dir.
/add-dir ../shared-protocol # let the agent into a neighboring repo/rewind
Rolls the code and/or the conversation back to a checkpoint, or compacts a chunk of the conversation. Aliases: /checkpoint, /undo. You need it when a run of edits went the wrong way and untangling what exactly the agent changed takes longer than stepping back.
The first thing to know: the command doesn't always work. Copies of files are taken before an edit only if fileCheckpointingEnabled is on. Off — and there's nothing to restore from.
Second: the menu doesn't open only from the command. A double Esc on an empty input line does the same thing. If the line has text in it, a double Esc clears the text — so clear the line first.
The menu has six items, and half of them aren't about rolling back:
| Item | What it does |
|---|---|
| Restore code and conversation | A full return to the state at the checkpoint |
| Restore conversation | The history comes back, the files stay as they are |
| Restore code | The files come back, the conversation stays whole |
| Compact from here | Compact the conversation from the chosen point onward |
| Compact up to this point | Compact everything that came before the chosen point |
| Cancel | Do nothing |
The two compaction items are essentially a targeted /compact: free up context, but from one specific chunk of the conversation rather than all of it. The line has an optional field for saying what to pay attention to while compacting, and a marker is left where the compacted part was.
The choice here is two-step: first the point you're returning to, then one of six actions on it. Of the rollbacks, the one you want most often is "restore code": the edits went astray, but the discussion they grew out of is valuable and it would be silly to lose it.
Limits worth knowing before you need them. The last hundred checkpoints are kept, and they're deleted along with the session after thirty days — the same cleanupPeriodDays. Not restored: whatever the shell commands you ran did, most subagent edits, changes made from outside, and anything living behind symbolic and hard links. Which means a database wiped by a migration won't come back, a git reset won't be undone, installed packages will stay. This is an undo for recent edits, not a version control system and not a substitute for commits.
Restoring code isn't always complete: if a file's type or directory changed since the checkpoint, it gets skipped, and the session tells you separately how many files it left alone.
/rewind # the rollback and compaction menuModel and performance
/model [model]
Switches the model and remembers the choice. [extra cost] it isn't the command itself that costs, it's part of what you can pick with it: on a number of plans, Fable 5 and the million-token-context variants are charged against credits on top of your subscription, and without credits enabled those rows in the list don't work. With no argument it opens the list of what's available. You reach for the command when the character of the work changes: a heavy investigation is worth running on the strongest model, while a stream of small edits belongs on a fast, cheap one.
| What you passed | What happens |
|---|---|
| nothing | The list of available models opens |
a family alias — opus, sonnet, haiku, fable | The current model of that family is taken |
default | The default model for your plan |
best | Fable 5 where the organization has access, otherwise the newest Opus |
opusplan | Planning on Opus, execution on Sonnet |
opus[1m], sonnet[1m] | The same model with a million-token context window |
a version prefix, e.g. opus-5 | Resolves to a specific model |
| a full identifier | Exactly that one is taken |
The choice is remembered and survives a restart — that's how /model differs from the ANTHROPIC_DEFAULT_MODEL variable, which it overrides.
The picture as of August 2026. The current models are Opus 5, Sonnet 5, Fable 5 and Haiku 4.5. There is no Haiku 5: the haiku alias still points at 4.5, and that regularly misleads people reading examples with fallbackModel.
What stands behind an alias depends on the provider, and that's a non-obvious detail for anyone working through a cloud. On Anthropic's own API sonnet is Sonnet 5, on Amazon Bedrock and Google Cloud it's Sonnet 4.5, and on Microsoft Foundry opus is Opus 4.6 outright. The very same config gives you different models on two providers.
All of this is configured in three ways. What the aliases stand for — through ANTHROPIC_DEFAULT_OPUS_MODEL and its relatives (there's no such variable for best). The picker list itself — through the modelPicker key: you append your own labeled rows there, Bedrock and Vertex identifiers included, and replaceBuiltInOptions replaces the built-in list entirely. Over the top of all that sits the corporate availableModels; since version 2.1.205 a family alias isn't rejected by it but resolves to the newest permitted model.
fallbackModel lives on its own — a list of models Claude Code will switch to by itself if the main one is overloaded. It doesn't change your choice, it's insurance for however long something is unavailable.
What exactly gets billed separately. For Fable 5, whether it draws on credits depends on the plan and on the type of seat in the organization; where it does, that row in the list carries a note that credits are required, and before the first such request Claude Code asks for confirmation once. In non-interactive mode (-p) and through the Agent SDK there's no such question — the charge happens silently. With the million-token window the picture is different: on Sonnet 4.6 it requires credits on any subscription plan, Max included; on Opus only on Pro, while on Max, Team and Enterprise it's part of the plan with no configuration at all. On Sonnet 5 through Anthropic's own API the million-token window is always on and needs no credits.
In the list you choose between families and specific versions: you can see what's available on your plan and which rows carry a credits requirement. With an argument the list doesn't open — the model changes right away. The chosen model applies to the current session and stays chosen next time.
/model # pick from the available list/model opus # by alias/model opusplan # plan on Opus, execute on Sonnet/effort [level|auto|status]
The effort level sets how much the model thinks about a turn. It isn't the same as picking a model: the model decides who thinks, the effort decides how much. The practical point is trading time and token spend for the quality of the turn: on an obvious edit, deep reasoning only slows things down, while on a tangled defect, skimping on it ends in a wrong diagnosis.
| Value | What happens | When it makes sense |
|---|---|---|
low | Minimal reasoning, an answer almost immediately | Mechanical edits, renames, questions with an obvious answer |
medium | The normal mode | Everyday work |
high | Noticeably more reasoning before acting | Tasks where a mistake costs more than the wait |
xhigh | The most reasoning available in normal mode | Design work, digging into a tangled defect |
max | The same, with the emphasis on thoroughness | Rarely; before irreversible changes |
ultracode | xhigh plus permanent workflow orchestration | Large decomposable jobs where cost isn't the priority |
auto | The level is matched to the task | The default, if you haven't intervened |
status | Changes nothing, shows the current level | — |
Four non-obvious things.
max can't be saved in the settings. The effortLevel key accepts values only up to xhigh. Maximum is set for a session — by the command or the --effort max flag — and deliberately doesn't stay on forever. ultracode works the same way: the command and the flag work, but it isn't among the values listed in the schema; permanently it's switched on by a separate boolean key, ultracode.
The level is remembered per model. Since version 2.1.248 every model has its own saved level: switch to another one and you get its setting, not your last one.
Other commands override it. /code-review high raises the effort for that turn, /code-review low lowers it, even if the session was running on xhigh.
The word ultracode works right inside the prompt text — by default that's enough to turn orchestration on for one turn; workflowKeywordTriggerEnabled is what governs it. If it fired by accident, it's cancelled on the spot with Alt+W (Option+W on macOS). To start out with it: claude --effort ultracode.
A word on what ultracode spends. It isn't billed on top of your plan, but one request of yours unfolds into several workflows in a row, and every workflow spawns agents — your plan's limit melts noticeably faster than in an ordinary session. The large-run warning Claude Code shows when more than 25 agents are planned or the forecast passes a million and a half tokens is not displayed in ultracode mode: by turning it on you've already agreed to large runs. On the Pro plan, workflow orchestration first has to be enabled in /config.
One more thing, fixed in 2.1.251, an edge case that's easy to hit: Opus 5 refused to work with xhigh and max when thinking was turned off. Now in that combination the effort is simply sent as high.
With an argument the level switches on the spot, for the current session; status changes nothing and only shows the level in force.
/effort status # what the level is right now/effort low # cheap and fast/effort ultracode # xhigh plus permanent workflow orchestration/fast [on|off]
Fast mode: the same model, but with accelerated output. [extra cost] it has no free allowance — the mode is always paid for with credits on top of the subscription, even if your plan's limit hasn't been used up yet, and until credits are enabled the command will tell you they're needed and switch nothing. You reach for it where waiting costs more than paying: conversational debugging, a long run of small edits, a live demo. It isn't a different model and isn't a different effort level — it's an output mode.
The price of the speed-up on Opus 5 and Opus 4.8 is 10 dollars per million input tokens and 50 per million output, the same across the whole million-token window; that's more than the usual Opus rates. There's an unpleasant subtlety about switching it on partway through a conversation: the entire accumulated context is recharged at the full fast-mode input price, so it's cheaper to turn it on at the start of a session than on the hundredth turn. If credits run out mid-work nothing breaks — Claude Code retries the rejected requests at normal speed and normal price. In the Claude Console there are no credits at all: the organization pays for the tokens along with the rest of its API spend. On Amazon Bedrock, Claude Platform on AWS, Google Cloud Agent Platform and Microsoft Foundry the mode doesn't exist.
The neighboring settings keys: fastMode turns it on permanently, while fastModePerSessionOptIn makes every session start without it, even if you switched it on last time.
/fast on # accelerated output/fast off # back to normal/brief
"Brief only" mode: maximally compressed answers with no expanded explanations. The command takes no arguments. Useful when you're driving the work yourself and what you want from the agent is a result or a short fact, not a walkthrough with examples. It affects neither the amount of actual work nor the depth of reasoning — only what gets printed to you is shortened; depth is /effort's job.
/brief # answer as briefly as possible/advisor [model|off]
The advisor: a stronger model prompts the main agent at key moments. [not on all plans] it needs access to Anthropic's own API — by subscription or through the Console; on Amazon Bedrock, Claude Platform on AWS, Google Cloud Agent Platform and Microsoft Foundry there is no advisor, and it requires feature-flag fetching to be enabled. The point is not to pay for a strong model across the whole session, but to call it in at specific spots. The feature is experimental, and it's too early to run real work on it.
The second model doesn't step in constantly, only at key points — when the main agent is making a decision where a mistake is costly. The argument is an alias or a full model identifier; off turns it off. With no argument a picker opens. There's also a launch flag, --advisor <model>, which, by the way, isn't in the output of claude --help.
The advisor's usage comes out of your ordinary plan limit — with one exception: if Fable 5 is appointed advisor, its work is paid for with credits wherever ordinary Fable 5 usage is paid for with credits. Until you've consented to that charge through /model fable, Claude Code simply won't appoint Fable as advisor.
With no argument the same model list opens, but what you're choosing in it isn't the working model, it's the helper: the main model stays as it was, and the one you pick is attached on top of it.
/advisor # pick an advisor from the list/advisor opus # hints from Opus/advisor off # turn the advisor off/plan [open|share|description]
Planning mode: the agent reads, analyzes and proposes a plan, but changes nothing — file edits and dangerous commands are unavailable. The way out is accepting the plan; after that the session returns to normal mode and starts carrying it out. You want it where the cost of a misunderstood task is higher than the time spent agreeing on it: before a big rework, in unfamiliar code, when an edit spreads across a dozen files.
| Argument | What it does |
|---|---|
| nothing | Just enter planning mode |
| the task text | Enter and start planning it right away |
open | Open the file of the session's current plan |
share | Publish the plan as a separate page you can share |
Plan files live in ~/.claude/plans/ unless plansDirectory is set — people use it to move them into the project repository, so the plan is discussed and versioned along with the code.
The plan-acceptance dialog has a "clear context" option: the plan stays, and all the exploration it was built on is thrown away. It only shows up with showClearContextOnPlanAccept, which is off by default, and on long tasks it's one of the most useful settings — execution starts with a clean window.
The mode is available right from the start too: claude --permission-mode plan. And it's worth knowing separately that auto mode is in effect by default inside planning as well; that's switched off with the useAutoModeDuringPlan key.
The finished plan is shown together with the acceptance dialog, and there you pick among three options. "Yes, and use auto mode" — accept and continue in auto mode; where auto mode isn't available the same row reads "Yes, auto-accept edits", and in a session started with permissions bypassed it reads "Yes, and switch to BYPASS PERMISSIONS (no further prompts) for this session". "Yes, manually approve edits" — accept, but confirm every edit by hand. "No, keep planning" — stay in planning and say what to fix. That's how the documentation describes it.
/plan # enter planning mode/plan split payments into a service # enter with the task right away/plan share # share the plan/goal [condition|clear]
Sets the condition under which the work counts as finished; the agent keeps going by itself until it's met, instead of stopping after every turn. That changes the rhythm: the turn doesn't come back to you at every step, and you only have to step in if something went off the rails. It makes sense on long mechanical work — pushing a build through to green, carrying the same edit across the whole project.
| Argument | What it does |
|---|---|
| the condition text | Set the goal |
clear, stop, off, reset, none, cancel | Drop the active goal — any of the six words |
| nothing | Show the current goal, or the last one reached |
The condition has to be checkable — a command, a file's state, a marker in the output. A vague "until it's good enough" turns into endless work, because there's nothing to check it against.
A separate cost item few people think about: while a goal is active the agent periodically wakes up and checks on stuck background work, and every such check is a full turn with the full context. The frequency is set by CLAUDE_CODE_GOAL_CHECKIN_MINUTES, zero disables the checks entirely; since version 2.1.246 there are no more than three of them per goal.
/goal until all the tests are green # work until the condition is met/goal # show the current goal/goal clear # drop the goalCode review and quality
The first three commands all look at the same diff and are therefore easy to confuse; the fourth doesn't analyze anything at all:
| Command | What it looks at |
|---|---|
/code-review | correctness bugs and code cleanliness; only edits with --fix |
/simplify | cleanliness only — and applies what it finds right away |
/security-review | only vulnerabilities in the branch's changes |
/diff | doesn't look for anything, just shows the changes |
/code-review [level|ultra] [--fix] [--comment] [--post|--no-post] [target]
Reviews the diff for bugs and simplifications [Skill]. Alias: /review. An ordinary local review counts against your plan's limits, but the cloud ultra mode is [costs extra]: three free runs each on Pro and Max, after that it's charged to credits, usually five to twenty-five dollars per review, and if credits aren't set up a paid run is simply blocked. That same ultra is also [not on every plan]: it needs a claude.ai login, and it isn't there on third-party providers or in organizations with zero data retention.
The most configurable of the built-in commands: an effort level, four flags, a review target and a separate cloud mode — and each is parsed by its own rules. The full form is /code-review [low|medium|high|xhigh|max|ultra] [--fix] [--comment] [--post|--no-post] [<PR#>|<branch>|<path>|<note>], and everything in it is optional: a bare /code-review is a valid call.
What it looks for. Two different things. Correctness bugs: an inverted condition, an off-by-one, a null dereference, a forgotten await, a check that was dropped, an error swallowed in a catch, broken callers of a changed function, the classic traps of the particular language. And cleanliness: new code that repeats something already in the repository; needless complexity and dead code; needless work such as repeated computations or independent operations run one after another; the "wrong level of fix", where a patch goes in the spot where the general mechanism should have been fixed; direct violations of the rules in your CLAUDE.md.
Correctness bugs always outrank cleanliness findings: if there are more findings than the level allows, the latter get cut first. The review itself changes nothing until --fix is passed.
Where it runs. Usually in a background agent: the session isn't blocked, and the findings arrive as a separate message. In three cases the review takes over the whole session: if you started it again while the previous one is still running; if you're in non-interactive -p mode or in the SDK; and if CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1 is set, which disables background tasks entirely.
Who can start it. Not just you. Ask "take a look at my changes" in plain text and the agent will start the review itself, and a scheduled task with /code-review in the prompt will fire too. If that gets in the way, you can keep the command typeable but forbid the agent and the scheduler from running it:
{ "skillOverrides": { "code-review": "user-invocable-only" }}The cloud mode is the exception: the agent never starts ultra, neither on its own nor on a schedule.
Argument order. Three rules that make a call behave differently than you expected:
ultrais only understood as the first word./code-review ultra --fixis a cloud review, while/code-review --fix ultrais an ordinary local one in which the wordultrais read as the target.- The level is the first word left once the flags have been stripped from the line. That's why
/code-review --fix highworks, and the level will behigh. - Flags can go anywhere: at the start, at the end, between the level and the target. The only exception is rule 1.
And a fourth one, separate: this command "eats" the command typed after it. Normally several skills chain in one message, and /write-tests /fix-issue 123 will load both. But since 2.1.218 /code-review /fix-issue 123 reads /fix-issue 123 as target text rather than as a second command. Before 2.1.218 it was the other way around.
Effort levels.
| Level | How it searches | Findings | When to use it |
|---|---|---|---|
low | A single pass over the diff: no subagents, no reading whole files, no re-verification of findings; test files aren't looked at | up to 4, on some models up to 8 | A quick, cheap read-through before a commit |
medium | Eight independent search angles — three on correctness, three on cleanliness, one each on the level of the fix and on the CLAUDE.md rules — then verification of every finding | up to 8 | An ordinary review |
high | The same eight angles, but the verification leans toward completeness: a finding stays unless it can be disproved | up to 10 | When a missed bug costs more than extra noise |
xhigh | Ten angles with eight candidates each, verification, and a separate final "what did we miss" pass | up to 15 | A large or risky diff |
max | The same as xhigh, with maximum emphasis on completeness | up to 15 | Before a release, a migration — anything hard to roll back |
ultra | Not a level but a mode of its own: a multi-agent review in the cloud | — | A whole pull request you'd like a second pair of eyes on |
The numbers in this table were read off the binary: the official documentation describes the levels qualitatively — "low levels return the most confident findings, high ones broaden coverage and may include less confident ones" — and nowhere publishes how many search angles there are or what the cap on findings is.
The exact pipeline depends on the session's model, so the table is about what the levels mean, not about a guaranteed number of agents. On Opus 5, medium and high currently collapse into a single careful pass with a cap of fifteen findings, and the differences start at xhigh; on Sonnet 5, at high, xhigh and max the number of search agents is picked from the size of the diff — anywhere from two to eight.
There's no separate charge for the upper levels, but every search agent carries its own context, so xhigh and max burn through your plan's limit noticeably faster than low. Running max on every little fix is the easiest way to be out of your weekly limit by Wednesday.
Remembering the level. If no level is given, the one you typed last time is used: it survives across sessions, and the report opens with a line like "using high, the level from last time". Two exceptions: a level passed in a non-interactive -p run remembers nothing, and ultra neither reads the remembered level nor changes it. If you've never typed one, the current session's effort level is used. The level you type also sets the model's effort for the turn, including downward: /code-review low in a session on xhigh will lower it.
A typo doesn't break the call: /code-review higher gets you a warning that the value wasn't recognized, plus the previous or default level. The shorthand med is accepted as medium.
Flags.
| Flag | Where it works | What it does |
|---|---|---|
--fix | locally and with ultra | After the report, apply the findings to the working tree |
--comment | locally, if the target is a pull request on GitHub | Post every finding as a separate line comment |
--post | ultra only, repository on github.com | Post the summary as one ordinary comment from your account |
--no-post | ultra only | Remove the offer to post from the launch dialog — which is the default behavior anyway |
--fix fixes what was found right in the working tree, both bugs and cleanliness. A finding is skipped if the fix would change intended behavior, require changes far beyond the diff that was reviewed, or looks like a false positive; at the end you're told what was skipped and why. With ultra the fixes are applied locally the moment the cloud returns its result.
--comment requires the target to be a pull request. If it isn't, the flag is ignored, the findings are simply printed, and the agent tells you so. Comments go out through the GitHub integration, or through gh api if the session doesn't have one.
--post is not the same as --comment: one shared comment instead of per-line remarks, and only for a cloud review. In an interactive session the launch dialog will still ask for confirmation; in non-interactive mode it posts on the flag alone. Passed to an ordinary local review, it's ignored — you'll be reminded that posting there is --comment's job.
--no-post is for not seeing the offer to post at all. Passing both at once is pointless: the command only reads --post, so --post --no-post will still offer to post.
The review target. With no target, your current work is reviewed: the branch's commits above its upstream plus uncommitted changes. That's why the command makes sense before a commit, too.
In a local review the target is handed to the model as a string, and it decides for itself what it is: a pull request number, a branch name, a path to a file or a folder — or just a hint about where to look first. In ultra the target is parsed strictly:
| What you passed | What happens |
|---|---|
| nothing | The current branch is reviewed against the base one |
1234, #1234, PR 1234, a link to /pull/1234 | That pull request is loaded and reviewed |
| the name of an existing branch | Taken as the base, and the diff is computed against it |
| anything else | Recorded as a note for the review: the cloud agent doesn't see it and reviews the branch diff anyway, but when the findings come back they'll be tied to what you asked for |
Reviewing in the cloud: what it needs, what it costs, where the ceiling is. ultra launches a background agent in Claude Code on the web: it clones the repository into a cloud sandbox, runs a multi-agent search over the diff and sends the findings to your session as a notification. It takes minutes, and you can keep working the whole time.
You need a git repository and a GitHub remote, a claude.ai account with GitHub connected, and for a private repository the Claude app installed on the owner. It's unavailable on third-party providers, with optional requests turned off, in organizations with zero data retention, and when the organization forbids it. An important detail: when the mode is unavailable, /code-review ultra doesn't fail — it quietly runs an ordinary local review, so if you were expecting the cloud one, it's worth making sure it actually started.
The diff ceiling is up to five hundred changed files and eight thousand changed lines. A pull request that's too big is rejected, and the rejection names the limits in force, the size of your diff and the biggest files; an empty diff is rejected too.
The price: three free runs each on Pro and Max — granted to the account once, never refreshed — and none at all on Team and Enterprise. After that it's credits, usually five to twenty-five dollars per review depending on the size of the changes. A run counts from the moment the cloud session starts: a review you stop or that crashes still spends a free run, while a paid one is charged only for the part it worked through. If credits aren't set up, a paid run is simply blocked.
What you confirm before it starts. A paid cloud run doesn't go off silently: first you're shown a dialog with a cost estimate and asked to agree to the credit charge — once per conversation. In the same place, if --post was passed, you decide whether to post the summary as a comment in the pull request or keep the findings to yourself. Until you confirm, the cloud session doesn't start.
From CI. Since 2.1.218 the cloud review can be started non-interactively:
claude -p '/code-review ultra'The command starts the review, prints a link for following along, and doesn't wait for the result. But if the review is going to spend credits, the run stops: confirming payment requires an interactive session. For that case there's a separate subcommand, and the very act of running it counts as your consent to the charge:
claude ultrareview # cloud review of the current branchclaude ultrareview 1234 --post # review a PR, summary as a comment in itclaude ultrareview --json # raw findings instead of a reportclaude ultrareview dev --timeout 60 # against branch dev, wait up to an hourThe exit code is 0 if the review finished (with findings or without) and 1 if it couldn't be started. --timeout defaults to thirty minutes.
The canonical form is /code-review ultra; /ultrareview is its alias, it isn't available to every account, and the whole feature is marked as research. Articles often have it the other way around, as if /ultrareview were the main command.
In GitHub Actions. The review has a separate life in CI, and there it's configured by a file rather than by flags. You put a REVIEW.md in the repository root that sets the rules: which paths and branches to skip, which categories of findings to hide, what counts as important, how to behave when the same pull request is reviewed again.
Findings come in three levels: important ones, nitpicks, and ones that were already in the code before these changes. Violations of your CLAUDE.md rules land in the nitpicks. The check always finishes with a neutral status and so never blocks a merge on its own — but its last line prints a finding counter as JSON like {"normal": 2, "nit": 1, "pre_existing": 0}, which you can use to put up a barrier of your own in your own pipeline.
What comes back depends on the mode: an ordinary review sends a report as a separate message, --fix adds fixes in the working tree to it, --comment takes the findings off into comments in the pull request, and ultra first asks for confirmation in the launch dialog and only then gives you a link to the cloud session.
/code-review # current changes, level as last time/code-review high --fix # deeper, and fix what it finds right away/code-review medium --comment 1234 # review PR 1234 with comments right in it/code-review ultra 1234 --post # cloud review of a PR, summary as a comment/simplify [target]
Find simplifications in the changed code and apply them right away [Skill]. This is cleaning up after yourself once the code already works: the command doesn't look for bugs at all, so it runs faster than a review — but it can't replace one either. It's worth reaching for when a change has grown: near-identical chunks have appeared, your own helpers on top of ones that already exist, extra intermediate layers.
It looks at the same diff as /code-review, but searches only for cleanliness, and does it with four parallel agents: reuse of helpers already written, simplifications, efficiency, and whether this is the right level of abstraction. It doesn't look for bugs on principle — that's a division of labor, not an oversight. And unlike the review, it applies what it finds right away. The argument is an optional target: a path, a folder or a pull request number.
It isn't billed separately, but four agents means four contexts at once, so the command eats through your plan's limit noticeably faster than a single pass.
A historical trap: before version 2.1.147 what is now /code-review was called /simplify, and it applied its fixes by default. An old script that called /simplify to hunt for bugs does something completely different today.
You won't have to choose anything along the way: the command asks nothing, and what comes back is a list of the simplifications applied — by that point the edits are already in the working tree.
/simplify # all the changed code/simplify src/payments # just this folder/security-review
Check the branch's changes for vulnerabilities. No arguments. This is a third look at the same diff, but through different optics: not "does it work" and not "is it written neatly", but what could be pulled out of it or broken from the outside. It makes sense to call before the branch heads off to the shared repository — especially if the change touched authentication, parsing of user input, or secrets.
It looks for injections, authorization and authentication problems, data leaks, and unsafe handling of secrets and input.
The one requirement people trip over: you need a remote named origin — the diff is computed against its main branch. Without it the command fails with a git error about an ambiguous argument, and it looks mysterious.
What comes back is a list of what was found: the place in the code, the nature of the problem, and why it's dangerous.
/security-review # vulnerabilities in the branch's changes/diff
Look through uncommitted changes interactively. No arguments. It analyzes nothing, it's a viewer: uncommitted changes and, more usefully, the diff of each agent turn separately. It comes in handy when the agent has worked through several turns and you need to see which step it went wrong on — so it's a thing to use before /rewind, not after.
Inside it you choose what to look at: all the uncommitted work at once, or one specific agent turn. Leaving the viewer puts you back in the same session and changes nothing in the code — rolling back lives in /rewind, it isn't here.
/diff # look at what's uncommittedDevelopment and workflows
/run and /verify get mixed up constantly: both are about "checking it live", but they answer different questions.
| Command | The question it answers |
|---|---|
/verify | Whether one specific change does what it was meant to do |
/run | How the whole app behaves when you bring it up the usual way |
/run
Start the project's app and check the change live, not just with tests. [Skill] You reach for it when the diff tells you nothing: a screen changed, a form behaves differently, a command's output moved — you just need to see the app running. Don't mix it up with /verify: that one answers for a single concrete edit, while /run brings everything up as is.
This is about the whole app: start it the way it's started in this project, and let you look. For the agent to know exactly how, it needs a launch skill — /run-skill-generator creates it, once per project. Without one, /run will try to guess from the project type, and on a non-standard build it'll guess badly.
Once called, the usual build and start steps run — the ones written down in the skill or inferred from the project type — and then you look at the app itself: did it come up, and does it do what you brought it up for.
/run # start the app and see it with your own eyes/verify
Confirm that a change works: build it, run it, watch how it behaves. [Skill] You reach for it right after an edit, when what matters is seeing the result rather than trusting the diff. What gets checked is the change itself, not the whole app — for that there's /run.
The logic is simple: a review checks that the diff reads right, /verify checks that it works right.
Since 2.1.200 the command can write the verification recipe it found into a skill of your own, .claude/skills/verify/SKILL.md, and sitting in the repository root it then replaces the built-in one — so you work out once how to verify this project, and after that it works for everyone.
An important change: since 2.1.215 /verify is launched only by you. The agent used to be able to call it itself. The same happened to /deep-research in 2.1.218. If you've read an article saying the agent will verify itself, it's out of date.
The check runs all the way through on its own — build, run, watch the behavior — and at the end you get a verdict on whether it holds up and what exactly was looked at. If the repository didn't have a verification recipe yet, you'll be offered one to write down along the way.
/verify # build, run, make sure it works/run-skill-generator
Create a skill that knows how to start this project's app — /run then runs on top of it. [Skill] The command works out how everything here builds and starts, and writes the recipe it found into a skill that lives in the repository and works for everyone.
Done once per project.
The work isn't instant here: the app really is brought up from scratch, while noting which install commands, environment variables and start script actually worked. The result is a skill file in the repository, not text in the terminal.
/run-skill-generator # teach the project the /run command/batch <instruction>
Plan a large-scale edit and run it in parallel across 5–30 isolated working copies, each opening its own pull request. [Skill] You need it where the same edit has to land in dozens of places and each place is a self-contained piece of work. For one edit in a couple of files it's overkill: the overhead of the fan-out eats the whole gain.
The heaviest of the built-in commands and the only one that spawns dozens of agents by default. The instruction first turns into a plan — a list of the concrete places that need editing — and then each place gets its own agent in its own isolated git working copy, and each of them opens a separate pull request.
Isolation is the key part here. The agents edit files in parallel, and without separate working copies they'd step on each other's toes. Hence the requirements: a git repository, a clean tree and a configured gh, otherwise there's nothing to open a pull request with.
The number of agents runs from five to thirty, and it's derived from the plan rather than set by you: as many places as were found, that many agents, up to the ceiling. If the plan comes out at two places, no fan-out is needed, and the command will say so.
There's no separate charge for it, but it eats your plan's limit many times over: twenty agents means twenty sessions, each with its own context.
A good instruction is one where the boundaries of each place are obvious and the edits aren't tied to each other. A bad one is "refactor the project": the plan comes out of vague items, and thirty agents will independently invent thirty different architectures.
The fan-out's behavior is shaped by the worktree settings: symlinkDirectories saves disk space when the project has heavy dependencies, sparsePaths speeds up checkout in large monorepos, baseRef decides whether to branch off the remote main branch or off your current local state.
The order goes like this: first you're shown the plan and asked to agree — that's the moment where it's decided whether as many places were found as you expected. After approval the agents go off to work in the background, and links to the opened pull requests show up as they're ready.
/batch move all controllers over to the new client # a fan-out of isolated agents, each with its own PR
/batch spread the shared DTOs into the modules that use them # if there are few places, no fan-out is needed — the command will say so/debug [description]
Turn on debug logs for the session and help you get to the bottom of a problem. [Skill] It comes in handy when it's unclear whose trouble this is — yours or the agent's own: the verbose logs show which tools were called and what they answered. The logs stay on until the end of the session and don't carry over to the next one.
The description is optional — with it you say up front what you're chasing.
Without a description it stops at turning the verbose logs on, and you carry on working as usual. With one, the command gets straight to work on the problem you named, leaning on whatever shows up in those logs.
/debug # turn on debug logs
/debug it only fails on CI, green locally # the same plus a description of the problem/fewer-permission-prompts
Go through the transcripts, find the frequent safe calls and assemble an allowlist out of them. [Skill] The point is to stop confirming the same harmless read ten times a day. The command looks at your own history rather than a generic list, so the permissions come out fitted to this specific project.
The edit lands in the project settings, which means it takes effect for everyone who works with this repository.
What you get is a proposed list of permissions, sorted by what got confirmed most often; it's up to you whether to accept it whole or strike out the extras before it lands in the project settings.
/fewer-permission-prompts # build an allowlist from your history/commit [wishes]
Put a commit together: look at the status and the diff, write the message in the accepted format. [Skill] The message format is derived from this repository's commit history rather than from generic rules — in someone else's project your commit will look like the ones next to it. It's useful for exactly one reason: it removes two boring steps — deciding what goes into the commit, and putting into words what you actually did.
The argument isn't flags, it's wishes in plain text; the same goes for /pr. Those wishes affect what ends up in the commit and how the message is written.
What goes into the commit message as attribution is set by the attribution object with its commit and pr fields, where an empty string removes it entirely. You can turn the built-in commit instructions off completely with includeGitInstructions: false — then the agent will use only your own rules.
Before the commit is created you can see what was selected for it and in what wording — that's where you decide whether both suit you. The wishes in the second example narrow the commit down to the schema files; everything else stays untouched in the working tree.
/commit # a commit with a message in the project's format
/commit only the schema changes, leave the rest alone # only the schema files go into the commit/pr [wishes]
Open a pull request: create a branch, push it, write the description through gh. [Skill] The description is assembled from what's really in the diff, not from your retelling of it. The three steps by hand take a couple of minutes, and the description is usually the part people skimp on; here it writes itself.
A branch is created if you're still on the main one. The wishes set the draft flag, the reviewers, the shape of the description.
The steps run one after another — branch, push, creating the request through gh — and at the end you're holding a link to the opened pull request. Wishes like "as a draft" change what the request opens as, but not the order of the steps.
/pr # branch, push, pull request with a description
/pr as a draft, don't assign reviewers # the same, but the request opens as a draft/commit-push-pr
All three steps in one go: commit, push, pull request. [Skill] The same as /commit and /pr back to back, but with no pauses in between — for when the work is plainly finished and there's nothing to discuss. If you want to look at the commit before it leaves, you're better off with the two separate commands.
It has one quirk: dangerous git and gh flags are not approved automatically. --force, --amend, --no-verify will still ask for confirmation, even if your permissions are generous. That's deliberate: a chain of three steps runs fast, and a human doesn't have time to notice that history is being rewritten somewhere in the middle.
All three steps run without stopping, and at the end you're left with a link to the request. Exactly one thing can break the chain — a dangerous flag along the way: on that one you will be asked whether to go on.
/commit-push-pr # all three steps at once/update-config
Change settings: hooks, permissions, environment variables — with settings.json edited for you. [Skill] Its main case is behavior of the "every time that…" kind: only a hook can do that, and no amount of asking or memory will get you there, because it's the program itself that runs them, not the model. Say in plain words what should happen, and the command works out which settings file to write it into and in what shape.
Settings come in project and personal flavors, and those are different files: the project ones are seen by everyone who works with the repository, the personal ones only by you. If the edit is about your own habits rather than the shared way of working, say so up front.
Before anything is changed you'll be told which setting will appear and in which file — and if the wrong file got picked, that's exactly the moment to step in.
/update-config add a hook that formats files after edits/claude-code-docs [question]
Answers about Claude Code itself: features, settings, the SDK, the Claude API, the Slack app. [Skill] It answers from the documentation rather than from the model's memory — and those are different things, because the program changes from version to version faster than the model's knowledge is updated. Better to ask in a human sentence, the way you'd ask a colleague.
What comes back is a breakdown based on the docs with links to their sections — which are also handy for checking that the answer wasn't invented.
/claude-code-docs how to restrict the agent's access to a folder/claude-in-chrome
Allow work in your Chrome: clicking, filling in forms, reading the console. [Skill] [not on every plan] — it needs a claude.ai account login: with an API key, and through Amazon Bedrock, Google Cloud and Microsoft Foundry, the extension isn't available. The work happens in your real browser, with your tabs and sessions — which is why it fits where what needs checking isn't code but a live page: reproducing a UI bug, walking through a form, looking at console errors.
Access is granted per site and configured in the extension itself: the agent won't go to a page you haven't allowed.
Once called, the agent connects to your browser and works with the allowed tabs from there. If the site you need isn't among the allowed ones, the choice is simple: grant it access in the extension, or give up on this check.
/claude-in-chrome # allow work in the browser/plugin-types [folder]
Generate input types for the connected MCP tools. The command reads the tool descriptions and lays them out as types, so that in the plugin's code the calls get checked by the compiler instead of being guessed from memory. The argument is the folder of the plugin to generate for. You need it when developing your own plugin; in ordinary work on a project it won't come up.
There's not much to watch here: the command's result is type files inside the plugin folder you named.
/plugin-types ./my-plugin # MCP tool types for the plugin/workflow-authoring
A reference on writing scripts for workflows. [Skill] It explains what a script is made of, how resuming after a failure works, and what people usually trip over. You read it before writing your own workflow, not while one is running.
It doesn't authorize running a workflow by itself.
What comes back is the reference itself — how a script is built, resuming, the typical mistakes and worked examples — after which you can sit down and write your own.
/workflow-authoring # how to write workflow scripts/claude-api [migrate|upgrade|prompt-audit|managed-agents-onboard|cost-optimize]
Help with the Claude API and the SDK. [Skill] The only command in this group with a fixed set of arguments. You need it when you're writing code that calls Claude itself: model identifiers, parameters, streaming, tool calling, caching — all of it checked against the documentation rather than the model's memory.
The argument picks the scenario: without one it's a general reference, with one it's concrete work on your code.
| Argument | What it does |
|---|---|
| no argument | General help with the Claude API and SDK: parameters, streaming, tool calling, caching |
migrate | Migrating code to a new model: what to change in identifiers, parameters and expectations |
upgrade | Moving to a new major version of the client library; since 2.1.236 |
prompt-audit | Find instructions written for older models in prompts, skills and tool descriptions, and propose the edit as a diff; since 2.1.221 |
managed-agents-onboard | Onboarding onto server-side agents with a managed sandbox |
cost-optimize | A breakdown of your API spend and what to do about it; since 2.1.247 |
The skill also switches itself on without the command: if the project's code imports the official Anthropic library, it activates on tasks that touch it.
With an argument the command first reads your code and comes back with a list of places and proposed edits — whether to accept them all or one at a time is up to you.
/claude-api migrate # migrate to a new model
/claude-api prompt-audit # find instructions written for older models in prompts/deep-research <question>
A fan-out of web searches across many sources, fact-checking, and a report with links. [Workflow] You reach for it when one search isn't enough: the question is contested, the sources contradict each other, or you need a cross-checked answer rather than the first one that turns up. The search runs along several independent lines, the findings are matched against each other, and the report shows exactly what the conclusion rests on.
Since 2.1.218 it's launched only by you — the agent used to be able to call it itself.
This is a dynamic workflow: a lot of agents get launched, and a single run eats your plan's limit noticeably faster than an ordinary session. On the Pro plan, dynamic workflows have to be enabled first with the Dynamic workflows entry in /config.
The first thing you're asked for is permission to run the workflow — and that's your only choice along the way. After that everything runs in the background, the session stays free, you can follow the progress through /workflows if you like, and at the end a report with links arrives; claims that couldn't be verified are marked as unverified rather than passed off as fact.
/deep-research how approaches to idempotency in queues differSubagents, background tasks, automation
/list-agents
Shows everyone you can message straight from the session: subagents you spawned, teammates, other Claude Code sessions on this machine, and cloud ones. The name in the list is the address: copy it and your message goes to exactly that agent. You don't pull the list up out of curiosity — you pull it up when you need to know who's still alive and how to reach them. Alias: /peers.
Teammates (agent teams) are off by default everywhere and are switched on with the CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 variable — until it's set, there will be no rows for them in the list. And keep the price in mind: a team of agents burns roughly seven times as many tokens as an ordinary session, because every teammate has its own context window and keeps spending until it finishes.
The command only prints the list and offers nothing to pick: you take the name of the agent you need from it yourself and plug it into a message.
/tasks
Shows everything running alongside the conversation: background tasks, spawned processes, their state and how long they've been going. This is also where you manage them — the one place that shows every running build and test run at once. Handy when there are several of them and it's unclear which are still alive and which died long ago. Alias: /bashes.
You pick a specific row in the list: from there you can look at that task's output or stop it, without leaving the conversation and without hunting the process down in the system.
/daemon
Manages Claude Code's background services — the ones that run outside your conversation: assistants, scheduled tasks and remote control. You come here when one of them has to be switched on, switched off, or stopped from firing. Note that some of these services — scheduled tasks and remote control — only exist when you're logged into a claude.ai account; with an API key they simply won't be there.
The choice here is between services, not between tasks: you find the row you need and toggle its state, and everything else happens by itself.
/workflows
The history of workflows — the runs where a task is split across many agents that work in parallel. It shows both the running and the finished ones: how many agents, which step, how it ended. This is where a run is paused and resumed — the only place you can influence a long run without killing it outright. Don't confuse it with background tasks: those are about processes and commands, these are about multi-agent runs.
One such run eats noticeably more tokens than the same work in an ordinary conversation — there are many agents, each with its own context. It's billed as ordinary usage; there's no separate bill. When a run has more than 25 agents or the forecast goes past 1.5 million tokens, Claude Code warns you in advance; in ultracode mode the warning isn't shown — by turning it on you already agreed to big runs. On the Pro plan, workflows themselves have to be enabled first in /config.
/loop [interval] [prompt]
Repeat a prompt or a command on an interval; with no interval the pace is chosen for you. Alias: /proactive. [Skill]
The command takes two things in a row: an optional interval and the thing to repeat. What gets repeated can be either a plain prompt or a slash command.
| What you passed | What happens |
|---|---|
<interval> <prompt> | The prompt runs on a schedule at that interval |
<interval> /command | The same, but a slash command is what repeats |
<prompt> | No interval given: the agent decides for itself when to wake up next |
| nothing | An autonomous loop: the agent picks both the task and the pace |
The interval is written as a human shorthand: 5m, 30m, 1h. Take the no-interval mode literally: the agent picks the pause based on what it's waiting for. A build that takes eight minutes it will wait out in a single pause, not in eight one-minute checks.
There's exactly one trap, and it's an expensive one: a loop that wakes up every minute to check on a background task is almost always pointless. You'll be told when background work finishes anyway, and every wake-up is a full request carrying the whole context.
What's already running and how often is shown by /usage: the dedicated command for that, /loops, is disabled in build 2.1.251.
The call starts the loop and hands control straight back: from then on it wakes up on its own, and each wake-up looks like an ordinary request in the session.
/loop 5m /code-review low # every five minutes — a quick review pass/loop 1h check whether new failing tests appeared, and fix the obvious ones/loop check if the build is broken # no interval: the pace picks itself/schedule [description]
Creates, updates and runs an agent that works in the cloud on a schedule. [not on every plan] — it needs a claude.ai account login: with a Console API key, under an Anthropic profile, and through Bedrock, Google Cloud and Foundry the command isn't there, and the closest replacement is /loop. [beyond the plan] — the runs themselves count against the plan's usual limit, but the account also has a daily cap on the number of runs: once you hit that or the plan limit, you can only continue on connected credits, and without them the extra runs are rejected until the window resets. Alias: /routines. [Skill]
The difference from /loop is where it runs. /loop works inside your session, on your machine, for as long as it's open. /schedule sets a task up in the cloud: it runs on schedule whether or not your laptop is on.
The argument is a description in words, and the schedule, the task and the intent are all derived from it: the command can not only create, but also update, list, run out of turn and delete. The rest of the requirements are the same as for everything cloud-based: GitHub connected and no ban from the organization — on Team and Enterprise the owner can turn schedules off for everyone. The default environment comes from the remote setting. The whole feature is marked as research, which means it will change.
There's one thing to remember about spend: a scheduled task wakes up and sends the full context even while you're at the computer busy with your own work. It's the least visible line item of them all.
What ends up on screen depends on what you asked for: all four calls below are the same command parsing your description.
/schedule every morning at 9 collect a failing-test report # create the task/schedule show my scheduled tasks # what's already set up/schedule run the morning summary right now # an out-of-schedule run/schedule delete the task about dependencies # delete/autofix-pr [prompt]
Starts a cloud session that watches the pull request of the current branch and pushes fixes itself — repairing a failing CI build, for instance. [not on every plan] — it runs through Claude Code on the web, and that needs a claude.ai login: with an API key and through Bedrock, Google Cloud and Foundry there are no cloud sessions. The optional argument narrows the mandate: what may be changed and what must not be touched. Control comes back immediately — after that the session lives in the cloud on its own, and that's where you have to look at it.
/autofix-pr # watch the PR and fix CI failures/autofix-pr only the linter, don't touch the logic # the same thing, but with a limitArtifacts, documents and design
An artifact is a page published on claude.ai that you can open, click around in and hand to colleagues to look at. Almost everything below is a built-in skill, and what you get depends on the account: some of it is only enabled for certain subscriptions and organizations.
Publishing exists on Pro, Max, Team and Enterprise: on Team it's on from the start, on Enterprise the organization owner turns it on, and with CMEK, HIPAA or a ban on data retention it's closed off entirely. You need a session logged into claude.ai — with an API key, a gateway token or Bedrock, Google Cloud and Foundry credentials the page won't publish. Artifacts aren't billed separately: generating a page spends output tokens like any other answer.
The official command reference lists only /artifacts, /design, /design-login and /design-sync out of this group; the other fifteen or so are [not in the docs] — not in the changelog, not in search, so what's below is what the build actually has, not what was promised somewhere.
/artifacts
Shows your published artifacts and the ones shared with you: the title, the link, when it was updated. [not on every plan] — like everything in this group, it needs a session logged into claude.ai. The main use is practical: finding the link to a page made in a previous session — without it Claude Code will publish a new one instead of updating the old one. It doubles as an inventory: you can see what's already published and whether anything got lost.
The list is interactive: on the selected row the artifact either opens in the browser or its link is copied to the clipboard — you don't have to leave the terminal for that.
/prototype
Turns an idea into a working prototype — a single self-contained page you can open, poke at and show around. [not on every plan] — publishing requires a claude.ai login. You reach for it when arguing in words costs more than just looking: an interface screen, a flow of several steps, a draft landing page. What sets it apart from the design commands below is that it makes a working thing, not a picture.
Nothing is asked up front: you describe the idea in words, the work then runs through to a finished page, and at the end a link to it is what's left.
/prototype a plan picker page: three plans, a month-year toggle, discount math/doc
Publishes a working document that's edited right on the page: a note, a cheat sheet, an instruction for the team. [not on every plan] — it needs the same claude.ai login. The point is that the document doesn't stay buried in a chat: it has an address, you can open it, add to it and hand out the link. Worth reaching for when the result is meant for people, not for you alone in the terminal.
What kind of document you need is said right in the command; back comes the address of the published page, and from there you edit it either on the page itself or by asking the agent.
/doc turn the decisions from this conversation into a deploy cheat sheet for the on-call/plan-artifact
Publishes a plan as a separate page you can share: the stages, what follows what, what's needed from whom. [not on every plan] — publishing requires a claude.ai login. Handy when a plan put together in planning mode has to be shown to people rather than retold. The only thing that separates it from /doc is the template: here it's a plan, not an arbitrary document.
From there you spell out what the plan should contain; the result is a page with the stages and a link to it.
/artifact-pr-review [number or link]
Goes through a pull request and lays the analysis out as a separate page: the verdict, the recommendation, the contentious spots, the blind spots. [not on every plan] — publishing requires a claude.ai login. The argument is a PR number or a link to it. You need it when the analysis has to be shown to the author and everyone else; don't confuse it with /code-review — that one hunts for defects and works in the terminal, while this one makes a readable page with a conclusion.
The work happens in two passes and isn't instant: first the PR is read in full, and only then is the page published, and its link is what you get.
/artifact-pr-review 1234/artifact-dashboard
Builds a dashboard from a ready-made template: metrics, charts, breakdowns on one page. [not on every plan] — publishing requires a claude.ai login. You use it when you have numbers and need to show them whole: project status, the results of a run, metrics for a period. The template sets the layout and the styling — what's on you is the data and knowing what matters in it.
From there you supply the data and say what matters in it; at the end a link to the finished dashboard is what's left.
/artifact-dashboard weekly queue metrics: length, wait time, share of retries/artifact-report
A report from a ready-made template: the conclusions on top, the detailed sections below. [not on every plan] — publishing requires a claude.ai login. Good for the outcome of an audit, an analysis or a big run, when the result has to be handed to people whole rather than retold in pieces. The difference from a dashboard: here it's text and reasoning, not tiles with numbers.
From there you say what the report is about; the result is a published page and a link to it.
/artifact-report the load test results for the partner team/artifact-data-table
Publishes data as a table from a ready-made template — a separate page instead of a wall of text in the terminal. [not on every plan] — publishing requires a claude.ai login. You need it when there are more rows than fit in an answer and you want to walk your eyes over them. The data comes from what you supplied or from what piled up in this session.
From there you supply the rows and the columns; at the end, a link to the page with the table.
/artifact-data-table an SLA-by-service table from the latest report/artifact-explainer
An explainer page from a ready-made template: one topic or mechanism taken apart step by step. [not on every plan] — publishing requires a claude.ai login. You use it when you have to explain how something works to a colleague or a new person on the team, and the explanation should outlive a single conversation. It differs from a report in its job: a report reports a result, an explainer teaches you to understand.
From there you name the topic; the result is a page with the walkthrough and a link to it.
/artifact-explainer how our order idempotency scheme works/artifact-components
Pulls in the ready-made reusable components an artifact gets assembled from. The point is simple: don't redraw from scratch every time something that's already built and looks decent. It publishes nothing itself — it works on the page you make in the next step.
Nothing appears on screen after the call: the set of components simply lands in the context.
/artifact-design
The styling rules for artifacts: layout, typography, the dark theme and, more importantly, matching the effort to the task. You load it before making a page so that it looks like a finished thing rather than a draft out of a terminal. It publishes nothing and prints nothing.
/artifact-diagramming
How to draw diagrams that show the real mechanism rather than a set of boxes with arrows: when a diagram is warranted at all, what belongs on it and how to keep it legible in the light and the dark theme. You load it when an artifact needs a diagram. It publishes nothing and displays nothing.
/artifact-capabilities
Describes what a published page can do at runtime: read your data, remember what visitors do (a poll, a checklist, a document edited right on the page), keep shared state, ask Claude. You load it before asking for such a page: without it you'll get ordinary static HTML that remembers nothing. Which capabilities you get depends on the account, and the command shows what's available to you specifically.
/dataviz
The styling rules for charts and dashboards: which chart type suits which data, palettes, axes, labels, accessibility, behavior in the dark theme. You load it before the first line of chart code is written — redoing it later costs more. It works beyond artifacts too: the rules are the same for an image and for code in any library.
The call itself outputs nothing: the rules load and take effect on the next chart.
/whiteboard
A shared whiteboard: you draw by hand and the answers come back onto it. [not on every plan] — the board lives as a published page, which means a claude.ai login is required. Good where explaining in words takes longer than sketching: the arrangement of elements, the structure of a screen, the links between parts of a system.
The board opens as a separate page, and the link to it is what you get back from the call.
/whiteboard sketch the exchange between the orders service and payments/whiteboard-mp
The same thing, but the board is live, and it isn't only a human drawing on it: the agent adds its own on top of yours, and it turns into work for two. [not on every plan] — like the ordinary board, it requires a claude.ai login. You use it when you don't want to "draw and then ask" but to sketch together.
The page works the same way, with the link in the reply; the difference is that from then on one canvas holds both your strokes and whatever the agent drew in.
/whiteboard-mp let's work out together where idempotency gets lost in this scheme/workshop
Builds a design together with you, one decision at a time: a question — your answer — the next step, instead of a big page made whole in one go. [not on every plan] — the result gets published, so a claude.ai login is needed. Good when you don't yet know what you want yourself and the answer crystallizes as you go.
The conversation starts with a question and goes on in questions to the end; the finished page with its link appears right at the finish.
/workshop a notification settings screen — one decision at a time/design [sync|login|consent|revoke|import|export|status|description]
The Claude Design hub — the link between Claude Code and the design system on claude.ai. [not on every plan] — it exists on Pro, Max, Team and Enterprise (on Enterprise it's off by default), it needs a session where artifacts work and a version no lower than 2.1.234; on Bedrock, Google Cloud, Foundry and Claude Platform on AWS the command isn't there. It isn't billed separately: the spend goes into the same shared limit as ordinary work.
Officially this is one command "with a design description", while /design-login and /design-sync are two separate ones. In the binary, /design also understands seven subcommands, and that's documented nowhere. The whole thing showed up in version 2.1.234 and is marked as research — meaning it will change.
| Subcommand | What it does |
|---|---|
status | Shows the state of the connection to Claude Design |
login | Logging in, which is also granting access |
consent | Documented nowhere |
revoke | Revokes the access that was granted |
import | Pulls the design system from there into the project |
export | Pushes the project's design system there |
sync | The same as the separate /design-sync command |
description | The ordinary call: you say in words what design you need |
The subcommands answer differently: status reports the connection state, login sends you off to the browser to confirm access, and import and export move the design system between the project and claude.ai.
/design status # the state of the Claude Design connection/design login # log in/design import # pull the design system from there/design export # push it there/design-sync [hint]
Assembles a React project's design system straight from the code and pushes it to claude.ai/design, so that everything drawn there looks like your product and not somebody else's template. [not on every plan] — the same requirements as /design: a claude.ai login and artifact publishing available. The argument is a short hint about what to call the upload or what to look at in the project. If access hasn't been granted yet, start with /design-login.
It all happens in one pass and without questions: the project is taken apart, the design system is assembled and shipped off to claude.ai/design — and that's where you look at it.
/design-sync Acme DS/design-login
Authorizes access to the design system — the very access an upload needs. [not on every plan] — it works wherever the rest of Claude Design works, and it requires a claude.ai account login. It's split out separately because you log in once and upload many times afterwards. If /design-sync complains about access, this is where to start, and the way to check the result is /design status.
The login is confirmed in the browser; after that the access stays granted, and there's no need to repeat it before every upload.
Configuration and interface
/config [key=value]
The settings panel: with no argument it opens a panel with every setting you can change from the interface. It's the main entry point into the agent's whole behavior — from the theme to the model to the operating modes — and looking in here is easier than remembering key names in the settings file. Alias: /settings.
With an argument the setting is applied right away, no panel: /config theme=dark. The full list of accepted keys is printed by /config --help — don't guess, it's shorter than the list of keys in the settings file.
The direct form landed in 2.1.181, named shorthands like theme and model in 2.1.182. It works in non-interactive mode too, and from a phone over remote control, which makes it the main way to change a setting from a script.
There's exactly one limitation, and it isn't obvious: the key=value form can't turn on a setting that needs your confirmation in the panel. It can turn autoContinueAtUsageLimit off, for instance, but not on — turning it on comes with a dialog, and this form has nowhere to show one.
/config # open the settings panel/config --help # which keys the key=value form accepts/config theme=dark # set it right away, no panel/config model=sonnet # same for the model/permissions
Rules for allowing and denying tools, plus the auto-mode tab. You come here for two reasons: you're tired of confirming the same harmless command over and over — or, the other way round, you need to cut the agent off from something it shouldn't touch. The rule is written into the settings and applies from then on by itself, without asking. Alias: /allowed-tools.
You pick a list first — allowed, denied, or ask-first — and inside it you add your own rule or drop one you don't need; the changes take effect from that moment, no restart required.
/permissions # permission rules/theme
Change the interface color theme. The theme only affects how Claude Code draws itself in the terminal — code highlighting in diffs, borders, selections; it doesn't touch the terminal's own settings.
Besides light and dark there are colorblind-friendly variants, ANSI variants for terminals with a palette of their own, and auto, which adapts to the terminal background. Your own themes go in ~/.claude/themes/ or come from plugins; the picker itself has an item for creating a new one.
You choose from a list: the selected theme applies to the whole interface and is remembered in the settings, so the next session starts with the same one.
/theme # pick a theme/keybindings
Open or create the keyboard shortcuts file — ~/.claude/keybindings.json. In it you override interface shortcuts, including chords of two presses in a row. You need it when a shortcut you're used to gets intercepted by the terminal or the multiplexer and never reaches Claude Code at all. The file opens in an editor; if it didn't exist yet, it's created.
/keybindings # your own keyboard shortcuts/terminal-setup
Configure terminal shortcuts — Shift+Enter for a line break, for example. The edits go into the terminal's own configuration, not Claude Code's: running it once per machine is enough, but after moving to another terminal you'll have to repeat it.
/terminal-setup # Shift+Enter and other terminal shortcuts/statusline
Configure the status line: with a script of your own, or generated from your shell prompt. The status line is what Claude Code prints by the input box: usually the directory, the branch and the model, but the contents are entirely yours. The script is called whenever the line is refreshed, and whatever it prints ends up in the line.
The choice here is between two paths: build the line out of your shell prompt so it looks like the prompt you're used to — or point at your own script and decide what goes in it yourself.
/statusline # configure the status line/voice [hold|tap|off]
Voice input. [not on every plan] — dictation requires signing in with a claude.ai account: with an API key and at third-party providers it isn't there. It comes in handy when you need to dictate a long task statement instead of typing it; which mode you pick depends on how you'd rather keep your hands.
| What you passed | What happens |
|---|---|
hold | Hold the button down to talk |
tap | Tap to talk, tap to send |
off | Turn voice input off |
The argument applies right away, without a dialog: dictation switches to the mode you named.
/voice hold # hold the button down to talk/voice tap # tap to talk, tap to send/voice off # turn voice input off/tui [default|fullscreen]
The interface renderer: fullscreen is full-screen and flicker-free, default goes back to the normal one. Full-screen takes over the whole window and redraws itself, so long output doesn't jump around. The normal one writes into the terminal stream, and the terminal scrolls the history itself — if you copy chunks of output with the mouse or rely on terminal scrollback, stay on it.
Switching won't work in every session: if restrictions are in effect that a restart wouldn't carry over — permissions set for this session only, say — the command refuses and changes nothing.
/tui fullscreen # full-screen renderer, no flicker/tui default # back again
# the refusal in a session with restrictions a restart doesn't carry over# (this is how it looks in the docs):Cannot switch renderers in this session — it has restrictions a restart can't carry over (permission rules set for this session only). Nothing was changed. Running /tui fullscreen in a session started without them switches every later session too./color [color|default]
The prompt line color for the current session. This isn't a theme, it's the color of the input line specifically; handy when four terminals are open and you don't want to mix them up.
| What you passed | What happens |
|---|---|
| a color from the palette | The prompt line is painted in it until the end of the session |
| nothing | A color is picked at random — that's not a bug, it's on purpose |
default | Reset to the normal color |
The palette is fixed: red, blue, green, yellow, purple, orange, pink, cyan, plus default to reset. If remote control is connected, the color syncs to the web interface too.
/color purple # prompt line color/color # random color/color default # reset/scroll-speed
Mouse wheel scrolling speed. A purely creature-comfort setting: by default the wheel in a long session either crawls or jumps past the spot you wanted, and this is where you fix it. The command opens a speed picker, and you can check the result right there with the wheel.
/scroll-speed # mouse wheel scrolling speed/focus
Focus view: only your prompt, the tool summary and the final answer stay on screen. Everything in between — call details, the contents of files that were read, long command output — leaves the screen. You need it when the session has grown and the conversation itself gets lost behind the technical output, and also when you're showing the agent's work to someone else.
/focus # keep only the essentials on screen/hooks
A view of the hooks configured per event. A hook is your own command that Claude Code runs on an event: before a tool call, after a file edit, at the end of a turn. The panel shows what is wired to which event — it's the first place to look when a hook silently doesn't fire.
/hooks # which hooks are configured/auto-mode-setup
Tell auto mode about your environment and adjust its rules. Auto mode is work without confirming every step, and by default it plays it safe simply because it knows nothing about your project. The command walks through the environment with you and turns your answers into rules: what can be done here silently, and what must not be touched under any circumstances.
/auto-mode-setup # tell auto mode about your environment/sandbox [exclude "pattern"|install]
Configure the sandbox for commands. The sandbox limits where a running command can write and how it reaches the network, and it's exactly what lets routine work run without confirming every call. The command is only visible where the sandbox is supported.
| What you passed | What happens |
|---|---|
| nothing | The sandbox panel opens, with dependencies and overrides |
exclude "pattern" | A command matching the pattern is taken out of the sandbox |
install | Install the sandbox itself (Windows) |
exclude is for the case where a build or a container command doesn't work inside the isolation and you deliberately pull it out; the list accumulates in the sandbox.excludedCommands key.
/sandbox # sandbox panel/sandbox exclude "docker *" # take a command out of the sandbox/sandbox install # install the sandbox (Windows)/import [codex|gemini] [--dry-run] [--yes]
Migrate configuration from another coding agent: instruction files, MCP servers, commands, subagents and skills. [not on every plan] — unavailable at third-party providers and when server flag loading is turned off. codex and gemini are supported.
| Argument | What it does |
|---|---|
codex or gemini | Where to migrate from; without an argument you'll be asked |
--dry-run | Show what would be migrated, changing nothing |
--yes | Migrate without the interactive picker |
In non-interactive mode the command prints what it found and suggests the line that confirms the import. Requires version 2.1.213 or newer.
What matters is what /import does not do: the AGENTS.md file some other agents use isn't read by Claude Code on its own — but /import can carry the configuration from there over into a form it understands.
Without --yes the choice stays yours: the command shows what it found by kind and asks what exactly to take — you can grab just the MCP servers and leave commands and skills as they are.
/import codex # pull in another agent's configuration/import gemini --dry-run # see what would be migrated/import codex --yes # migrate without questions/cloud-plugins
Whether cloud sessions should use the plugins enabled on this machine. [not on every plan] — cloud sessions themselves require signing in with a claude.ai account and aren't available with an API key or at third-party providers. A cloud session runs on someone else's machine, where your set of plugins doesn't exist: this setting decides whether to drag it over there or make do with what's built into Claude Code.
The choice is simple but has consequences: with plugins a cloud session behaves like your local one; without them it works on a bare configuration, but you aren't dragging extra sources into the cloud.
/cloud-plugins # plugins in cloud sessions/skills
The list of skills, with control over their visibility.
The descriptions of every available skill sit in the context permanently, every session, whether you use them or not. With a large set of plugins that's a noticeable share of the window — which is exactly what the /skills screen is for.
You type and the list filters by name, description and source. The t key sorts by token count, and this is usually where you discover that half the window is taken up by three skills you've never used once. Space or Enter toggles a skill's visibility for the model and for the menu, Esc saves and closes.
Not everything can be toggled: plugin skills, skills with disable-model-invocation: true in the frontmatter, and ones whose visibility is set in enterprise settings or through --settings won't budge. The permanent equivalent is the skillOverrides key, and /skill-doctor helps find the ones that simply go unused.
/skills # the list of skills and their visibility/plugin
Managing plugins and marketplaces. A marketplace is the source plugins are installed from; a plugin itself brings commands, skills, subagents, hooks and MCP servers all at once, so a single plugin can noticeably change how a session behaves. Through this panel a marketplace gets connected, and a plugin gets installed, disabled and removed. Aliases: /plugins, /marketplace.
The order of selection is: the marketplace first, then a plugin inside it. Some of the changes don't take effect instantly — /reload-plugins finishes them off.
/plugin # plugins and marketplaces/reload-skills
Pick up skills and commands changed on disk without restarting the session. You need it when you're writing a skill of your own and don't want to restart on every edit. Only the files are re-read — the conversation and its context stay put.
/reload-skills # pick up skill changes from disk/reload-plugins [--force]
Activate pending plugin changes — the same as /reload-skills, only for plugins. Handy right after /plugin, when the plugin is installed but the session doesn't see it yet.
The meaning of --force here is the opposite of the intuitive one: it is not "reload harder". If the reload would change the set of loaded MCP tools, it will wipe the prompt cache, and the command warns you and refuses to do it — and --force makes it do it anyway. So the flag overrides a refusal, it doesn't dig deeper.
/reload-plugins # apply pending plugin changes/reload-plugins --force # same, even if it wipes the prompt cacheMCP and integrations
/mcp [reconnect|enable|disable [<server>|all]]
Managing MCP servers and their OAuth authorization. An MCP server is an external process or service that brings its own tools, prompts and resources into the session: an issue tracker, a database, a browser, an internal API. You come here when a server dies mid-task, when it asks you to log in again, or when its tools are only getting in the way right now — an unneeded server is better switched off than kept around with its descriptions sitting in the context. The servers themselves are declared in the configuration; here you only see their current state.
| What you pass | What happens |
|---|---|
| nothing | The list of servers and their state |
reconnect <server> | Bring a dead server back up |
reconnect all | Reconnect everything |
disable <server> | Switch a server off for now |
enable <server> | Switch it back on |
Next to each server the list shows whether it's connected, dead, or waiting for authorization — and that's what you decide from: what to reconnect and what to switch off until the end of the session. For a connected server the panel also shows how many tools it exposes, and it flags separately the one that connected but handed over none.
Servers expose their prompts as commands. They show up in the menu as /server-name:prompt-name — and that's the form worth remembering, because the other one, /mcp__server__prompt, works too but only turns up in old articles. Arguments are passed space-separated and split on spaces: every argument is one token, and there's no way to pass a quoted phrase as a single argument.
A server's resources are pulled in with @. The form is @server:protocol://path, and it's a mechanism separate from tools: not "call a tool" but "put this content into the context".
In a background session with no terminal attached the panel won't open at all: the session goes into the "needs input" state, and you're offered the /mcp enable|disable|reconnect <server> form to manage servers.
/mcp # the list of servers and their state/mcp reconnect github # bring a dead server back up/mcp disable jira # switch a server off for now/jira:create_issue login-bug high # a server prompt, the current form/ide [open]
IDE integrations and their status. That link is what makes edits visible in the editor as diffs and what puts the fragment you select there into the context, so this is the first place to go when "nothing is happening in the editor" — usually it turns out the connection never came up. With no argument it shows the status of the editor integration; with open it opens the file in the connected IDE.
/ide # status of the editor integration/ide open # open the file in the connected IDE/chrome
Claude in Chrome settings. [not on every plan] The extension only works when you're logged into a claude.ai account — with an API key and at third-party providers it isn't there. Claude in Chrome is the agent walking around the pages of your own browser: clicking, reading the page, looking at the console. Permissions are granted per site, and nothing runs without them, which is why you look in here before your first browser task.
/chrome # browser-work settingsAccount and authentication
/login
Log into an Anthropic account, or switch accounts. This is also where you choose what pays for the work — a claude.ai subscription or an API key from the Console — and that decides more than the bill: some capabilities (web sessions, the mobile app, credits beyond the plan) exist only on a subscription. Login happens in the browser; once you confirm, control comes back to the terminal.
This is where the "you need to log in again" messages send you too: Not logged in · Please run /login, OAuth token revoked · Please run /login, OAuth token has expired · Please run /login — all three are quoted verbatim from the documentation.
/login # log in or switch accounts/logout
Log out of the account. The stored credentials are wiped and the session can't work any further until you log back in — you need this when the machine is shared or when you want a clean switch to another account.
/logout # log out/setup-bedrock
Set up Amazon Bedrock: authentication, region, model pins. You need it where the work goes through AWS rather than through Anthropic directly — usually because of a requirement to keep the traffic inside your own cloud. Visible when Bedrock is on.
Together with /setup-vertex it's an example of commands hidden by state: they only appear once the matching provider environment variable is set. Until it is, they aren't in /help either.
/setup-bedrock # set up Amazon Bedrock/setup-vertex
Set up Google Cloud: authentication, project, region, model pins. The point is the same as with Bedrock: the traffic goes through your cloud and is billed there. Like /setup-bedrock, it's only visible when the provider environment variable is set.
/setup-vertex # set up Google Cloud/install-github-app
Install Claude GitHub Actions for a repository. It's the app that makes pull request reviews happen on GitHub's side rather than in your terminal. Installed once per repository; the local /code-review doesn't depend on it and works with nothing installed.
/install-github-app # put CI review on the repository/install-slack-app
Install the Slack app. [not on every plan] Claude Code in Slack requires a claude.ai login — with an API key and at third-party providers it's unavailable. Once it's installed you can hand over a task straight from a conversation and the answer lands in the same place — handy where the discussion is happening in Slack anyway. In a corporate workspace the install can run into admin rights.
/install-slack-app # install the app into Slack/privacy-settings
Viewing and changing the privacy settings: what leaves your machine out of your work and how it's allowed to be used. You come here before working on closed or someone else's code — to see the current state instead of guessing at it. On corporate accounts some of the switches are locked by organization policy.
/privacy-settings # what leaves the machineUsage and cost
/usage
Session cost, plan-limit usage and activity statistics. Aliases: /cost, /stats. You come here in two cases: when you need to know whether you'll make it to the limit reset, and when the spend suddenly jumped and you need to see what's driving it.
The screen shows three things: how much this session has spent, how full the plan limits are, and where the tokens are going — broken down by skills, subagents, plugins and individual MCP servers, plus notes on any behavior accounting for more than ten percent of the spend. The d and w keys switch the window between a day and a week, and since 2.1.242 scheduled tasks get their own lines.
Then come four things worth understanding, and not one of them is obvious.
The breakdown is computed from the local session history. That is, from the transcripts on this machine. Work from another computer or from the web interface doesn't land in it — while the limits themselves are shared across the account. The gap between "I've barely spent anything" and "the limit is nearly gone" is usually exactly this.
There are several limits, and switching models helps against only one of them. The "you've run out of the session limit" and "you've run out of the weekly limit" messages are about windows shared by every model — /model won't save you there. Only after "you've run out of the Opus limit" or "the Sonnet limit" will moving to a model from another family put you back to work. Since 2.1.234 Claude Code can wait out the reset and resume the interrupted task by itself; you turn that on through /rate-limit-options and the autoContinueAtUsageLimit key.
The prompt cache lives for an hour only on a subscription. The moment you start spending credits beyond the plan, the cache lifetime drops from an hour to five minutes — and the same lunch break that cost nothing yesterday today means reprocessing the whole context from scratch. On an API key and at the cloud providers it's five minutes by default.
The session counter resets on /clear. Before 2.1.211 it accumulated across clears, so the numbers in older articles don't line up with today's.
If the limits server is unreachable, the screen shows the last data it loaded with a note and offers a retry on the r key. While credits beyond the plan are switched on, they get a line of their own here.
The invisible spend lines that don't show up in the breakdown but really do burn the limit while you're doing nothing: scheduled tasks wake up and go off with a full context; a message from another of your sessions arrives as a new turn (cured by crossSessionInbound: "hold"); active-goal checks start turns while background work is running; every live teammate spends until it finishes. And /compact is a large request in itself, whereas /clear costs nothing.
/usage # limits, spend, breakdown# the whole output, as the author of a bug report posted itSessionTotal cost: $86.94Total duration (API): 1h 31m 17sTotal duration (wall): 1d 22h 35mTotal code changes: 2538 lines added, 312 lines removedUsage by model: claude-opus-4-8: 9.0k input, 461 output, 50.4k cache read, 29.9k cache write ($0.3802) claude-haiku-4-5: 2.0k input, 43 output, 0 cache read, 0 cache write ($0.0022) claude-sonnet-5: 86.5k input, 448.0k output, 197.4m cache read, 3.4m cache write ($86.55)
Current session: 17% used, resets 1:29pm (Europe/Madrid)Current week (all models): 19% used, resets Aug 13 at 8:59am (Europe/Madrid)# a separate line in the same place, starting with 2.1.251, about the prompt cache; this is how it looks in the documentationPrompt cache (main): 14 requests · 91% of input tokens from cache · 2 misses (last 6m 10s ago, 310.2k tokens re-cached) · 1 expected rebuild (compaction or tool-result clearing) · warm (1h TTL, last activity 40s ago)
/stats # the same, opening straight on the statistics tab/cost # the same, in the usual view/usage-credits
Set up credits so you can keep working once you hit the plan limit. [not on every plan] The command only works after logging in with a claude.ai subscription through /login; with API-key authentication it isn't there. Credits are spend paid on top of the subscription at the usual API rates, billed separately from the plan. Without them, a spent limit means simply waiting for the window to reset; with them you get an offer to continue, and the work from there on costs money.
Where exactly the command takes you depends on your role: a Pro or Max subscriber goes to the usage page on claude.ai, a Team or Enterprise member with billing access goes to the admin settings, and a member without that access is asked to confirm and has a request sent to the organization's admins. On the page itself you choose three things: whether credits are on or off, whether to set a monthly spending cap or lift it, and topping up the balance. For people who subscribed through the mobile app, enabling and topping up only work in the web version.
Remember the side effect described above: once you start spending beyond the plan, the prompt cache lives five minutes instead of an hour.
/usage-credits # switch on credits beyond the planRemote work and environments
/desktop
Continue the current session in the desktop app. [not on every plan] The app needs a claude.ai login — on an API key and at third-party providers it isn't there. The session moves over together with its context and history: you don't have to state the task again. Useful when the work is easier to continue in an app window than in the terminal. Alias: /app.
/desktop # continue in the app/teleport
Pull a web session into this terminal. [not on every plan] Web sessions are a research preview for Pro, Max and Team (on Enterprise you need a suitable seat type), require a claude.ai login and are unavailable on Bedrock, Google Cloud and Microsoft Foundry. The context, the history and the state of the work move over to you and from there you work locally — you need this when the task was set from a phone or a browser but finishing it is easier by hand. You pick from your own active web sessions; after the pick, the terminal continues the one you named. There's no separate charge for the cloud machine; it spends the account's usual limits. Alias: /tp.
/teleport # take a web session into the terminal/remote-control
Open the session up to control from a phone or from the web. [not on every plan] Requires a claude.ai login; with an API key it's unavailable. The work itself stays on your machine — from outside you only send requests and read answers, so access to the repository and the environment goes nowhere. Handy when something long is running and you want to keep an eye on it without sitting at the desk. Alias: /rc.
The refusal is clear enough: if the session isn't running through api.anthropic.com, the command names the reason outright and says which environment variable to unset.
/remote-control # open the session up to a phone# the refusal when CLAUDE_CODE_USE_BEDROCK is set — this is how it looks in the documentationRemote Control is only available when using Claude via api.anthropic.com. CLAUDE_CODE_USE_BEDROCK is set, so this session is using Amazon Bedrock — unset it (or run in a shell without it) to use Remote Control./session
Show the remote session's address and a QR code for it. You need it after /remote-control, when the link got lost or you're connecting a second device: with a phone it's easier to point the camera than to copy the address by hand. It works wherever remote control does — that is, when logged into claude.ai. Alias: /remote.
/session # the session address and a QR code/remote-env
The default environment for web sessions and teleport. The point is for the cloud machine to start up already prepared for your project instead of empty: otherwise the very first build or test run trips. Set up once, then applied to every new web session. It only concerns the web side, which needs a claude.ai login.
/remote-env # the default environment for the web/web-setup
Connect GitHub to Claude Code on the web through the local gh. That is, hand outward the access already configured on your machine instead of authorizing separately in the browser. Done once; without it a web session won't see private repositories. Like everything on the web side, it requires a claude.ai login.
/web-setup # connect GitHub to the web# this is how it looks in the documentationConnected as <your-github-username>Diagnostics and help
/help
Help and the list of available commands. The list is assembled for your session: commands hidden by state (like the cloud-provider setup) or switched off by an admin won't appear in it — which makes it the honest answer to "what do I actually have", unlike the documentation. A good check after installing a plugin: its commands should show up here.
/help # what's actually available/status
Version, model, account, API connectivity and tool statuses. The first place to go when the behavior doesn't match expectations: the wrong model, the wrong account, a setting that never arrived. It works even while an answer is being generated.
It opens the settings panel on the status tab. Besides the version, model, account and connectivity, there's a line for the kind of session: interactive for an ordinary one, background job · attached or background job · unattended for a background one — depending on whether a terminal is attached to it. The line appeared in 2.1.221.
Plus, since 2.1.243, a line in the same place about skipped sources of enterprise settings: if an admin dropped in a policy file but a different, higher-priority one is in force, you'll see here exactly which one is being ignored. It's the first thing to look at when "the admin's setting never arrived".
Per the documentation, the same tab can carry lines for the profile, the login method, the API key, the host address and the proxy, and behind a corporate gateway — provider lines with its base address.
/status # version, model, account, connectivity# lines from the status tab, as the author of a bug report posted them (build 2.1.199)Version: 2.1.199Session ID: 352ea81c-819d-4028-bba5-daef515d0815Login method: Claude Enterprise account…Model: claude-fable-5[1m] (claude-fable-5)Setting sources: User settings, Enterprise managed settings (remote)/doctor
Diagnosing the installation and putting the configuration in order. Alias: /checkup. You come here when CLAUDE.md has grown and every request drags along kilobytes of instructions, or when something behaves oddly after an update.
Since 2.1.205 this isn't a screen with a report but a full skill that edits your configuration. What it does: clears out duplicates between the local and the committed CLAUDE.md; trims the committed one, throwing away what the agent would work out from the code anyway; moves permanently loaded instructions into skills and nested files loaded on demand; offers to make auto mode the default and to pre-approve the safe commands you've been denying most often. It shows the findings first, then makes the changes.
The check picks up what's next to it as well: the health of the installation, broken settings files, unused extensions and same-named subagents in one folder — every finding comes with a proposed fix.
The terminal claude doctor is still diagnostics with no edits and no session start; it reads the settings files in the current folder without asking you to trust it.
The command stays available even when the bundled skills are switched off entirely: it's specifically marked as surviving disableBundledSkills. You can hide it with the DISABLE_DOCTOR_COMMAND variable or a "doctor": "off" entry in skillOverrides.
/doctor # check and fix the configuration/feedback [report]
Send feedback about Claude Code. You can pass the text right in the argument or type it into the field that opens. It fits "it doesn't work the way I expected" and wishes; for a concrete breakage with the conversation attached there's /bug.
/feedback # send feedback/feedback edits are applied but never show up in the diff/bug [report]
Report a bug or share the conversation. It's also what you use when you just want to hand someone a whole session turn. Before attaching the conversation it's worth remembering what's in it: internal service names, pieces of private code and everything that landed in the context go along with it. Alias: /share.
Before sending, the command asks whether to attach the conversation.
/bug # report a bug/heapdump
Take a memory dump — for diagnosing high memory use. Hidden.
It writes a memory snapshot and a consumption analysis to the desktop (to the home folder on Linux without a desktop). The command is hidden not by a server flag but by not being shown in the menu: type it out in full and it works. An important warning: when you contact support, attach only the analysis file — the snapshot itself contains your whole conversation and your credentials, and must not be shared.
/heapdump # memory dump to the desktop/insights
An analysis report on your sessions: areas of the project, work patterns, points of friction. It's a look at habits, not at money — how much was spent is what /usage shows. Worth looking at once every few weeks: the report usually surfaces something that should long since have been moved into CLAUDE.md or into a skill.
One run analyzes up to two hundred sessions it hasn't seen yet; very short ones are skipped. If anything was left out, the report header carries the total next to the analyzed count — for example, 200 sessions (412 total).
/insights # an analysis of my sessions/skill-doctor
Which of the loaded skills go unused and take up context for nothing. Every enabled skill costs room in the window: its description is always loaded, its body only when it fires, and a dozen forgotten skills noticeably narrows the useful context. From the results you decide what to switch off and what to rewrite so that it fires when it should.
/skill-doctor # which skills hang in the context for nothing/explain-usage
Where this session's tokens went, in plain language. [Skill] Unlike /usage, with its numbers and breakdown, here you get an analysis with conclusions: which turns came out expensive and why. Useful when the limit is melting faster than expected and the table doesn't make it clear what to do about it.
/explain-usage # where the tokens went/install [version] [--force]
Install a native build right from the session — no package manager, no leaving for the terminal. Useful for moving off an npm install onto the native one, or for rolling back to a specific version when a fresh one broke something important. The argument is the version: stable or a concrete number; --force installs it over the current one.
/install stable # install the stable build/install 2.1.236 --force # a specific version, over the current oneInformation and documentation
/release-notes
The list of changes by version: what appeared, what got fixed, what got switched off. Worth reading after every update — a noticeable share of Claude Code's behavior changes from build to build, and "it worked yesterday" is most often explained right here.
A nice detail: the notes are printed into the transcript but don't land in the model's context. That wasn't always the case, and showing all the changes used to mix the whole changelog into every subsequent request.
/release-notes # what changed, version by version/powerup
Short interactive lessons on the features. The point is that much of this doesn't find you on its own: plans, skills, background tasks, hooks. A lesson runs right inside the session and takes a couple of minutes — it's a way to learn about one thing rather than read the whole documentation.
/powerup # a short lesson on the features/mobile
A QR code for installing the mobile app. The app is there for working away from your desk: set a task on the move and check how it ended. Aliases: /ios, /android.
/mobile # the mobile app's QR code/radio
The Claude FM lo-fi radio in the browser. Exactly what it looks like: background music, nothing to do with the agent's work.
/radio # background music/passes
Share a free week with friends and get credits. Not everyone sees the command: it only appears on accounts that have it available — so someone else's /help may not have it.
/passes # share a free week/upgrade
Move up to Max: higher limits, more Opus. You usually land here straight from a message about a spent limit. If what you're hitting is a specific model rather than the plan, it's cheaper to try /model first — switching model family is exactly what clears that case.
/upgrade # move up to Max/stickers
Order stickers. Nothing to do with the agent's work: an order form opens.
/stickers # order stickers/team-onboarding
Generate a team onboarding guide from your usage history. The point is not having to write such a document from scratch: it's assembled from how you actually work, not from generic advice. What comes out is text you edit by hand and put in the repository.
/team-onboarding # a team guide from my historyRemoved and disabled commands
They have no sections of their own — there is no point typing them. The table is here because half the articles on the internet still recommend them, and when a command "doesn't work", this is the easiest place to look.
Removed entirely:
| Command | What happened to it |
|---|---|
/vim | Removed in 2.1.92. The key mode is switched in /config with the "Editor mode" field, or with the editorMode key. |
/pr-comments | Removed in 2.1.91. Just ask the agent to show you the pull request comments. |
/output-style | Deprecated in 2.1.73 and removed in 2.1.91. The reply style is set with the outputStyle key. |
/ultraplan | Removed. Use planning mode instead, /plan. |
/agents | Formally still there, but all it does is tell you that subagents are created as files in .claude/agents/. Background agents are claude agents in the terminal. |
/extra-usage | Renamed to /usage-credits in 2.1.144. |
/init-verifiers | Never existed — if you met it in somebody's article, it's an invention. |
--enable-auto-mode | The flag was removed in 2.1.111. Use --permission-mode auto instead. |
Disabled from the inside in build 2.1.251: registered, but they don't work and don't show up in the menu.
| Command | What to use instead |
|---|---|
/version | The session version is shown by /status, the binary version by claude --version. |
/update (alias /restart) | To update, run claude update in the terminal. |
/loops | What is running and how often is shown by /usage; the loops themselves are created by /loop. |
/wellbeing (aliases /breaks, /break-reminder, /downtime) | The settings themselves work: the breakReminder and quietHours objects in the settings file. |
/pause-memory (aliases /memory-pause, /toggle-memory) | Auto-memory is turned off with the autoMemoryEnabled key. |
There are also commands that appear depending on state, and you won't see them until that state arrives: /limit-reset and /low-priority — when you've hit the session limit, /rate-limit-options, /pro-trial-expired, /design-consent and /design-revoke, while /setup-cowork only lives in Cowork mode. Plus two entirely internal entry points, __remote-workflow and workflow-launch-exec, through which the server hands a ready-made workflow to the session.
And a category of its own — model-only skills: keybindings-help, memory-types, cowork-plugin. The agent pulls them in by itself; you can't type them. The mechanism is general and available to you too — it's the user-invocable: false field in a skill's frontmatter.
Two stubborn misconceptions to finish with. There is no /alias command: what sits in the binary under that name is a description of the system alias utility, used for completing commands entered with !. And there is no .claudeignore file either — to make the agent ignore files, use .gitignore, which is respected by default, or .ignore.
How the menu finds a command
A small thing that saves your nerves. Since version 2.1.236 the menu highlights a command if the letters after / match its name or one of its aliases — from the start of the name or from the start of a word inside it, with the separators :, _ and - ignored during the comparison. That's why /adddir highlights /add-dir, and /new highlights /clear through its alias.
What changed at the same time and matters more: a typo is no longer guessed. Enter on a non-existent command used to launch a similar one. Now nothing is highlighted after a typo, the close matches stay in the list and are picked with the arrows or Tab, but Enter sends your text as-is and reports an unknown command.
Unavailable commands simply vanish from the menu — you'll see "no commands match your query". Some answer with their own unavailability message instead: /schedule on an API key, for example, will say it requires an account. And you can't drag a hidden command out by a partial name — you have to type it in full.
Your own commands
Your own slash command is a SKILL.md file in a skill folder. There used to be a separate entity for this in .claude/commands/; commands and skills are now merged into one, and the old files keep working and give you exactly the same command.
Where to look and where to put them:
| Location | Scope | Command name |
|---|---|---|
~/.claude/skills/<name>/SKILL.md | personal, in every project | /<folder name> |
<project>/.claude/skills/<name>/SKILL.md | project-level, committed | /<folder name> |
.claude/commands/<name>.md | the old form, still works | /<file name> |
| a plugin | wherever it was installed from | /<plugin>:<name> |
The command name comes from the folder name, not from the name field. For personal and project skills, name is only the label in the list. For plugin ones it's the other way round: name replaces the last segment, so my-plugin/skills/review/ with name: fancy gives /my-plugin:fancy. The short form /fancy works too, as long as nobody else has taken that name.
The simplest example:
---name: fix-issuedescription: Work through an issue by number, find the cause and propose a fixargument-hint: <issue number>allowed-tools: Bash(gh issue view:*), Bash(gh pr create:*)---
Take issue number $0 from this repository.
The current state of the branch:
!`git status --short`
Read the description, find the cause in the code, propose the minimal fixand explain why it is minimal.You call it as /fix-issue 4821. Here $0 is the first argument, that is 4821, and the line with ! runs before the text reaches the model and is replaced with its own output. More on both below.
Frontmatter fields
There are twenty of them. It's useful to know they exist at all — half of them solve problems people otherwise solve with hacks.
| Field | What it sets |
|---|---|
name | The name; for personal and project skills, only the label |
description | The description the model uses to decide whether the skill fits |
when_to_use | A clarification of when to pick it |
argument-hint | The argument hint in the menu |
arguments | A list of named arguments mapped positionally onto $name |
disable-model-invocation | Forbid the model from invoking the skill by itself |
user-invocable | false — the skill is model-only, you can't type it |
allowed-tools | What to pre-approve for this turn |
disallowed-tools | What to forbid |
model | The model for the rest of the turn; accepts inherit |
effort | The effort level: from low to max |
context | fork — run the skill in a subagent |
agent | Which agent type to take with context: fork |
background | false — wait for the forked skill's result |
hooks | Hooks that live together with the skill |
paths | Restrict automatic activation to these paths |
shell | What to run embedded commands with: bash or powershell |
metadata | Arbitrary data |
license | The license |
compatibility | Compatibility requirements |
Three limitations people trip over. Frontmatter is read only if the opening --- is the very first line of the file. The description and when_to_use fields are cut down to fifteen hundred characters in the listing — anything longer the model won't see when it's choosing a skill. And in the old files in .claude/commands/ the same frontmatter works, except for name and paths — those are ignored there.
A separate word about allowed-tools: it's a pre-approval for one turn, not a restriction. The permission is dropped with your next message, though the skill's content stays in the context. And it has an unpleasant property worth knowing for anyone who runs the agent in someone else's repository: folder trust does not hold it back. A project skill applies its allowed-tools even in a folder you never marked as trusted, non-interactive runs included. Which means a skill sitting in a repository can grant itself broad rights — read this field in other people's repositories before you run anything.
Arguments: numbering starts at zero
The most unexpected corner of the whole topic, and one worth memorising word for word.
| Substitution | What gets substituted |
|---|---|
$ARGUMENTS | The whole argument string exactly as you typed it |
$ARGUMENTS[N] | The argument at that index, indexing starts at zero |
$N | The short form: $0 is the first argument, $1 the second |
$name | An argument from the arguments list in the frontmatter, by position |
Yes, $0 is the first argument, not the command name as in a shell. The off-by-one here is the most common mistake.
Indexed arguments are parsed with quoting in mind: in /my-skill "hello world" second the value of $0 is hello world as a whole. An indexed substitution that ran out of arguments stays in the text as-is; a named one turns into an empty string. An argument value that itself contains $1 or $ARGUMENTS is inserted literally and not expanded a second time. Escaping uses a single backslash: \$1.00. And if no substitution in the body got any arguments at all, the line ARGUMENTS: <value> is simply appended at the end.
Embedded shell commands
The form !`command` runs before the content reaches the model and is replaced with its output. That's how a skill gets the current state fed into it: the branch, the diff, the list of failing tests. Which shell runs it — bash or powershell — is set by the shell field in the frontmatter.
There are two rules that save you half an hour of head-scratching. The form is recognised only if the ! stands at the start of a line or right after a space — in KEY=!`cmd` it stays text and doesn't run. And the substitution pass goes over the file once: a command's output is not scanned again, so a command can't print another substitution and count on a second pass.
For a multi-line script, open a code block with an exclamation mark after the three backticks.
All of this is switched off with the disableSkillShellExecution key: every command is replaced with a stub saying it's forbidden by policy. It applies to user, project and plugin skills and to skills from added folders; built-in and enterprise ones are left alone. Skills synced from claude.ai never run such commands locally, whatever the setting says.
Path variables
Inside a skill's body and inside allowed-tools rules these get substituted: ${CLAUDE_SKILL_DIR} — the skill's own folder, ${CLAUDE_PROJECT_DIR} — the project root, ${CLAUDE_SESSION_ID}, and in plugin skills also ${CLAUDE_PLUGIN_ROOT} and ${CLAUDE_PLUGIN_DATA}.
The fact that they work in both places isn't a detail, it's a working trick: it's how a skill runs its own script without a single question about permissions.
---name: renderdescription: Render a diagram from its sourceallowed-tools: Bash(${CLAUDE_SKILL_DIR}/scripts/render.sh *)---
Run `${CLAUDE_SKILL_DIR}/scripts/render.sh $0` and show the result.The rule allows exactly the command the body tells it to run — no wider, no narrower.
Small things worth knowing
Skills stack. You can put up to six commands at the start of one message: /write-tests /fix-issue 123 loads both skills and passes 123 to both as arguments. Before version 2.1.199 only the first one was loaded and the rest counted as text. The exception is /code-review, which takes the rest of the line for itself.
ultrathink in a skill's body asks the model to think harder when the skill fires. It works as a plain word in the text.
Built-in command names are reserved, even if they're unavailable in your session: a skill with a conflicting name that arrives from sync will be skipped.
You can validate a skill without a plugin: claude plugin validate <path> works on an ordinary folder of skills and agents too. And to turn a folder of skills into a plugin, it's enough to drop .claude-plugin/plugin.json into it.
Settings: settings.json
Next come the keys of the settings file, experimental and enterprise ones included, with types and examples. The list is merged from two sources: the official settings reference, which currently holds about two hundred and twenty entries, and the validation schema inside the CLI itself. They don't match: the schema has keys the documentation doesn't, and the other way round — the documentation has keys the schema knows nothing about, because they live in a different file. More on that separately below.
Notation: [exp] — an experimental or internal key, may change or disappear; [admin] — takes effect only from an enterprise source; [deprecated] — deprecated; [global] — lives not in settings.json but in ~/.claude.json.
Where the file lives
There aren't four levels, or five, but more than is usually written about. Let's start with the ordinary ones:
| Level | File | Purpose |
|---|---|---|
| User | ~/.claude/settings.json | Personal settings across all projects |
| Project | <project>/.claude/settings.json | Team settings, committed to the repository |
| Local | <project>/.claude/settings.local.json | Personal, for one specific project, in .gitignore |
| Command line | --settings <file or JSON> | For a single run only |
| Policy | depends on the system | Enterprise policy |
| Global config | ~/.claude.json | Settings that are ignored in settings.json |
That last row is the one almost nobody mentions. Some settings live only in ~/.claude.json, and if you write them into settings.json they're silently ignored. That's also where Claude Code keeps your login session, the MCP server configuration and folder trust decisions. Normally this file writes itself and people rarely go into it by hand — but you need to know it exists, because "I set the key and nothing happened" is most often explained by exactly this.
Enterprise policy isn't a single thing either. There are four sources, and they're ranked:
| Rank | Source |
|---|---|
| 1 | Server-side settings from claude.ai or an enterprise gateway |
| 2 | Operating system policy: the managed settings domain on macOS, the HKLM\SOFTWARE\Policies\ClaudeCode registry key on Windows |
| 3 | The managed settings file: /Library/Application Support/ClaudeCode/managed-settings.json, /etc/claude-code/managed-settings.json, C:\Program Files\ClaudeCode\managed-settings.json |
| 4 | The same registry key, but in HKCU — writable by the user themselves, and therefore not counted as administrative and applied only where nothing above it exists |
The system policy and HKCU are re-read every half hour, the server-side settings once an hour. By default the sources do not add up: the highest-ranked one applies and the rest are dropped. You can change that with the managedSourcesBehavior: "merge" key, but it has to be set in the highest of the deployed sources — a lower one can't ask itself into the merge, and HKCU is never merged.
If an admin put something in place and it "didn't arrive", look at /status: since version 2.1.243 there's a line there about skipped sources that says outright which file was ignored.
The format: strict JSON
Here I have to correct myself, because I used to think otherwise and the internet repeats it often.
Settings files are strict JSON. A // comment or a trailing comma is a syntax error, and on the next run the file will be flagged as broken as a whole. No JSONC. (The confusion comes from JSONC really being in the product elsewhere — /terminal-setup, for example, parses the editor configuration with comments in it.)
The easiest way to check your file is to run it: settings errors are printed at startup. claude doctor will show them broken down.
A useful habit is the $schema line:
{ "$schema": "https://json.schemastore.org/claude-code-settings.json"}Your editor will start suggesting key names and underlining typos, and a typo in a key name is the most common reason a setting "doesn't work": unknown keys are silently ignored. One caveat: the schema sometimes lags behind the product. teammateDefaultModel, for instance, is still in it, but it was removed from Claude Code in 2.1.234 and affects nothing.
Who overrides whom
The order of the levels is the one in the table above. But "overrides" isn't true for everything, and here are the three exceptions that break the intuition.
Lists add up, they don't replace. If permissions.allow is set both in the user file and in the project one, you get the union of the two. An upper level cannot remove an entry from a lower one — the only thing that can is the enterprise allowManagedPermissionRulesOnly. Any priority table that says "each next one overrides the previous" is wrong for lists.
Four lists behave differently: fallbackModel is taken whole from the highest file that defines it (it's an ordered chain, and mixing it makes no sense); modelPicker — whole from the highest among the enterprise source, --settings and the user file, while in the project and local files it's ignored; availableModels from the admin applies as-is, without picking up your additions; modelSettings is resolved separately for each model.
For seven keys, a stricter value from below beats the enterprise one. Normally policy is absolute — not even --settings overrides it. But for these keys the stricter variant from any level wins, because nobody is going to stop you from forbidding yourself more than you have to: disableClaudeAiConnectors with the value true, enableArtifact with the value false (and disableArtifact: true), isolatePeerMachines with the value true, remoteControlAtStartup with the value false from a project or local file, crossSessionInbound with a stricter value on the "accept — hold — reject" scale, useAutoModeDuringPlan and syncClaudeAiSkills with the value false.
Project permissions wait for folder trust. permissions.allow and permissions.additionalDirectories from the project file only start working once you've confirmed trust for that folder. deny and ask take effect immediately — they only restrict.
And what comes next is the most important part, worth reading for everyone who runs claude -p in someone else's repository. In non-interactive mode the trust dialog isn't shown, so the project's permissive rules are dropped with a warning on the error stream — but that repository's hooks do run, its env block is applied, its authentication helper scripts are launched, the allowed-tools field of its skills takes effect, and the servers from its .mcp.json connect without asking. What gets dropped is the permissions, not the executable parts.
A safe run in an unvetted folder is --setting-sources user, --bare, --restricted or --settings '{"disableAllHooks": true}'. Simply setting disableAllHooks in your own user file is not enough: the project file ranks higher and will turn it back on.
Environment variables aren't a level
Another thing that's usually drawn wrong. Environment variables don't sit "between" the settings levels: who overrides whom is decided separately for each variable-and-key pair.
ANTHROPIC_MODELfrom the shell overrides themodelkey from any file.ANTHROPIC_DEFAULT_MODELonly takes effect ifmodelisn't set anywhere.--modeland/modeloverrideANTHROPIC_MODEL.- And
CLAUDE_CODE_EFFORT_LEVELworks the other way round and overrides--effortand/effort.
And separately: a value from the env block in the settings beats an export from the shell, not the other way round as people tend to assume. Claude Code writes every entry of the block into the process environment on top of the inherited value. You can't delete a variable from the settings file — you can set it to an empty string, which counts as "not set" when a provider is being chosen (though child processes will get the empty value). Shell variables are read once at startup, while values from env are re-read when the file changes — except in subsystems that are only configured at launch, like telemetry.
The skeleton of the file
Scalars like model, theme, numbers and flags are written at the top level. Grouped settings — permissions, env, hooks, statusLine, worktree, voice, sandbox, sshConfigs — are nested objects.
{ "$schema": "https://json.schemastore.org/claude-code-settings.json", "model": "opus", "outputStyle": "default", "theme": "dark", "autoCompactEnabled": true, "cleanupPeriodDays": 30, "includeCoAuthoredBy": false, "env": { "CLAUDE_CODE_USE_POWERSHELL_TOOL": "1", "DISABLE_TELEMETRY": "1" }, "permissions": { "allow": ["Bash(npm run build)", "Edit(src/**)"], "ask": ["Bash(git push:*)"], "deny": ["Read(./.env)"], "defaultMode": "acceptEdits", "additionalDirectories": ["../shared-lib"] }, "hooks": { "PostToolUse": [ { "matcher": "Edit|Write", "hooks": [{ "type": "command", "command": "npm run lint" }] } ] }, "statusLine": { "type": "command", "command": "~/.claude/statusline.sh", "padding": 1 }, "worktree": { "symlinkDirectories": ["node_modules"], "baseRef": "fresh" }, "enabledPlugins": { "formatter@anthropic-tools": true }}Authentication and providers
| Setting | Type | What it does |
|---|---|---|
apiKeyHelper | string, path to a script | A script that prints the authorization value to standard output. Handy for temporary and rotated keys. |
proxyAuthHelper | string, command | [experimental] A command that prints the proxy authorization header value. |
awsCredentialExport | string, path | A script that exports AWS credentials for Bedrock. |
awsAuthRefresh | string, path | A script that refreshes AWS authentication before it expires. |
gcpAuthRefresh | string, command | A command that refreshes Google Cloud authentication. |
otelHeadersHelper | string, path | A script that prints HTTP headers for telemetry export. |
policyHelper | object | [admin] An executable that computes policy settings at startup: path, timeoutMs, refreshIntervalMs. |
policyHelpers | object keyed by OS | [admin] The same, but separately for macOS, Linux, Windows and WSL. |
forceLoginMethod | claudeai, console, gateway | Pin the login method: subscription, billing through the Console, or a corporate gateway. |
forceLoginOrgUUID | string or array | [admin] Allow login only into the named organization, or into any one from the list. |
forceLoginGatewayUrl | string, URL | [admin] Mandatory corporate gateway address for login. |
forceRemoteSettingsRefresh | boolean | [admin] Block startup until fresh policy settings have been pulled. |
parentSettingsBehavior | first-wins, merge | [admin] How the parent layer coming from the SDK combines with the admin one. |
xaaIdp | object | [experimental] Hooking up an external identity provider: issuer, clientId, callbackPort. |
The gateway value of forceLoginMethod is only honoured from a source that lives on the machine itself: the policy file, the macOS settings domain, or the HKLM branch. In user, project, local and HKCU settings it counts as unset — otherwise corporate login could be redirected from a repository.
Model, thinking, effort
| Setting | Type | What it does |
|---|---|---|
model | string | The default model: an alias or a full identifier. |
availableModels | array of strings | [admin] Model allowlist. An empty array means the default model only. |
enforceAvailableModels | boolean | [admin] Apply the allowlist to the "default" entry in the model picker as well. |
modelOverrides | object | [admin] A mapping from Anthropic identifiers to provider identifiers. |
modelPicker | object | Your own list in /model: entries of {model, label, description}; replaceBuiltInOptions replaces the built-in one. |
modelSettings | object | Settings tied to a specific model — right now, the effort level. |
modelPricing | object | [admin] Your organization's rates instead of the price list: a discount multiplier and per-unit prices. |
advisorModel | string | The model for the advisor. |
agent | string | The agent name for the main thread: its system prompt, its restrictions and its model. |
alwaysThinkingEnabled | boolean | false turns thinking off. |
showThinkingSummaries | boolean | Show thinking summaries in the conversation and in the transcript. |
effortLevel | low, medium, high, xhigh | The saved effort level. The schema does not accept max. |
ultracode | boolean | [experimental] xhigh plus permanent workflow orchestration. |
fastMode | boolean | Whether fast output mode is on. |
fastModePerSessionOptIn | boolean | Don't carry fast mode over between sessions. |
autoCompactEnabled | boolean | Compact the conversation automatically as the context fills up. |
autoCompactWindow | number, 100000–1000000 | The size of the auto-compaction window, in tokens. |
precomputeCompactionEnabled | boolean | Prepare the compaction ahead of time, while work is still going on. |
switchModelsOnFlag | boolean | Switch to a different model when a safety filter fires. Defaults to true. |
fallbackModel | array of strings | Models to fall back to when the primary one is overloaded; tried in order. |
promptCacheTtl | 5m, 1h | The prompt cache lifetime for the main conversation. |
subagentPromptCacheTtl | 5m, 1h | The same for subagents; five minutes by default. |
Three defaults that change behaviour and that hardly anyone writes about.
switchModelsOnFlag is on. Which means that when a safety filter fires, the model quietly changes so the conversation isn't interrupted. Turn it off and an interactive session will stop and ask you, while a non-interactive run will fail the request with an error — which is often the better choice for scripts, because a silent model swap in CI looks like an unexplained change of behaviour.
promptCacheTtl picks itself: an hour on a subscription, five minutes otherwise. The environment variable overrides it.
effortLevel refuses max deliberately, so that the maximum level never stays switched on forever; you set it for one session with a command or a flag.
Tool permissions
The most practically important part of the file — and the most underrated for the sheer number of gotchas in it. The nested permissions object:
| Field | Type | What it does |
|---|---|---|
allow | array of rules | What's permitted without asking. |
deny | array of rules | What's forbidden always. |
ask | array of rules | What always requires confirmation. |
defaultMode | see below | The default mode. |
disableBypassPermissionsMode | "disable" | Forbid the permission-bypass mode. |
additionalDirectories | array of paths | Extra directories inside the access scope. |
Alongside them sit top-level keys: skipDangerousModePermissionPrompt and skipAutoPermissionPrompt remember that you've already accepted the corresponding warning; allowManagedPermissionRulesOnly [admin] tells it to honour only the lists coming from policy; disableAutoMode turns auto mode off; useAutoModeDuringPlan allows it inside plan mode, and defaults to yes.
Modes
| Mode | What it does |
|---|---|
default | The usual one: ask when it needs to. The alias is manual, accepted in settings too since 2.1.200 |
acceptEdits | Accept file edits automatically |
plan | Analysis only, change nothing |
auto | A classifier makes the call |
dontAsk | Automatically refuse anything that would have needed a question |
bypassPermissions | Accept everything |
dontAsk doesn't mean "don't bug me about the small stuff". It's the most dangerous misunderstanding in the whole permissions topic, and I've made it myself. The mode doesn't loosen things, it tightens them: everything that would raise a question in normal mode is automatically denied. Only what made it into allow, the built-in set of safe read commands, and whatever a hook approved will run. Your own ask rules don't ask in this mode, they refuse; a question from the agent to you gets rejected as well, even when it's permitted.
One more subtlety: the auto value has no effect from project and local settings — it has to be set in the user file. And sessions launched from the VS Code extension read only the user file, the enterprise one, and --settings.
Rule format
A rule is written as Tool(specifier): Bash(npm run build), Edit(src/**), Read(~/.zshrc).
{ "permissions": { "allow": ["Bash(npm run:*)", "Edit(src/**)", "Read(~/.config/**)"], "ask": ["Bash(git push:*)"], "deny": ["Read(./secrets/**)", "Read(./.env)"], "defaultMode": "acceptEdits", "additionalDirectories": ["../shared", "/tmp/workspace"] }}Looks simple. What follows is twelve rules of behaviour, each of which explains one popular "why doesn't my rule work" question.
The order of checks: deny first, then ask, then allow
Rules are checked in a fixed order — deny, then ask, then allow — and the first match wins, not the most specific one. Two consequences follow from that, and both break expectations.
A broad deny overrides a narrow allow: a deny of Bash(aws *) will block an allow of Bash(aws s3 ls). There are no exceptions to a deny — there's no "forbid everything except" mechanism here.
A matching ask asks even when a more specific allow exists. That isn't a bug, it's how you say "I always confirm this command by hand", and it works on top of any permission.
Between settings layers it's the same story: a deny in the user file beats an allow in the project file and vice versa, because every deny from every layer is checked before any allow.
Another small thing with large consequences: a bare tool name in deny removes the tool from the context entirely. An entry of "Bash" in the deny list means the agent never even learns that the tool exists. Bash(rm *), by contrast, leaves the tool visible and forbids only the matching calls.
Protected paths are checked before your rules
There is a list of paths whose writes are checked before anything looks at allow. Which is why Edit(.claude/**) in any settings file does precisely nothing — and it's the single most common source of "why is my permission being ignored" questions.
The protected directories: .git, .config/git, .vscode, .idea, .husky, .cargo, .devcontainer, .yarn, .mvn and all of .claude except .claude/worktrees. Among the files — .gitconfig, .gitmodules, every shell profile and startup file, .envrc, .npmrc, .yarnrc*, .pnp.cjs, bunfig.toml, .bazelrc, .pre-commit-config.yaml, lefthook.*, gradle-wrapper.properties, .ripgreprc, pyrightconfig.json, .mcp.json and .claude.json.
The logic is clear enough: these are all files whose contents change how your own machine behaves on the very next command, up to and including what gets executed instead of git commit. What happens on an attempt depends on the mode: normal and acceptEdits ask, plan allows it only if a bypass is available, auto hands it to the classifier, dontAsk refuses, bypassPermissions allows. The dialog also carries a separate option — permit edits to your own settings for this session.
The safety catch on deletion
rm and rmdir aimed at critical paths cannot be approved by anything: not by an allow rule, not by a hook that returned permission.
The critical paths are the filesystem root and any of its immediate children, the home folder, the drive roots on Windows and their first-level directories, the current working folder and its parents, and glob patterns inside added directories.
The interesting part is the table by mode, because it isn't laid out the way anyone expects:
| Mode | What happens |
|---|---|
normal, acceptEdits, plan | Asks |
auto | Hands it to the classifier |
dontAsk | Refuses |
bypassPermissions | Asks |
So the "skip every confirmation" mode is stricter here than auto mode: --dangerously-skip-permissions will still stop on a deletion like that.
Things that look harmless count too: rm -rf "$DIR"/* falls under the safety catch, because an empty variable turns it into a deletion starting at the root. Hiding the command in a substitution, in backticks, or in a process substitution won't help — the check sees through all of them.
Four path anchors
Read and Edit rules use .gitignore syntax, and it has four different ways to anchor a path. People mix them up constantly.
| Form | Anchored to |
|---|---|
//path | The filesystem root |
~/path | The home folder |
/path | The settings source, not the drive root |
path or ./path | The current working folder |
The third row is the trap. A single leading slash does not mean an absolute path: it anchors the rule to the settings file the rule is written in. Read(/secrets/**) in ~/.claude/settings.json means ~/.claude/secrets/**, and not secrets in your project at all. In project settings that same slash counts from the main working folder, in --settings from the folder of the file you named, and rules from local settings have, since 2.1.211, been anchored to the session's working folder rather than the repository root — so in a separate working copy Edit(/src/**) lands in that copy's own src.
A bare filename behaves exactly as it does in .gitignore and matches at any depth: Read(.env) is the same thing as Read(**/.env). Read(//**/.env), on the other hand, is anchored to the filesystem root.
On Windows, paths are converted to POSIX form before comparison: C:\Users\alice becomes /c/Users/alice. So a rule covering every drive is written //**/.env, and one covering a particular drive //c/**/.env.
The same rule catches different depths in allow and in deny
A single-segment relative folder pattern behaves asymmetrically, and that's on purpose.
Edit(src/**) in allow matches only the src folder at the root of the working directory. The very same rule in deny or ask matches a src folder at any depth — so it will catch vendor/pkg/src/lib.js too.
The reasoning is clear: a permission should be narrow, a prohibition broad. Every other form behaves identically in any kind of rule: Edit(/src/**) and Edit(src/components/**) match only where they're written, Edit(**/src/**) matches everywhere. The behaviour changed in 2.1.214: before that, Edit(src/**) caught any depth in permissions as well.
The colon works only at the end, and the space before the asterisk matters
The form Bash(ls:*) is exactly the same thing as Bash(ls *). But it's only recognized at the end of the pattern: in Bash(git:* push) the colon is an ordinary character, and the rule won't match anything at all.
The space before the asterisk is part of the rule. Bash(ls *) requires a space and therefore doesn't match lsof; Bash(ls*) does. A trailing asterisk also catches the bare command with no arguments, but only when it's the only asterisk in the rule: Bash(ls *) will match ls, while Bash(* --help *) will match npm --help x and won't match npm --help.
Everything before the first asterisk is compared literally. Hence an unpleasant surprise: Bash(git * main) permits any git subcommand, -c with arbitrary configuration included. Since 2.1.246 a warning is printed at startup for allow rules with an asterisk in front of the subcommand.
Compound commands
The separators Claude Code understands: &&, ||, ;, |, |&, & and a newline. Every part has to match a rule on its own — there's no blanket permission for the whole line.
A special case: if an operator ends up at the end with nothing after it — npm test &&, say — the command counts as unparseable and isn't split at all. And then not even Bash(npm *) will approve it.
When you answer "yes, and don't ask again" to a compound command, a separate rule is saved for each part that needed one. Stepping into a subfolder will spawn its own read rule. No more than five rules get saved out of one command.
Output redirections >, >>, 2> are checked as a file write — against your Edit rules, the protected-path list and the working directories. /dev/null is excluded from the check; a target that starts with ~ or contains a glob always requires confirmation.
Which wrappers get stripped and which don't
Before matching against the rules, these get stripped from the command: timeout, time, nice, nohup, stdbuf, the built-in command and builtin, zsh's noglob, and a bare xargs — that last one only without flags, since xargs -n1 grep is parsed as the command xargs.
A leading assignment to a known safe variable is stripped too, so Bash(npm test *) will match NODE_ENV=test npm test. An allow rule won't get past an assignment to any other variable; a deny rule gets through any of them.
The list is fixed and not configurable. And there isn't a single environment launcher on it: npx, docker exec, direnv exec, devbox run, mise exec are not stripped. The practical upshot: Bash(devbox run *) is a permission for devbox run rm -rf ., because as far as the check is concerned the command is devbox, not rm.
Separately, there are commands that can never be approved by a prefix rule: watch, setsid, ionice, flock, and find with -exec or -delete. In normal mode they always ask.
Rules for Write, Glob, NotebookEdit and MultiEdit are accepted and do nothing
File permissions are checked only against Edit(...) and Read(...) rules. A rule like Write(docs/**) or Glob(docs/**) will be parsed, saved, shown in /permissions — and never used. Since 2.1.210 a warning is printed at startup for one of these.
Write Edit(...) instead of Write, NotebookEdit and MultiEdit, and Read(...) instead of Glob. A bare tool name with no path does work, though: you can forbid Write wholesale.
A useful consequence: a Read deny rule on a path blocks editing and writing there as well — but not NotebookEdit.
Symbolic links
Every file access is checked against two paths at once: the link itself and wherever it points. And the rules are asymmetric about it.
A permission applies only when both paths match. So a link inside a permitted folder that points outside it will still ask.
A prohibition applies when at least one matches. So a link to a forbidden file is forbidden itself.
In practice: if Read(./project/**) is allowed and Read(~/.ssh/**) is denied, then ./project/key pointing at ~/.ssh/id_rsa will be blocked.
Rules on tool parameters
A little-known family. Deny and ask rules can match on a scalar field of the tool's input:
{ "permissions": { "deny": ["Agent(model:opus)", "Agent(isolation:worktree)", "Bash(run_in_background:true)"] }}One parameter per rule, nested fields aren't supported, * stands in for the value. A parameter the model didn't pass never matches — meaning Agent(model:opus) won't catch a call where no model was specified at all. The value is compared against what actually arrived, before normalization: the alias opus will match, the full identifier of the same model won't.
The tool's main field deliberately isn't matched this way: command, file_path, path, notebook_path, url are excluded. A Bash(command:rm *) rule is ignored with a warning — it would be far too easy to get around with a compound command.
For MCP tools, parameter rules work only through the --disallowedTools flag: any rule with mcp__ and parentheses in a settings file is skipped and ends up in the list of invalid settings and in the claude doctor output.
Wildcards in the tool name
In deny and ask rules the tool name can be given as a pattern, and the pattern has to cover the whole name: "*" means every tool, "mcp__*" every MCP tool.
In allow rules a pattern is permitted only after a literal mcp__<server>__ prefix, and the server name itself must be wildcard-free. So mcp__github__get_* works, while "*", "B*" and "mcp__*" in allow are skipped with a warning and permit nothing.
And one more trap: the tool name on screen can differ from the canonical one. What's shown as "Stop Task" is canonically called TaskStop, and only the canonical name works in rules and in hook filters.
WebFetch — two different rules that look alike
A bare WebFetch and WebFetch(domain:*) are not the same thing, because the second form also edits the sandbox's domain list.
| Rule | What it does |
|---|---|
allow: WebFetch | Fetches pages without asking, but doesn't widen the sandbox — curl from inside the sandbox to that same host will still ask |
allow: WebFetch(domain:*) | Plus grants the sandbox network access |
deny: WebFetch | Removes the tool entirely |
deny: WebFetch(domain:*) | The tool stays, every fetch is rejected, the sandbox's network is closed |
Wildcards in a domain: *.example.com catches subdomains at any depth, but not example.com itself. In any other position the asterisk matches only the text between two dots — example.* will catch example.org and won't catch example.evil.com.
And a sober note: as long as the agent has shell access, WebFetch permissions restrict network access in no way whatsoever.
The built-in set of safe commands
Some commands run without a question in any mode, and that list is hardcoded: ls, cat, echo, pwd, head, tail, grep, find, wc, which, diff, stat, du, cd and the read-only forms of git. You can't extend it; you can only override it with your own ask or deny rule.
Even it will ask, though, if: an unquoted glob turns up in a command that has write or execute flags (find, sort, sed, git — the glob could expand into -delete); docker has -H, --context, --url or --connection; file has -m, --magic-file, -f or --files-from; there's a Windows network path among the arguments; the command runs longer than ten thousand characters or doesn't parse. Plus cd together with git will ask if the folder really changes — the new folder may have git hooks of its own.
PowerShell
PowerShell rules are built the same way, are compared case-insensitively, and canonicalize the popular aliases: PowerShell(Get-ChildItem *) will match gci, ls and dir alike. The command is parsed into a syntax tree and split on | and ;, and on version seven on && and || as well; each part is checked separately.
Remove-Item has a check of its own, stricter than the one for rm: system paths and targets with a glob — a bare *, anything ending in /* or \*, $dir/* included — are forbidden in every mode without a question, before the classifier even gets a look. Only the "working folder or its parent, recursively" case goes through the normal mode rules, and that one does come off with a permissions bypass.
And a Windows-specific note: any command with a network path of the form \\server\share\file among its arguments will ask for confirmation even when it's harmless in every other respect — a path like that can walk off with your Windows credentials.
Auto mode
Since 14 August 2026 this is the default mode for new sessions on Pro, Max and Team. Every action is decided by a classifier rather than a list of rules, and it's configured through a separate autoMode object.
| Field | Type | What it does |
|---|---|---|
autoMode.environment | array of strings | What the classifier needs to know about your environment. This is exactly what /auto-mode-setup fills in. |
autoMode.allow | array of strings | What it lets through. |
autoMode.soft_deny | array of strings | What it asks you about. |
autoMode.hard_deny | array of strings | What it forbids without asking. |
autoMode.classifyAllShell | boolean | Whether to run every single shell command through the classifier. Off by default. |
Three things here matter more than the table itself.
The "$defaults" entry is almost always mandatory. In any of the four lists it mixes in the standard set of rules. Leave it out and the entire built-in list for that section silently disappears — together with the soft blocks on force-push, on curl | bash, on deploying to production and on bypassing auto mode itself, and with the hard block on data exfiltration. Your rules are supposed to extend the set, not replace it.
Narrow permissions bypass the classifier. A rule like Bash(npm test) stays in force under auto mode and is resolved before the classifier. Only broad permissions for arbitrary execution are suspended — Bash(*), interpreters with a wildcard — along with every rule that names the monitoring tool. Which means a narrow rule can wave through a destructive argument nobody ever looked at. The fix is classifyAllShell: true, and then every shell allow rule is switched off for the duration of auto mode.
The classifier doesn't read project settings. It takes autoMode only from the user file, the enterprise one and --settings. Otherwise a repository could hand itself permissions; local settings were read up until version 2.1.207, but not any more.
You can inspect and pick apart the configuration from the terminal:
claude auto-mode config # what's in effect and where it came fromclaude auto-mode defaults # the standard rules of all four listsclaude auto-mode defaults --label 'Git Destructive' # the full text of a single ruleclaude auto-mode critique # the model's review of your rulesclaude auto-mode reset --yes # reset to the standard set without askingThe critique subcommand is underrated: it asks the model to go through your own rules and point out the ones that are ambiguous, redundant, or bound to produce false positives.
The mode is turned off with disableAutoMode, and there's a trap here: the value must be the string "disable". The schema will accept an array or true without complaining, but the code compares against that exact string, and the mode quietly stays on. You can hide the setup wizard with "auto-mode-setup": "off" in skillOverrides; disableBundledSkills doesn't switch it off, because it's a built-in command rather than a skill.
MCP servers
| Setting | Type | What it does |
|---|---|---|
enableAllProjectMcpServers | boolean | Automatically approve every server from the project's .mcp.json. |
enabledMcpjsonServers | array of names | Explicitly approved servers from .mcp.json. |
disabledMcpjsonServers | array of names | Explicitly rejected servers. |
allowedMcpServers | array of objects | [admin] Allowlist: by name, by command or by address. An empty array means none are allowed. |
deniedMcpServers | array of objects | [admin] Blocklist. Takes precedence over the allowlist. |
allowManagedMcpServersOnly | boolean | [admin] The allowlist is read from policy only. |
allowAllClaudeAiMcps | boolean | [admin] Load the cloud connectors alongside the managed list. |
managedMcpServers | array of objects | [admin] The servers themselves, pushed out by an administrator: transport, connection and the map of allowed tools. |
That last row corrects a widespread claim I used to repeat myself: "servers are only ever defined in .mcp.json, and settings hold nothing but the permissions for them". True for you, but not for an administrator: managedMcpServers in enterprise settings holds actual server configurations and is rolled out to everyone through the policy file or a device management system.
Ordinary servers, though, are defined in .mcp.json or via claude mcp add.
Hooks
Hooks deserve an article of their own, and I have one: it covers every event, the exchange formats and working examples. Here — the settings keys, and what breaks most often.
hooks is an object of the form "event → array of matchers". A matcher has a matcher filter and a list of handlers.
{ "hooks": { "PostToolUse": [ { "matcher": "Edit|Write", "hooks": [ { "type": "command", "command": "npm run lint" }, { "type": "command", "command": "echo", "args": ["done"] } ] } ] }}There are thirty-three events. For tools: PreToolUse, PostToolUse, PostToolUseFailure, PostToolBatch. For the conversation: UserPromptSubmit, UserPromptExpansion, Stop, StopFailure, Notification, MessageDisplay. For the session: SessionStart, SessionEnd, Setup, InstructionsLoaded, ConfigChange. For compaction and model switching: PreCompact, PostCompact, PreModelSwitch, PostModelSwitch. For permissions: PermissionRequest, PermissionDenied. For subagents and tasks: SubagentStart, SubagentStop, TeammateIdle, TaskCreated, TaskCompleted. For files and folders: FileChanged, CwdChanged, DirectoryAdded, WorktreeCreate, WorktreeRemove. And two for MCP forms: Elicitation, ElicitationResult.
A handler comes in five kinds, set by the type field: command runs a program or a shell line, prompt asks a small fast model, agent dispatches a full-blown agent, http pokes a URL, mcp_tool calls a tool on an MCP server. The shared optional fields are if with a condition, timeout, statusMessage for the spinner, once to run it a single time per session, and async with its relative asyncRewake.
| Setting | Type | What it does |
|---|---|---|
hooks | object | The hooks themselves. |
disableAllHooks | boolean | Turn off every hook, and the status line command with them. |
allowManagedHooksOnly | boolean | [admin] Run only the hooks that come from policy. |
allowedHttpHookUrls | array of strings | [admin] Allowlist of addresses for HTTP hooks. |
httpHookAllowedEnvVars | array of strings | Which environment variables HTTP hooks may interpolate into headers. |
disableSkillShellExecution | boolean | Forbid inline shell calls in skills and in your own commands. |
Three reasons a hook "runs but does nothing"
Exit code 1 blocks nothing. Only code 2 blocks, and only on about a third of the events. A 1 — or any other non-zero code — is on most events just a non-blocking error in the log. And code 2 outranks your own JSON: even if you returned an "allow" decision, the 2 denies.
Where a 2 blocks: PreToolUse, UserPromptSubmit (wiping the prompt), UserPromptExpansion, Stop, SubagentStop, TeammateIdle, TaskCreated, TaskCompleted, ConfigChange, PostToolBatch, PreModelSwitch. Where it's ignored: PermissionRequest and PermissionDenied — the JSON fields decide there — and StopFailure. On PostToolUse a 2 doesn't block, it gets shown to the model. On WorktreeCreate any non-zero code aborts. And one more asymmetry: an expired timeout on PreToolUse doesn't block, while on PreModelSwitch it does.
The model almost never sees a hook's output. Plain text on standard output with exit code 0 lands in the debug log, not in the conversation. It's shown to the model on exactly four events: UserPromptSubmit, UserPromptExpansion, SessionStart and PostModelSwitch. The error stream is never shown anywhere, ever. On the remaining events the only way to pass something to the model is a structured response — the additional-context field or a system message. And the JSON is parsed only if the output starts with { and ends with }.
The filter is sometimes ignored entirely, and sometimes a regular expression. "*", an empty string, or no field at all all mean "everything". A filter made up only of letters, digits, _, -, spaces, commas and | is an exact match or a list of them. Any other character turns it into a regular expression, matched without anchors at either end unless you wrote them yourself. Case matters.
And the filter isn't always about a tool name. On SessionStart it's compared against how the session started, on SessionEnd against the reason it ended, on compaction against manual or auto, on ConfigChange against which settings file changed, on FileChanged against the file name, on a model switch against the model's canonical name. Whereas UserPromptSubmit, PostToolBatch, Stop, CwdChanged, TeammateIdle, the task events, the worktree events and MessageDisplay take no filter at all and silently ignore the one you wrote.
The default timeouts aren't uniform: command, http and mcp_tool get ten minutes, except thirty seconds on UserPromptSubmit and on the model-switch events, and ten on MessageDisplay; prompt gets thirty seconds, agent a minute; all the SessionEnd hooks together are given a second and a half. Async ones aren't limited at all.
On Windows it's worth remembering the form with a separate argument list: it runs without a shell and needs a real executable — .cmd and .bat wrappers require either the string form or launching through an interpreter.
Git: commits, pull requests, attribution
| Setting | Type | What it does |
|---|---|---|
attribution | object | The attribution text in commits and descriptions; an empty string hides it. The sessionUrl field controls the link to the session. |
includeCoAuthoredBy | boolean | [deprecated] Add co-authorship. Better to use attribution. |
includeGitInstructions | boolean | Include the built-in commit instructions in the system prompt. On by default. |
prUrlTemplate | string | Template for the pull request link: {host}, {owner}, {repo}, {number}, {url}. |
doneMeansMerged | boolean | [experimental] "Done means merged": the agent keeps going until the pull request is ready to merge. |
{ "attribution": { "commit": "", "pr": "" }, "includeGitInstructions": true}Interface and terminal
| Setting | Type | What it does |
|---|---|---|
theme | see below | Color theme. |
editorMode | normal, vim | Key mode in the input box. Replaced the /vim command, which is gone. |
keybindingFlavor | classic, readline | How the word-wise keys behave. readline is like Bash: delete back to a space, move by words, punctuation splits words. |
vimInsertModeRemaps | object | Your own ways out of insert mode, for example {"jj": "<Esc>"}. |
emojiCompletionEnabled | boolean | Emoji autocompletion in the input box. On by default. |
wheelScrollAccelerationEnabled | boolean | Scroll acceleration with the mouse wheel. Fullscreen mode only. |
defaultView | chat, transcript | Which view a session opens in. |
axScreenReader | boolean | Flat output for screen readers. |
tui | default, fullscreen | The interface renderer. |
viewMode | default, verbose, focus | Transcript view mode at startup. |
verbose | boolean | Full tool output instead of shortened summaries. |
autoScrollEnabled | boolean | Auto-scroll the conversation down. Fullscreen mode only. |
syntaxHighlightingDisabled | boolean | Turn off syntax highlighting in diffs. |
prefersReducedMotion | boolean | Reduce or remove animations. |
showTurnDuration | boolean | Show how long each turn took. |
showMessageTimestamps | boolean | Stamp messages with the time they arrived. |
terminalProgressBarEnabled | boolean | Report progress on long operations through terminal escape sequences. |
terminalTitleFromRename | boolean | Let /rename change the tab title. On by default. |
spinnerTipsEnabled | boolean | Show tips in the waiting spinner. |
spinnerVerbs | object | Your own spinner verbs: added to the standard ones, or replacing them. |
spinnerTipsOverride | object | Your own tips: as a list, from a file, or with your own heading instead of "Tip". |
footerLinksRegexes | array of objects | Your own link badges in the footer, driven by a regular expression. Five at most. |
spellcheck | object | Underline typos in the input box. Needs a checker installed: aspell, hunspell or ispell. |
companyAnnouncements | array of strings | Announcements at startup; if there are several, a random one is shown. |
todoFeatureEnabled | boolean | Turn on the task tracking panel. |
Values for theme: auto (follows the terminal background), dark, light, light-daltonized, dark-daltonized, light-ansi, dark-ansi, plus custom:<name> for a theme from ~/.claude/themes/ and custom:<plugin>:<name> for one that comes from a plugin.
Some of these keys are read only from the user file, --settings and policy: spinnerTipsOverride with a tips file, footerLinksRegexes and spellcheck. A project file can't override them — otherwise a repository could paint an arbitrary link into your interface.
Settings that live in ~/.claude.json
These keys are silently ignored in settings.json. Claude Code or /config normally writes them for you, but they're worth knowing about.
| Setting | Type | What it does |
|---|---|---|
permissionExplainerEnabled | boolean | [global] Ctrl+E on a permission dialog shows a breakdown of the command: what it does, what for, and what could go wrong, with a risk rating. On by default. |
diffTool | auto, terminal | [global] Where to show the edit diff when an IDE is connected. In the IDE by default. |
autoConnectIde | boolean | [global] Connect to a running IDE automatically when started from an external terminal. Off by default. |
autoInstallIdeExtension | boolean | [global] Install the extension automatically when launched from the VS Code terminal. On by default. |
externalEditorContext | boolean | [global] When you edit the prompt in an external editor via Ctrl+G, show the previous answer as comments at the top of the buffer. |
skippedMarketplaces | array of strings | [global] Marketplaces whose installation you declined. |
skippedPlugins | array of strings | [global] Plugins whose installation you declined. |
The first key is worth finding out about: Ctrl+E on a prompt asking to run a command gives you a human explanation of what that command does — without running it. On an unfamiliar command out of someone else's repository, that's exactly the button you've been missing.
The status line
| Setting | Type | What it does |
|---|---|---|
statusLine | object | Your own status line at the bottom, drawn by an external script. |
subagentStatusLine | object | A status line for each subagent in the agents panel. |
Fields of statusLine: type with the value "command", command with the script, padding, refreshInterval — recompute once every so many seconds — and hideVimModeIndicator if the script draws the vim mode itself.
{ "statusLine": { "type": "command", "command": "~/.claude/statusline.sh", "padding": 1, "refreshInterval": 5 }}The script gets JSON on its input with the session context: model, folder, cost, how full the context is. It prints one line. This is probably the most underrated setting of them all: spend figures permanently in view change behavior more than any instruction about saving tokens ever will. Just bear in mind that disableAllHooks turns this off too.
Context, memory, sessions
| Setting | Type | What it does |
|---|---|---|
cleanupPeriodDays | number from 1 | How many days to keep transcripts. Thirty by default. It also sets how long checkpoints live. |
desktopSessionCleanupPeriodDays | number from 0 | The ceiling on the exception that lets desktop app sessions survive the usual cleanup. |
crossSessionInbound | accept, hold, refuse | What to do with messages from your other sessions. |
dialogExpiry | 60s, 5m, 10m, never | How long before an unanswered dialog goes stale. Five minutes by default. |
askUserQuestionTimeout | the same values | The same, for the agent's questions to you. They don't expire by default. |
autoContinueAtUsageLimit | boolean | Continue the session once the plan's limit resets. On by default. |
autoMemoryEnabled | boolean | Automatic project memory. |
autoMemoryDirectory | string, a path | The folder auto-memory is stored in. Read from any settings level. |
autoDreamEnabled | boolean | Background memory consolidation. |
fileCheckpointingEnabled | boolean | Snapshot files before edits so that /rewind can restore them. |
outputStyle | string | The style of the assistant's answers. |
language | string | Preferred language for answers and voice input, for example "russian". |
promptSuggestionEnabled | boolean | Show prompt suggestions. |
awaySummaryEnabled | boolean | [experimental] A session summary when you come back after being away for more than five minutes. |
showClearContextOnPlanAccept | boolean | Offer to clear the context when a plan is accepted. Off by default. |
plansDirectory | string, a path | Folder for plan files, relative to the project root. |
claudeMd | string | [admin] CLAUDE.md-style instructions as organizational memory. |
claudeMdExcludes | array of patterns | Which CLAUDE.md files not to load. The policy file can't be excluded. |
respectGitignore | boolean | The file picker respects .gitignore. On by default; .ignore is always respected. |
fileSuggestion | object | Your own source of file suggestions for @ mentions. |
Two things are worth knowing about autoContinueAtUsageLimit: it's on by default, and it's read only from the user file, --settings and policy — meaning a project or local file that sets it isn't ignored, it turns the feature off.
Skills
| Setting | Type | What it does |
|---|---|---|
skillOverrides | object | A skill's visibility: on, name-only — the name without the description, user-invocable-only — hidden from the model but still callable by name, off — hidden entirely. |
skillListingMaxDescChars | number | Character limit on a skill's description in the listing. 1536 by default. |
skillListingBudgetFraction | number 0–1 | Share of the context given to the whole skill listing. One percent by default. |
disableSkillShellExecution | boolean | Forbid inline shell calls in skills and in your own commands. |
disableBundledSkills | boolean | Don't load the built-in skills. /doctor is the exception. |
syncClaudeAiSkills | boolean | Whether to pull skills synced with claude.ai. Only the value false is taken into account. |
syncClaudeAiPlugins | boolean | The same for plugins. |
skillOverrides is worth knowing about for anyone with a lot of skills: their descriptions sit in the context permanently, and name-only on the rarely needed ones frees up a noticeable chunk. The same key is also how you stop the agent from running a particular command on its own while keeping it available to you: the value user-invocable-only.
Plugins and marketplaces
| Setting | Type | What it does |
|---|---|---|
enabledPlugins | object | Which plugins are enabled; the key is plugin@marketplace. |
pluginConfigs | object | Configuration for each plugin. Ignored in project settings. |
extraKnownMarketplaces | object | Additional marketplaces for this repository. |
strictKnownMarketplaces | array of sources | [admin] Only these sources may be added. Supports owner/* — a whole organization. |
blockedMarketplaces | array of sources | [admin] Blocked sources. |
pluginSuggestionMarketplaces | array of strings | [admin] Whose plugins may show up in install suggestions. |
strictPluginOnlyCustomization | boolean or array | [admin] Forbid customization outside plugins for skills, agents, hooks, mcp. |
pluginTrustMessage | string | [admin] Extra text added to the warning shown before installation. |
disableCommandPluginSources | boolean | [admin] Forbid marketplaces of the "a local command prints the path to a plugin" kind. |
disableSideloadFlags | boolean | [admin] Forbid slipping plugins in through flags. |
Workflows, agents, teammates
| Setting | Type | What it does |
|---|---|---|
enableWorkflows | boolean | Turn workflows on or off. |
disableWorkflows | boolean | Turn workflows off. |
workflowKeywordTriggerEnabled | boolean | The word "ultracode" in a prompt turns workflows on for that turn. On by default. |
skipWorkflowUsageWarning | boolean | [experimental] The warning about the cost of multi-agent workflows has been acknowledged. |
workflowSizeGuideline | unrestricted, small, medium, large | A guideline for fan-out size: fewer than five agents, fewer than fifteen, fewer than fifty, or no hint at all. |
disableAgentView | boolean | [admin] Turn off the agents screen, background launching and the background service. |
disableAutoMode | "disable" | Turn off auto mode. Only as that string. |
teammateMode | in-process, tmux, iterm2, auto | How teammates are displayed. in-process by default. |
The auto value of teammateMode is defined precisely: split panes if the session is running inside tmux, or inside iTerm2 with its command-line utility available, or if tmux is installed at all; otherwise everything runs inside the process. The iterm2 value means native iTerm2 split panes, and it showed up in 2.1.186.
The teammateDefaultModel key is still in the schema, but it was removed from the product in 2.1.234 and affects nothing.
Worktrees
The nested worktree object controls how separate working copies get created for sessions and background agents.
| Field | Type | What it does |
|---|---|---|
symlinkDirectories | array of strings | What to symlink from the main repository so the disk doesn't balloon. Nothing by default. |
sparsePaths | array of strings | Which paths to include via a sparse checkout. A huge speed-up in monorepos. |
baseRef | fresh, head | What new copies branch off: the remote main branch or your local state. |
bgIsolation | worktree, none | Isolation for background sessions. By default a background agent doesn't touch the main tree. |
location | string, a path | Where the desktop app creates copies for SSH sessions. The CLI doesn't read it yet. |
{ "worktree": { "symlinkDirectories": ["node_modules", ".cache"], "sparsePaths": ["packages/app", "packages/shared"], "baseRef": "fresh", "bgIsolation": "worktree" }}Remote control, SSH, environments
| Setting | Type | What it does |
|---|---|---|
disableRemoteControl | boolean | [admin] Turn off remote control entirely. |
remoteControlAtStartup | boolean | Bring up the remote control bridge in every session. |
isolatePeerMachines | boolean | Require confirmation before a message goes to a session on another machine. |
autoUploadSessions | boolean | Mirror local sessions to the web, for viewing only. |
daemonColdStart | transient, ask | When the background service isn't there: bring it up for the session, or offer to install it permanently. |
remote | object | The default environment for remote sessions. |
sshConfigs | array of objects | [admin] Preconfigured SSH connections: id, name, sshHost, sshPort, sshIdentityFile, startDirectory. |
sshHostAllowlist | array of patterns | [admin] Restrict the app's SSH sessions to these hosts. * — any, *.example.com — the domain and its subdomains. |
disableDesktopLocalSessions | boolean | [admin] Forbid sessions on the machine itself in the desktop app: work over SSH only. |
browserExternalPageTools | "disabled" | [admin] Forbid the agent to read or touch external pages in the app's browser. Local previews still work. |
disableBrowserExternalNavigation | boolean | [admin] Forbid external navigation in the app's browser, for the agent and the human alike. |
disableMobileSimulatorTools | boolean | [admin] Take the iOS simulator tools away from the agent; the human keeps the panel. |
requireCoworkFullVmSandbox | boolean | [admin] Run tools inside an isolated virtual machine. |
channelsEnabled | boolean | [admin] Allow channel notifications. |
allowedChannelPlugins | array of objects | [admin] Allowlist of channel plugins. |
Three of these keys accept only a genuine boolean true: the string "true" or a 1 will be ignored, with a warning in the log. They are disableDesktopLocalSessions, disableBrowserExternalNavigation and disableMobileSimulatorTools. The terminal CLI doesn't read them at all — they're about the desktop app.
requireCoworkFullVmSandbox has an important side effect: inside a full virtual machine there is neither a device policy nor an enterprise settings file — you'll have to get them in there some other way.
{ "remote": { "defaultEnvironmentId": "env-123" }, "sshConfigs": [ { "id": "prod-box", "name": "Prod", "sshHost": "deploy@prod.example.com", "sshPort": 22, "startDirectory": "~/app" } ]}Notifications, voice, breaks
| Setting | Type | What it does |
|---|---|---|
preferredNotifChannel | auto, iterm2, terminal_bell, iterm2_with_bell, kitty, ghostty, notifications_disabled | Which channel to send system notifications through. |
inputNeededNotifEnabled | boolean | A push to your phone when a confirmation or a question is waiting. |
agentPushNotifEnabled | boolean | Let the agent send proactive mobile pushes. |
voice | object | Voice input: enabled, mode with the value hold or tap, autoSubmit. |
voiceEnabled | boolean | Dictation when signed in through claude.ai, if the organization's policy allows it. Not the same thing as voice.enabled, which overrides it. |
breakReminder | object | [experimental] A reminder to take a break after a long stretch of uninterrupted work. Never blocks. |
quietHours | object | [experimental] Quiet hours: one gentle hint per session inside a given window of local time. |
{ "voice": { "enabled": true, "mode": "hold", "autoSubmit": true }, "breakReminder": { "enabled": true, "intervalMinutes": 120 }, "quietHours": { "enabled": true, "start": "22:00", "end": "07:00" }}Sandbox and network
The sandbox object controls what processes inside the isolation are allowed to do. It's the longest section of the schema and the least used — but if you let the agent run in a mode where it doesn't ask for permissions, this is exactly the part you need to read.
Let me fix a common structural mistake right away: read and write paths live not directly in sandbox, but in sandbox.filesystem. A rule like "sandbox": {"denyRead": [...]} will do nothing.
| Field | Type | What it does |
|---|---|---|
enabled | boolean | Turn the sandbox on. |
enabledPlatforms | array of macos, linux, wsl, windows | [admin] Limit the whole configuration to these systems. On the rest it's inert in its entirety. |
autoAllowBashIfSandboxed | boolean | Automatically allow commands when they run inside the sandbox. |
allowUnsandboxedCommands | boolean | Allow a blocked command to be retried outside the sandbox. Defaults to true. |
failIfUnavailable | boolean | Fail if the sandbox couldn't be brought up, instead of quietly starting without it. |
excludedCommands | array of strings | Commands taken out of the sandbox; set by /sandbox exclude. |
ignoreViolations | object | Which violations not to show. |
filesystem.allowWrite | array of paths | Additional paths that are writable. |
filesystem.denyWrite | array of paths | Paths that can't be written to, including ones inside an allowed folder. |
filesystem.denyRead | array of paths | Paths that can't be read. |
filesystem.allowRead | array of paths | Exceptions that re-allow reading inside denied areas. |
filesystem.allowManagedReadPathsOnly | boolean | [admin] Read paths come from policy only. |
filesystem.disabled | boolean | Turn off the filesystem half of the sandbox. Not from project settings. |
network.allowedDomains | array of strings | Allowed domains. |
network.deniedDomains | array of strings | Domains that are always blocked. |
network.allowManagedDomainsOnly | boolean | [admin] Allow only domains from policy. |
network.strictAllowlist | boolean | Allow only explicitly listed domains. |
network.allowUnixSockets | array of strings | Allowed Unix sockets. macOS only. |
network.allowAllUnixSockets | boolean | Allow all Unix sockets. |
network.allowLocalBinding | boolean | Allow binding local ports. |
network.allowMachLookup | array of strings | Allowed Mach services. macOS only, and a wildcard is allowed only at the end. |
network.httpProxyPort | number | Port of the sandbox's internal HTTP proxy. |
network.socksProxyPort | number | Port of the internal SOCKS proxy. |
network.tlsTerminate | object | [experimental] Terminate TLS with your own certificate authority — needed to mask secrets. |
credentials.envVars | array of objects | What to do with secrets in variables: deny or mask, plus extraction and parsing. |
credentials.files | array of objects | The same for files holding secrets. |
credentials.awsPairs | array of objects | AWS variable pairs that the sandbox re-signs. |
credentials.sigv4 | object | What to do with the AWS request shapes that can't be re-signed: streaming uploads, presigned URLs and asymmetric signing. Each field is deny or passthrough; everything is denied by default. |
credentials.allowPlaintextInject | boolean | Allow secrets to be injected in plaintext. Off by default. |
allowAppleEvents | boolean | Allow Apple Events. macOS only. |
enableWeakerNetworkIsolation | boolean | Weakens protection. Weaker network isolation on macOS. |
enableWeakerNestedSandbox | boolean | Weakens protection. Allow a weaker nested sandbox. |
bwrapPath | string, absolute path | [admin] Your own bubblewrap binary on Linux. |
socatPath | string, absolute path | [admin] Your own socat binary. |
ripgrep | object | Your own ripgrep for the sandbox. Project settings don't override it. |
Three things are worth singling out.
allowUnsandboxedCommands is on by default. Which means the agent can retry a command the sandbox blocked outside it, through a special parameter. If you turned the sandbox on for isolation, that's most likely not what you wanted — switch it off with an explicit false.
enabledPlatforms makes the configuration inert in its entirety. On a system that isn't in the list there's no sandbox, no automatic permissions, no warning at startup, and no failure from failIfUnavailable. Silent, as if the section weren't there.
Secret masking doesn't work everywhere. On macOS and Windows the mask mode degrades into deny: there's nothing there to substitute the value on the fly. Masking entries also have an onExtractNoMatch field — what to do when the regular expression finds nothing: warn (the default) lets the variable through unmasked, deny removes it inside the sandbox, error stops the run.
{ "sandbox": { "enabled": true, "autoAllowBashIfSandboxed": true, "allowUnsandboxedCommands": false, "network": { "allowedDomains": ["api.example.com", "*.githubusercontent.com"], "deniedDomains": ["telemetry.example.com"] }, "filesystem": { "denyRead": ["~/.ssh", "~/.aws"], "denyWrite": ["~/.config"] } }}Updates and everything else
| Setting | Type | What it does |
|---|---|---|
autoUpdatesChannel | latest, stable, rc | Auto-update channel. |
minimumVersion | string | Keeps you from dropping below the given version when switching channels. |
requiredMinimumVersion | string | [admin] Below this version the organization won't let you work. |
requiredMaximumVersion | string | [admin] The organization's version ceiling. |
managedSourcesBehavior | first-wins, merge | [admin] How several policy sources add up. |
wslInheritsWindowsSettings | boolean | [admin, Windows] WSL reads policy from the full Windows policy chain. |
processWrapper | string | [admin] What to wrap spawned processes in. |
allowManagedPermissionRulesOnly | boolean | [admin] Honor permission rules from policy only. |
defaultShell | bash, powershell | The shell for commands typed with !. Defaults to bash on every platform. |
respondToBashCommands | boolean | Respond to commands entered with !. Defaults to yes. |
feedbackSurveyRate | number 0–1 | Probability of showing a session-quality survey. |
feedbackDrafts | notify, quiet, off | Whether the agent may draft feedback on its own. You still send it yourself. |
enableArtifact | boolean | Artifact publishing. Turning it off in any layer wins. |
disableArtifact | boolean | [deprecated] Its inverted predecessor: true turns it off, false is ignored. |
disableClaudeAiConnectors | boolean | Don't load cloud connectors. |
skipWebFetchPreflight | boolean | Skip the blocked-address check in strict corporate environments. |
$schema | string | A link to the settings schema: autocomplete and validation in your editor. |
The schema accepts a few more housekeeping keys: modelProposedGoals, totalTokensReminder with its relatives, and disableDeepLinkRegistration. They're internal, never show up in the interface, and aren't described anywhere.
Environment variables
The env block in settings is a "name → value" object. All values are strings: numbers and flags go in quotes, "PORT": "3000", a flag is "1".
An honest caveat about completeness: the official documentation lists three hundred and forty-nine variables by name, including per-region ones for every model at every provider, plus the whole telemetry set. Retelling them here is pointless. Below are the ones actually used, plus the behavior of the env block, which isn't gathered in one place anywhere.
{ "env": { "CLAUDE_CODE_USE_POWERSHELL_TOOL": "1", "ANTHROPIC_MODEL": "claude-opus-5", "BASH_DEFAULT_TIMEOUT_MS": "120000", "DISABLE_TELEMETRY": "1" }}How the env block behaves
It beats an export from the shell. The value from the settings file is written into the process environment on top of the inherited one. That's exactly the opposite of what people usually expect.
You can't delete a variable — you can only set it to an empty string. When a provider is being picked, an empty value counts as unset, but child processes will get exactly that empty string.
Values are re-read on the fly when the file changes — except for subsystems configured only at startup, like telemetry. And since 2.1.246 /cd layers the new folder's env on top of the old one.
Project and local settings aren't allowed everything. Three groups are dropped: variables that set where files live (CLAUDE_CONFIG_DIR, CLAUDE_CODE_TMPDIR, HOME, TMPDIR, TMP, TEMP, XDG_*); variables that turn on dumping session contents (OTEL_LOG_RAW_API_BODIES, ENABLE_BETA_TRACING_DETAILED, BETA_TRACING_ENDPOINT); and variables affecting startup and syncing (CLAUDE_CODE_PROCESS_WRAPPER, CLAUDE_CODE_SYNC_SKILLS, CLAUDE_CODE_SYNC_PLUGINS, the plugin cache and seed folder). The list grew in 2.1.251, as it happens. The warning about it is only visible under debug.
A few more variables are ignored in any file and read only from the launch environment: CLAUDE_CODE_REMOTE, CLAUDE_CODE_ACCOUNT_UUID, the cross-session exchange socket and token, CLAUDE_CODE_PROJECT_DIR_NAME and CLAUDE_CODE_RESTRICTED.
And the other direction, which almost nobody writes about: Claude Code sets variables for child processes itself. They're visible from hooks and from any script you run: CLAUDECODE=1, CLAUDE_CODE_CHILD_SESSION=1, CLAUDE_CODE_SESSION_ID, CLAUDE_PID — its own process id, CLAUDE_EFFORT with the current effort level (ultracode mode shows up as xhigh), and in cloud sessions CLAUDE_CODE_REMOTE=true plus the remote session id. A hook that needs to know the effort level, or to tell a child session from the main one, takes it from here instead of guessing.
Providers and authentication
| Variable | What it does |
|---|---|
ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN | Anthropic API key and token. |
CLAUDE_CODE_OAUTH_TOKEN | Subscription token — sign in without an interactive login. |
ANTHROPIC_BASE_URL | Your own API base URL: a proxy or a gateway. |
ANTHROPIC_CUSTOM_HEADERS | Extra HTTP headers on API requests. |
ANTHROPIC_BETAS | Beta headers in requests. |
CLAUDE_CODE_USE_BEDROCK, CLAUDE_CODE_USE_VERTEX | Turn on Amazon Bedrock or Google Cloud as the provider. |
ANTHROPIC_BEDROCK_REGION_PREFIX | Which cross-region profile to prefer instead of the one derived from the AWS region. |
ANTHROPIC_BEDROCK_BASE_URL, ANTHROPIC_VERTEX_BASE_URL | Your own provider URLs. |
AWS_BEARER_TOKEN_BEDROCK, ANTHROPIC_VERTEX_PROJECT_ID | Bedrock credentials and the Google Cloud project. |
CLAUDE_CODE_SKIP_BEDROCK_AUTH, CLAUDE_CODE_SKIP_VERTEX_AUTH | Skip provider auth when a gateway handles it. |
HTTPS_PROXY, HTTP_PROXY, NO_PROXY | Proxies for outbound traffic. |
NODE_EXTRA_CA_CERTS | Your own root certificate for a corporate proxy. |
There aren't two or three providers, by the way: besides the Anthropic API, Amazon Bedrock and Google Cloud, Microsoft Foundry and Claude Platform on AWS are supported too, and each has its own set of variables and its own mapping of aliases to models.
Models, context, limits
| Variable | What it does |
|---|---|
ANTHROPIC_MODEL | The main model. Overrides the model key from the files. |
ANTHROPIC_DEFAULT_MODEL | The model for new sessions; applies only if model isn't set anywhere. |
ANTHROPIC_DEFAULT_OPUS_MODEL and the same for sonnet, haiku and fable | What the aliases stand for. |
ANTHROPIC_SMALL_FAST_MODEL | [deprecated] The small fast model. Replaced by ANTHROPIC_DEFAULT_HAIKU_MODEL. |
CLAUDE_CODE_SUBAGENT_MODEL | The model for subagents. |
CLAUDE_CODE_EFFORT_LEVEL | Effort level. Overrides --effort and /effort. |
MAX_THINKING_TOKENS | Token limit for thinking. |
CLAUDE_CODE_MAX_OUTPUT_TOKENS, MAX_MCP_OUTPUT_TOKENS | The output token limit and the MCP output limit. |
CLAUDE_CODE_DISABLE_1M_CONTEXT | Don't use the million-token window. |
CLAUDE_CODE_MAX_CONTEXT_TOKENS | Your own ceiling for the context window. |
CLAUDE_CODE_AUTO_COMPACT_WINDOW, CLAUDE_AUTOCOMPACT_PCT_OVERRIDE | The auto-compaction window in tokens and in percent. |
DISABLE_AUTO_COMPACT | Turn off auto-compaction. |
DISABLE_PROMPT_CACHING | Turn off prompt caching. |
API_TIMEOUT_MS, CLAUDE_CODE_MAX_RETRIES | API request timeout and the number of retries. |
Behavior and environment
| Variable | What it does |
|---|---|
CLAUDE_CONFIG_DIR | A different configuration folder entirely. |
CLAUDE_CODE_PROJECT_DIR_NAME | The short name of the project's transcript and auto-memory folder. Set only together with CLAUDE_CONFIG_DIR and only from the launch environment. |
CLAUDE_CODE_TMPDIR | Directory for temporary files. |
CLAUDE_CODE_USE_POWERSHELL_TOOL | Use the PowerShell tool instead of bash. |
CLAUDE_CODE_GIT_BASH_PATH | Path to Git Bash on Windows. |
CLAUDE_CODE_SHELL, CLAUDE_CODE_SHELL_PREFIX | The shell and a prefix for shell commands. |
CLAUDE_ENV_FILE | A script run before every shell command in the same process — that's how virtualenv activation survives across calls. |
CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR | Return to the original folder after every command: a cd inside a call isn't kept. |
BASH_DEFAULT_TIMEOUT_MS, BASH_MAX_TIMEOUT_MS | The default and maximum command timeouts. |
BASH_MAX_OUTPUT_LENGTH | Limit on the length of a command's output. |
CLAUDE_CODE_TOOL_MEMORY_LIMIT | Memory limit for commands, via control groups. Linux only. |
MCP_TIMEOUT, MCP_TOOL_TIMEOUT | Timeouts for server startup and for a tool call. |
CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS | How many subagents run at once. Twenty by default. |
CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH | Subagent nesting depth. Three by default; one disables nesting. |
CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY | How many parallel read-only calls. Ten by default. |
TASK_MAX_OUTPUT_LENGTH | Ceiling on subagent output in characters: 32000 by default, 160000 maximum. |
CLAUDE_CODE_ENABLE_TASKS | Which task tools to hand out: the new ones by default, zero brings back the old single tool. |
CLAUDE_CODE_ENABLE_TODO_TOOLS | Bring the task tools back on models where they were removed. |
USE_BUILTIN_RIPGREP | Use the bundled ripgrep. |
CLAUDE_CODE_WEBFETCH_CACHE_TTL_MS | How long fetched pages stay in the cache. Fifteen minutes by default. |
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS | Turn off background tasks. |
CLAUDE_CODE_DISABLE_CLAUDE_MDS | Don't load CLAUDE.md files. |
CLAUDE_CODE_SAFE_MODE, CLAUDE_CODE_RESTRICTED, CLAUDE_CODE_SIMPLE | The same as the launch flags of the same names. |
Three traps in this table are worth spelling out.
The MCP timeouts differ by five orders of magnitude. Server startup is thirty seconds. A tool call, by default, is about twenty-eight hours — effectively no limit at all. On top of that, HTTP servers and cloud connectors cap each request at a minute, and that's a separate limit.
CLAUDE_CODE_PROJECT_DIR_NAME doesn't work on its own — only together with CLAUDE_CONFIG_DIR, and only from the environment, not from a settings file.
Safe mode takes away more than it looks like. CLAUDE_CODE_SAFE_MODE isn't only instructions and skills: plugins, hooks, MCP servers, custom commands and agents, output styles, workflows, themes, keybindings, the status line, the file-suggestion source, language servers and auto-memory don't load either. All that's left is corporate policy, including the hooks and status line it sets. It's a debug mode meaning "turn off everything I configured", and for tracking down a broken configuration it's perfect.
Rendering and accessibility
In one line, because there are a lot of variables and they're rarely needed. CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN brings back the classic renderer, and it's stronger than both CLAUDE_CODE_NO_FLICKER and the tui setting. There are separate switches for the mouse and clicks, scroll speed, virtual scrolling, full repaints, the native cursor, syntax highlighting, hyperlinks and truecolor in tmux. For accessibility there's CLAUDE_AX_SCREEN_READER and its relatives.
Privacy, telemetry, updates
| Variable | What it does |
|---|---|
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC | A single switch for all non-essential outbound traffic. |
DISABLE_TELEMETRY, CLAUDE_CODE_ENABLE_TELEMETRY | Turn telemetry off and on. |
DO_NOT_TRACK | The widely adopted variable with the same meaning. |
DISABLE_GROWTHBOOK | Don't pull server-side feature flags. |
DISABLE_ERROR_REPORTING | Don't send error reports. |
DISABLE_AUTOUPDATER, DISABLE_UPDATES | Turn off auto-updates. |
DISABLE_COST_WARNINGS | Hide cost warnings. |
DISABLE_FEEDBACK_COMMAND | Hide feedback submission. The old name DISABLE_BUG_COMMAND is accepted too. |
DISABLE_DOCTOR_COMMAND | Hide /doctor. |
The OTEL_* family | Exporting metrics, logs and traces. |
Three things here catch people out.
DISABLE_BUG_COMMAND isn't a separate switch. It's the old name of DISABLE_FEEDBACK_COMMAND, and that one variable turns off /feedback, the feedback drafts, and /bug with /share, because they all go out over the same channel.
A value of 0 doesn't turn it back on. For CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, the variable being present at all — including as 0 or false — disables the traffic. To get it back you have to remove the variable entirely.
Turning off telemetry turns off features too. Along with the feature flags, these stop working: the default auto mode, /auto-mode-setup, remote control, /import, /schedule, the advisor, artifact comments, the new MCP client, and the PowerShell tool as the default on Windows. It's a deliberate trade-off rather than an incidental defect, but it's worth knowing before you spend half an hour looking for where remote control went.
What "all non-essential traffic" actually covers: auto-updates, telemetry, error reports, feedback submission, release notes, refreshing a gateway's model list, and availability checks. Plus — unexpectedly — running local plugin-source commands in the background, because they can drag a dependency install along with them. What it doesn't cover is the auto-install of the official marketplace; that one has its own variable.
Terminal commands and flags
Everything you type outside a session, in an ordinary shell. Each subcommand below gathers it all in one place: its own subcommands and flags, the fine print and the examples.
The important part first, and this is the official wording rather than my own observation: claude --help does not list every flag. A flag missing from the help is not a flag that does not exist. Below I mark what the help leaves out — there are at least a dozen such flags, and some of them are perfectly useful things like capping the number of turns.
Misspell a subcommand and you get the nearest match suggested and an exit, with no session started: claude udpate gets you a question asking whether you meant claude update.
Subcommands
claude [prompt]
Start an interactive session in the current folder — the ordinary way to begin work. A prompt in the argument does not change the mode: the session stays interactive, it just takes the first turn right away instead of waiting for input. Handy when the task is already formulated and you would rather not type it separately. Don't confuse this with -p: that one prints an answer once and exits.
The same splash screen opens either way: version, account and model, current folder, tips and recent activity. With a prompt in the argument it still shows up, but nothing waits for input — the first turn starts immediately.
claude # interactive session
# this is how the start screen looks in a user's report, build 2.0.26╭─── Claude Code v2.0.26 ─────────────────────────────────────────────────────╮│ │ Tips for getting started ││ Welcome back ksmith! │ Ask Claude to create a new appor c… ││ │ ││───────────────────────────────────────│ ││ ▐▛███▜▌ │ Recent activity ││ ▝▜█████▛▘ │ No recent activity ││ ▘▘ ▝▝ │ ││ │ ││ Sonnet 4.5 · Claude Max │ ││ /Users/ksmith/claude-context-test │ │╰─────────────────────────────────────────────────────────────────────────────╯
claude "fix the failing test in orders" # session, straight into the taskclaude -p "<prompt>"
A non-interactive run: Claude Code works through one prompt, prints the result to standard output and exits. This is the main mode for scripts, pipelines and CI — the output can be piped onward or saved to a file. The session itself is a full one: the same tools, the same permissions, the same project settings, there is just nobody around to ask. Hence a subtlety: if you have picked a model or a mode that draws on credits, you will not be shown the one-time consent for the charge — an interactive session asks, -p and the Agent SDK charge silently.
All that appears on screen is the answer itself: no splash screen and no input line in this mode.
claude -p "what does this script do?" # answer and exitclaude auth login|logout|status
Log in, log out, and check the authorization status. The status prints as JSON — a convenient way for a script to check that the machine is logged in at all before running anything on it. Some capabilities hinge not on an API key but specifically on being logged into a claude.ai account, so an inexplicable "feature unavailable" is best investigated starting here.
Logging in offers a choice of which account pays: your claude.ai subscription or Console billing. The --console flag picks the second one outright, without asking. After that a browser opens and waits for confirmation; logout deletes the stored credentials from the machine.
claude auth login --console # log in through Console billing
claude auth status # authorization status as JSON
claude auth logout # log outclaude setup-token
Issue a long-lived authorization token. [not on every plan] A subscription is required. The token is for places where you cannot log in interactively — a build server, a container, CI: you put it in an environment variable and claude -p works with no browser and no human.
You confirm the login in a browser, after which the token is printed to the terminal — and from there it goes into the build machine's environment.
claude setup-token # long-lived token for CIclaude agents
The management screen for background agents, and their launcher too. A background agent is a session that lives apart from your terminal: you hand it a task, close the window, and come back for the result. This screen shows what is running, what has finished and what has failed; all of it is available through separate subcommands (attach, logs, stop, rm) — the screen just collects them in one place.
You pick the session you want from the list, then choose what to do with it: open it in your terminal, look at its output, stop it, or delete it along with its working copy. Keep in mind that every background session burns your plan's limit like any other: five agents working at once eat through it five times faster.
claude agents # the background agents screen
# this is how the list looks in the documentationPinned ✽ clawd walk cycle Drawing the walk-cycle sprite frames 3m
Ready for review ∙ jump physics Opened PR with collision fix #2048 2h
Needs input ✻ power-up design double jump or wall climb? 1m
Working ✽ collision detection Adding swept-AABB checks to CollisionSystem 2m ✢ playtest level 3 run 12 · all checkpoints cleared in 4m
Completed ✻ title screen result: menu, options, and credits done 9m ∙ sound effects result: 14 SFX exported to assets/audio 4h … 6 moreclaude attach <id>
Open a background session in this terminal. You get its whole conversation and carry on as if you had started it here. You need this when the agent has run into a question or gone off course and it is easier to steer it by hand from there. The id comes from claude agents or from the output at launch.
claude attach a1b2c3 # attach to a background sessionclaude logs <id>
Print a background session's latest output and exit. A quick way to see what the agent is up to without taking it over or getting in its way. Handy to call from a script when you need to wait for a result or just make sure work is happening.
claude logs a1b2c3 # a background session's latest outputclaude stop <id>
Stop a background session; the conversation is kept. Alias: kill. This is not deletion: the session stops working and stops spending your limit, but its output and its working copy stay where they are and you can still look at them. If you want the session gone rather than stopped, that is claude rm.
claude stop a1b2c3 # stop itclaude respawn [id]
Restart a background session, or all of them, on the current version. The point is that agents already running keep spinning on the version they started with, and a Claude Code update does not reach them on its own. A single session is restarted by id, --all does the lot at once.
claude respawn --all # restart them all on the new versionclaude rm <id>
Delete a background session and its working copy. Unlike stop, this is irreversible: the conversation goes, and so does the separate folder the agent worked in, along with everything you did not pull out of it into a branch. Clearing out finished sessions is worth doing — otherwise the list overgrows and the working copies take up space.
If the working copy still holds commits that exist nowhere else, the command refuses to touch it and tells you it left everything as it was.
claude rm a1b2c3 # delete the session and its working copyclaude daemon
The background service that holds all the background sessions. A subcommand few people know about, though it runs for everyone: it is the supervisor that starts background sessions and keeps them alive. You do not need it at all right up until an agent stops responding or the session list looks suspiciously empty — that is when you come here for its state and its log.
| Subcommand | What it does |
|---|---|
status | Service state: version, socket folder, number of worker processes |
run [path] | Start the service by hand |
logs | The service log |
stop | Stop it; --any — together with the sessions, --keep-workers — leaving the worker processes |
uninstall | Remove the service |
The --json-path and --log-file flags change where the state file and the log live; by default that is ~/.claude/daemon.json and ~/.claude/daemon.log. In version 2.1.251 permanent installation of the service is disabled: it comes up on demand and shuts down when the last client disconnects.
A trap for scripts: claude --dangerously-skip-permissions daemon status works, but any other global flag before the word daemon will start an interactive session instead of the subcommand. Put the subcommand first.
claude daemon status # background service state
claude daemon stop --any --keep-workers # stop the service, keep the workersclaude mcp
Configuring MCP servers without starting a session. An MCP server is what the model reaches outside the project with: to an issue tracker, a database, the file system, an internal API. All of the same can be configured inside a session, but the shell is handier when servers are rolled out by a script or have to be set up identically on several machines.
| Subcommand | What it does |
|---|---|
add <name> <command-or-url> [args...] | Add a server. |
add-json <name> <json> | Add a server as a single line of JSON. |
add-from-claude-desktop | Import servers from Claude Desktop. macOS and WSL only. |
list, get <name> | The list and the details. |
login <name>, logout <name> | Authorize against a server, or clear its stored credentials. |
remove <name> | Remove a server. |
reset-project-choices | Reset the "approved or rejected" decisions on project servers. |
serve | Run Claude Code itself as an MCP server. |
The most important flag here is --scope, and leaving it out explains a good half of the "why can only I see this server" and "why does everyone suddenly have it" questions. Values: local (the default), project — into .mcp.json, which gets committed, and user — into your user settings. It is available on add, add-json, add-from-claude-desktop and remove.
There are four transports, not three: stdio, http, sse and ws. Short forms: -t for --transport, -H for --header. For OAuth there is --client-id, --client-secret (it will prompt, or take it from an environment variable) and --callback-port; login additionally has --no-browser.
Unapproved servers from .mcp.json show up in the list as awaiting approval and do not connect. Adding one is confirmed with a line saying exactly where the entry went; list walks the servers before printing and checks whether they answer, and serve does not exit — the process stays up and talks over standard input and output.
claude mcp add fs npx -- -y @modelcontextprotocol/server-filesystem ~/work # into the local scope
claude mcp add --scope project github https://api.example.com/mcp -t http # into the project's .mcp.json
claude mcp add-json local-tools '{"command":"./tools","args":["--serve"]}' # the same thing from ready-made JSON
claude mcp list # what is connected and in what state
# captured on build 2.1.252Checking MCP server health…
claude.ai Google Drive: https://drivemcp.googleapis.com/mcp/v1 - ✔ Connectedserena: C:/Users/user/.local/bin/uvx.exe --python 3.13 --from git+... - ✔ Connected
claude mcp serve # serve Claude Code itself as an MCP serverclaude plugin
Plugins and marketplaces. Alias: plugins. A plugin is a bundle of skills, agents, commands, hooks and MCP servers, shipped and updated as one piece from a marketplace. This is where you install them, enable them, disable them and build your own. It works without starting a session, so rolling out an identical set across a whole team is easy to script.
| Subcommand | What it does |
|---|---|
install <plugin> | Install from a marketplace. Alias i. |
uninstall <plugin> | Remove it. Aliases remove, rm. |
enable, disable | Turn an installed one on or off. |
list | List what is installed. Alias ls. |
details <name> | An inventory of components and an estimate of how much context the plugin will eat. |
update <plugin> | Update it; takes effect after a restart. |
marketplace | Managing marketplaces. |
init <name> | Create a plugin skeleton. Alias new. |
validate <path> | Check the manifest, plus the skills, agents and commands in the folder. |
eval [target] | Run the test cases against the plugin and show the scores. |
tag [path] | Create a release git tag, checking the manifest against the marketplace entry. |
prune | Remove automatically installed dependencies that are no longer needed. Alias autoremove. |
Almost every subcommand takes -s, --scope with the values user (the default), project and local, and update also takes managed. Beyond that: install has --config key=value (repeatable) and -y; uninstall has --keep-data, --prune, -y; disable has -a for all of them; list has --json and --available; prune has --dry-run and -y; validate has --strict, which turns warnings into errors; init has --description, --author, --author-email, -f and --with with a list of components: skills, agents, hooks, mcp, lsp, output-style, channel.
Worth knowing: validate works on an ordinary folder of skills and agents too, with no plugin involved.
A plain list prints the installed plugins with their version, scope and state — enabled or disabled; with --json the same thing arrives machine-readable, for a script to parse.
claude plugin install code-review@claude-plugins-official # install from a marketplace
claude plugin list --json # what is installed, machine-readable
# captured on build 2.1.252, without --jsonInstalled plugins:
❯ frontend-design@claude-plugins-official Version: unknown Scope: project Status: ✔ enabled
claude plugin details formatter # how much context it takes up
claude plugin init my-tools --with skills,hooks # a plugin skeleton
claude plugin validate ./my-tools --strict # check the manifest and the folder's contentsclaude auto-mode
Configuring the auto-mode classifier. Auto mode decides what to run without asking and what to stop and ask you about; it decides that from a set of rules, and the rules come from three places — the built-in set, your settings, the project's settings. These subcommands show which of them are in force right now and where each came from, let you read a built-in rule in full, and let you ask the model to critique your own. It is worth coming here when auto mode asks too often or, the other way round, waves through what it should not.
| Subcommand | What it does |
|---|---|
config | What is in force and where from |
defaults | The built-in rules; with --label — the full text of one rule |
critique | The model's critique of your rules |
reset | Reset; --yes — without confirmation |
defaults prints JSON: an object with the keys allow, soft_deny, hard_deny and environment, each holding an array of long text rules with names like "Security Discussion: …". The --label flag cuts one whole rule out of it.
claude auto-mode config # what is in force and where from
claude auto-mode defaults --label 'Git Destructive' # the full text of one rule
claude auto-mode critique # the model's critique of your rules
claude auto-mode reset --yes # reset without confirmationclaude project purge [path]
Delete all the state for a project: transcripts, tasks, file history, the configuration entry. The code itself is not touched — only what Claude Code has accumulated next to it. You need this when a project is finished, or when something has crept into the accumulated state that should not be there. Before running it for real it is worth looking at the list with --dry-run.
claude project purge ~/work/my-repo --dry-run # what would be deleted
# this is how it looks in the documentationPurge plan for /home/user/work/my-repo:
dir: /home/user/.claude/projects/-home-user-work-my-repo project transcripts (.jsonl) and memory/ config: projects["/home/user/work/my-repo"] project entry in ~/.claude.json (trust, history, MCP servers) filter: /home/user/.claude/history.jsonl 12 prompt(s) typed in this project
shell-snapshots/ are not project-scoped and will not be touchedbackups/ may still contain this project entry in old .claude.json snapshots (/home/user/.claude/backups); at most 5 are kept and they rotate out automaticallyDry run: 3 item(s) would be deleted.claude doctor
Diagnostics for the installation, with no session started and nothing modified. It runs a set of checks on how Claude Code is installed and what state its environment is in, and prints the result line by line. It fixes nothing on its own: this is a diagnosis, not a cure. It is the sensible place to start any "why doesn't it work" investigation, before changing settings at random.
claude doctor # diagnostics, nothing modified
# captured on build 2.1.252Claude Code doctor
Running: native (2.1.252)Commit: c0778c45886dPlatform: win32-x64Path: C:\Users\user\.local\bin\claude.exeConfig install method: nativeSearch: OK (bundled)Auto-updates: enabledAuto-update channel: latestLast update attempt: success → 2.1.252 (2026-08-31)Managed settings (remote): not fetched — requires an Enterprise or Team subscription
Remote ControlControl this session from claude.ai/code or the Claude mobile app
No installation issues found.
For a full setup checkup that can also fix issues, run /doctor in a Claude Code session.claude import [source]
Bring configuration over from another coding agent, so you do not have to retype the rules, commands and settings you already assembled for a different tool. The source is given as an argument. --dry-run shows exactly what would come across without changing anything — start there if your current configuration already has something to lose.
claude import codex --dry-run # what would come across from another agentclaude install [version]
Install the native build: stable, latest or a specific version. Native means a standalone binary instead of an npm package, and it can update itself. The argument picks what gets installed: stable is the tested channel, latest is the newest, and an exact number pins the version hard — which is what build machines do, where behavior has to be the same today and in a month.
claude install stable # install the stable buildclaude update
Check for updates and install them. Alias: upgrade. The native build updates itself anyway, so you call this by hand when you need the fresh version right now — for a capability from a specific release, say. Background sessions already running will not pick the update up: you restart them afterwards with claude respawn --all.
It starts with the current version and a check of the channel, and then comes either the install or a message that the download failed.
claude update # update
# the first lines of real output; in that run a download error came nextCurrent version: 2.1.241Checking for updates to latest version...…claude ultrareview [target]
A cloud multi-agent review that prints its findings to the terminal. [costs extra] Pro and Max get three free runs — one-time, never replenished — and Team and Enterprise get none at all; after that the review is charged against credits, usually 5–25 dollars a run depending on the size of the changes, and with credits turned off the launch is simply blocked. [not on every plan] It needs a claude.ai account login: via Amazon Bedrock, Google Cloud Agent Platform and Microsoft Foundry, and in organizations with Zero Data Retention, the command is unavailable.
The analysis does not run on your machine: the changes go off to a cloud session where several agents work on them in parallel, and what comes back to the terminal is a finished list of findings. A run counts from the moment the cloud session started: a review stopped halfway still uses up a free run, while a paid one is charged only for the part that ran. Consent for the credit charge is asked once per conversation.
claude ultrareview # findings print straight to the terminalclaude gateway
Start the corporate authorization and telemetry gateway. Developers reach the API through it rather than directly: the credentials stay on the gateway, and the gateway also collects usage statistics — so keys do not spread across machines and you can see who spends how much. Its configuration comes from a separate file passed by a flag. A purely corporate thing; on your own you do not need it.
The command does not exit: it is a server, and it stays up until something stops it.
claude gateway --config gateway.yaml # the corporate gatewayclaude remote-control
Hidden: hold remote control open as a server. Alias: rc. The machine stays reachable, and you can attach to its session from another device without going near the computer itself. The process does not exit on its own — it lives until you stop it, and --continue picks up the last control session instead of a new one. [not on every plan] It needs a claude.ai account login — remote control does not work with an API key.
claude remote-control --continue # return to the last control sessionclaude self-hosted-runner
Hidden: turn a machine or a container into a site where web, mobile and desktop sessions run. [not on every plan] This is a public beta for Team and Enterprise, off by default: the organization's owner has to allow self-hosted environments, the organization has to have web Claude Code enabled, and it does not work with Zero Data Retention. There is no separate charge for such a site — the hardware is yours, and sessions on it draw on the same organization limit as sessions on Anthropic's infrastructure.
It has a setup subcommand and an orchestrator of its own that brings up runners as the queue builds, plus around twenty flags: the API address, the environment secret file, the hooks folder, the health-check port, capacity, drain and shutdown timeouts, an idle runner's lifetime, a client label. All of it is described in a separate reference on self-hosted environments — contrary to the widespread belief that the subcommand is undocumented.
claude self-hosted-runner setup # prepare a machine as a siteInstalling and updating
There are more ways than npm install, and it is worth knowing, because the native build updates itself and the npm package does not.
# macOS, Linux, WSL — the native installercurl -fsSL https://claude.ai/install.sh | bashcurl -fsSL https://claude.ai/install.sh | bash -s stable # pin the channelcurl -fsSL https://claude.ai/install.sh | bash -s 2.1.236 # pin the version
# Windowsirm https://claude.ai/install.ps1 | iex # PowerShellwinget install Anthropic.ClaudeCode # or through a package manager
# macOS via Homebrew — two different packagesbrew install --cask claude-code # stable, about a week behindbrew install --cask claude-code@latest # the fresh one
# npm — works, but needs Node 22+npm install -g @anthropic-ai/claude-codeThere are signed repositories for apt, dnf and apk as well. And claude install and claude update work once Claude Code is already installed.
Exit codes
A three-line section, but an important one for scripts.
| Code | What it means |
|---|---|
| 0 | Success |
| non-zero | The run failed |
| 143 | Interrupted by a termination signal |
| 137 | The install was killed before it finished |
A subtlety: a bad flag is reported on the error stream before the work starts, while a failure during the work — a missing login, for instance — is printed as the result on ordinary output. Which means the return code alone will not tell "it did not start" apart from "it started and could not finish".
A signal interrupt leaves the current turn unfinished and without a result, kills the process tree of any commands it launched, fires the session-end hooks — and when the session is resumed, that turn continues from where it stopped.
Launch flags
The [not in help] marker means the flag works, but claude --help in build 2.1.251 doesn't print it.
Sessions and resuming them
| Flag | What it does |
|---|---|
-c, --continue | Resume the last conversation in the current folder. Skips background sessions. |
-r, --resume [value] | Resume by id, or open the interactive picker. |
--fork-session | On resume, start a new id instead of reusing the old one. |
--session-id <uuid> | Set a specific session id. |
-n, --name <name> | Display name for the session. |
--from-pr [value] | Resume the session tied to a pull request. |
--no-session-persistence | Don't save the session to disk. Only with non-interactive mode. |
--teleport [session] | Pull a web session into the terminal. |
--cloud [description|id|url] | Create a cloud session or attach to an existing one. |
--remote | [deprecated] The old name of --cloud. Still turns up in other people's scripts. |
--environment <id> | Create a cloud session on your own environment. |
--ref <branch> | [not in help] Which ref to bring the cloud environment up from. Works together with --environment. |
--remote-control [name], --rc | Start a session with remote control enabled. |
--remote-control-session-name-prefix <prefix> | Prefix for the auto-generated names of such sessions. |
--bg, --background | Run in the background and hand control back; prints the id. |
--exec <command> | [not in help] Run a plain command as a background task instead of a session. |
-w, --worktree [name] | Create a fresh git worktree for the session. |
--tmux | Bring up a tmux session for the worktree. |
--teammate-mode <mode> | [not in help] How to show teammates: in-process, auto, tmux, iterm2. |
claude -c # resume the last conversationclaude -r # pick from a listclaude -r 8f3c1d2e --fork-session # resume as a copy, original untouchedclaude -n "payments refactor" # start with a nameclaude --from-pr 1234 # session for a pull requestclaude --bg "run the whole test suite" # in the background, returns an idclaude --bg --exec 'pytest -x' # a background task with no session at allclaude -w feature-x # its own worktree for the sessionclaude -w feature-x --tmux # the same, in tmuxclaude --cloud "fix the flaky CI tests" # a cloud sessionclaude --environment ccpool_abc --ref main -p "run the smoke tests"The --exec flag deserves its own line: it turns the CLI into a launcher for background tasks with no model involved at all. The command runs in a pseudo-terminal, you read its output through claude logs, and you stop it with claude stop. Handy when you want one uniform way to watch long-running processes.
Output and non-interactive mode
| Flag | What it does |
|---|---|
-p, --print | Print the answer and exit. The folder-trust dialog is skipped. |
--output-format <format> | text by default, json or stream-json. |
--input-format <format> | text by default, or stream-json. |
--json-schema <schema> | Schema for validating a structured response. |
--include-partial-messages | Deliver chunks of messages as they arrive. |
--include-hook-events | Include hook lifecycle events in the stream. |
--forward-subagent-text | Forward subagent text and thinking. |
--replay-user-messages | Echo user messages back into the output. |
--max-turns <n> | [not in help] Cap on the number of tool-using turns. The main cost-control lever in CI. |
--max-budget-usd <amount> | Cap on what the API calls may spend. |
--permission-prompt-tool <tool> | [not in help] An MCP tool that answers permission requests in a human's place. |
--ax-screen-reader | Flat text, no frames and no animation. |
--verbose | Override the matching setting from the file. |
claude -p "list the public endpoints" --output-format json | jq -r '.result'claude -p "build a report" --json-schema ./report.schema.json | jq '.structured_output'claude -p "fix the linter" --max-turns 5 # turn capclaude -p "check the style" --max-budget-usd 0.50 # spending capclaude -p "..." --permission-prompt-tool mcp_auth_toolcat diff.patch | claude -p "assess the risk of these changes"Two flags here are the most useful ones and also the ones missing from the help. --max-turns limits how many turns may call tools; when the cap is hit the run ends with a matching marker in the result, and this is exactly what Anthropic officially recommends as the main cost-control lever in CI. --permission-prompt-tool names an MCP tool that will answer permission requests instead of a human — the only way to get approval logic into a non-interactive run.
What you need to know about non-interactive mode
Slash commands do work there. Your own skills and commands are pasted straight into the prompt text. The terminal-only built-ins like /login aren't available, but /model, /effort, /fast, /color and /rename take their value as an argument, and /mcp with no argument prints a text summary of the servers. You change a setting with /config key=value.
claude -p "/model sonnet /code-review low"claude -p "/config thinking=false tell me what this module does"The json format hands back noticeably more than the answer text. Here's a real response to a trivial request, captured from build 2.1.252 and trimmed — only repetitive counters were dropped:
{ "type": "result", "subtype": "success", "is_error": false, "result": "ok", "session_id": "8a792c19-cd74-4531-8311-f5cab07771d8", "num_turns": 1, "total_cost_usd": 0.351315, "duration_ms": 4988, "duration_api_ms": 2029, "ttft_ms": 2271, "stop_reason": "end_turn", "terminal_reason": "completed", "usage": { "input_tokens": 2, "output_tokens": 4, "cache_creation_input_tokens": 34368, "cache_read_input_tokens": 15050, "service_tier": "standard" }, "modelUsage": { "claude-opus-5": { "inputTokens": 2, "outputTokens": 4, "costUSD": 0.351315, "contextWindow": 1000000, "maxOutputTokens": 64000, "provider": "firstParty" } }, "permission_denials": [], "subagent_stats": { "spawned": 0, "completed": 0, "failed": 0 }, "fast_mode_state": "off", "fast_mode_disabled_reason": "sdk_opt_in_required"}Three things here are worth a look. The answer text sits in result — that's what you normally call jq -r '.result' for. The cost in total_cost_usd is computed by the client, not the server, and broken down per model in modelUsage. And usage shows where the money actually went: in the example above, four tokens of answer came with thirty-four thousand tokens of cache writes — meaning you pay for context, not for the answer. With a validation schema, the structured response lands in a separate field alongside these same metadata.
You can save the session_id and continue the conversation later — and, since version 2.1.223, from a different folder.
Flag conflicts. -p together with --bg is an error. So is --cloud with a task description together with -p; but --cloud <id> together with -p will queue the message on that cloud session and exit.
Stream limits. Piped input is capped at ten megabytes: go over and you get a clear error and a non-zero exit code. If the input stream can't be read at all, you get a warning and the run continues with the prompt from the command line.
Background tasks die with the run. A command started in the background during claude -p is torn down about five seconds after the result is printed. Background subagents and workflows are the exception — they get waited on, but never longer than ten minutes of uninterrupted idleness.
--bare is the recommended mode for scripts, and in the future it will become the default behavior for -p. The difference matters: without it, a non-interactive run executes the hooks from the project's .claude/settings.json and connects the servers from its .mcp.json even in a folder you never trusted, without asking a single question.
Model, effort, permission mode
| Flag | What it does |
|---|---|
--model <model> | An alias (fable, opus, sonnet, haiku) or the full name. |
--fallback-model <model,...> | Fallback when the main model is overloaded. Only with -p. |
--effort <level> | low, medium, high, xhigh, max, and per the docs ultracode as well. |
--advisor <model> | [not in help] Turn the advisor on and pick its model. |
--agent <agent> | The agent for the session; overrides the setting. |
--agents <json> | Declare your own agents right on the command line. Validated at startup. |
--permission-mode <mode> | default (also known as manual), acceptEdits, plan, auto, dontAsk, bypassPermissions. |
--dangerously-skip-permissions | Bypass the permission checks. |
--allow-dangerously-skip-permissions | Make the bypass an available option without turning it on. |
--restricted | Restricted mode. |
--safe-mode | Turn off every customization. |
--bare | Minimal mode for scripts. |
claude --model haiku -p "list the changed files"claude --effort xhigh # a session that reasons deeplyclaude --effort ultracode # straight into workflow orchestrationclaude --advisor opus # bring in the advisorclaude --permission-mode plan # start in planning modeclaude --permission-mode acceptEdits # accept edits automaticallyclaude --safe-mode # no hooks, skills, plugins or MCPclaude --bare -p "..." # minimal mode for a scriptThree warnings. --dangerously-skip-permissions doesn't work as an administrator: on Linux and macOS a run as root or through sudo is rejected, because root plus no questions asked means access to everything on the machine. Inside a recognized sandbox the check is lifted. An organization can forbid the mode entirely with the disableBypassPermissionsMode key.
The docs and the binary disagree in two places. For --permission-mode the docs list both default and manual as its alias, while the binary's help lists only manual. For --effort the docs know about ultracode, the help doesn't. In both cases the wider variant works.
--safe-mode and --bare are different things. The first turns off all customization for diagnostics. The second is a minimal execution mode for scripts, where authorization also goes strictly by key. For debugging "something broke after my settings" you want the first one.
Tools, folders, MCP
| Flag | What it does |
|---|---|
--tools <tools...> | The set of built-in tools: an empty string turns them all off, default turns them all on, or list the names. |
--allowedTools, --allowed-tools | Allow tools by list. Both spellings work. |
--disallowedTools, --disallowed-tools | Deny tools by list. |
--add-dir <folders...> | Extra working folders. |
--mcp-config <configs...> | Load MCP servers from files or from JSON strings. |
--strict-mcp-config | Use only the servers from this flag. |
--plugin-dir <path> | Load a plugin from a folder or an archive, for this session only. |
--plugin-url <url> | The same, but the archive comes from a link. |
--channels <servers...> | [not in help] Which MCP servers to listen to for external events. |
--dangerously-load-development-channels | [not in help] Allow channels outside the approved list. |
--disable-slash-commands | Turn off all skills. |
--chrome, --no-chrome | Turn the Chrome integration on or off. |
--ide | Connect to the IDE automatically when exactly one fits. |
Both tool lists accept names separated by commas as well as by spaces. With -p, the servers from --mcp-config are awaited before the first turn, but no longer than the startup timeout; a malformed entry is skipped and the run carries on and finishes normally — which means what you check in CI is not the exit code but the list of server errors in the first event of the stream.
Settings, prompt, odds and ends
| Flag | What it does |
|---|---|
--settings <file-or-json> | Extra settings: a path to a file or a JSON string. |
--setting-sources <sources> | Which settings layers to load: user, project, local. |
--system-prompt <prompt> | Replace the system prompt entirely. |
--system-prompt-file <path> | [not in help] The same, but from a file. |
--append-system-prompt <prompt> | Append to the system prompt. |
--append-system-prompt-file <path> | [not in help] The same, but from a file. |
--append-subagent-system-prompt <text> | [not in help] Append to every subagent's system prompt. |
--exclude-dynamic-system-prompt-sections | Move the machine-dependent chunks into the first user message — the cache is reused better. |
--autocompact <auto|tokens> | Auto-compaction threshold. |
--betas <betas...> | Beta headers on the requests. |
--init | [not in help] Run the init hooks before the session. Only with -p. |
--init-only | [not in help] Run the startup hooks and exit without starting a conversation. |
--maintenance | [not in help] Run the maintenance hooks. Only with -p. |
--file <id:path ...> | Download file resources at startup. |
--prompt-suggestions [on] | Suggestions for the next prompt. |
--brief | Enable the tool the agent uses to talk to the user. |
-d, --debug [filter] | Debug mode with a category filter. |
--debug-file <path> | Write the debug log to a file. |
-v, --version | Version. |
-h, --help | Help. |
claude --settings '{"disableAllHooks": true}' -p "..." # a run without the repo's hooksclaude --setting-sources user -p "..." # ignore the project settingsclaude --append-system-prompt-file ./team-rules.mdclaude --append-subagent-system-prompt "always give file paths"claude --init-only # warm up the container and exitclaude -d "api,hooks" # debug by categoryclaude -d "!1p,!file" --debug-file ./claude.log # everything except these categories--init-only is worth calling out separately: it's the natural way to warm up a container or a working folder in CI — the install and session-start hooks run, and then the process exits without starting a conversation.
And one divergence worth remembering if you write scripts from the docs: -v in build 2.1.251 is --version, even though the docs claim it's the short form of --verbose. Check it on your own version before you rely on it.
What no documentation covers at all
A caveat for the future: since none of this is in the documentation, nobody ever promised to keep it. Building automation on top of it is a risk you take knowingly.
Some fifteen commands for artifacts. Out of this group the official reference has only /artifacts, /design, /design-login and /design-sync. Everything else — /prototype, /doc, /plan-artifact, /artifact-pr-review, /artifact-dashboard, /artifact-report, /artifact-data-table, /artifact-explainer, /artifact-components, /artifact-design, /artifact-diagramming, /artifact-capabilities — isn't mentioned anywhere. Same goes for /whiteboard, /whiteboard-mp and /workshop.
Seven subcommands of /design. Officially it's a single command that takes a description of the design. In the binary it understands sync, login, consent, revoke, import, export and status.
Diagnostics for your own spending. /skill-doctor, which shows unused skills, and /explain-usage, which explains where the money went in plain language, are both undocumented. So is /plugin-types, which generates types for the connected MCP tools.
Five more everyday commands. /brief — short-answer mode. /daemon — managing background services. /cloud-plugins — plugins in cloud sessions. /session (alias /remote) — the address of a remote session and a QR code for it; the reference has /remote-control and /teleport, but not this line. And /install, which installs the native build straight from the session.
Built-in skills everybody uses. /commit, /pr, /update-config, /claude-code-docs, /claude-in-chrome are described neither in the command reference nor in the section on built-in skills. The one indirect mention in the changelog is a bug fix for the agent calling a commit skill that didn't exist.
Commands turned off in this build. /version, /update, /loops, /wellbeing with all its aliases, and /pause-memory are registered but don't work. Not one of them appears in the changelog, neither as removed nor as added: /version, /wellbeing and /pause-memory never show up there once in the whole history, and the mentions of /update are bug fixes from back when it still worked.
Commands that appear depending on state. /limit-reset, /low-priority, /pro-trial-expired, /design-consent, /design-revoke, and /setup-cowork, which belongs to Cowork mode. The documentation admits to exactly one hidden command — dumping memory — and separately mentions that the provider configuration shows up along with an environment variable. About these six, nothing.
Internal entry points and model-only skills. __remote-workflow and workflow-launch-exec, through which the server hands a ready-made workflow to a session. And three skills the agent pulls in on its own that you can't type yourself: keybindings-help, memory-types, cowork-plugin. The mechanism — the user-invocable: false field — is documented; the skills themselves aren't.
How /code-review works inside. The documentation describes the levels qualitatively. How many independent search angles there are, how many candidates per angle, what the cap on findings is at each level, and the fact that on Opus 5 the medium and high levels currently collapse into a single pass — none of that is anywhere. Nor are the three argument-parsing rules that make ultra work only as the first word.
The /sandbox exclude "pattern" form. The official line about this command is one sentence: toggle sandbox mode. Nothing about taking individual commands out of the isolation, and nothing about the subcommand that finishes the install on Windows.
The /name alias of /rename. The reference's line about the command itself is unusually detailed — name sanitization and a length limit — but the alias isn't in it.
The --file flag. Downloading file resources at startup is missing from the list of flags.
Eight settings keys. Not a single line about them in the documentation, in the changelog, or in the published schema: doneMeansMerged — "done means merged"; breakReminder and quietHours — break reminders and quiet hours (a search turns up an article about the consumer Claude app, but that's a different thing and has no settings keys); precomputeCompactionEnabled; daemonColdStart; defaultView; autoUploadSessions; showMessageTimestamps. Plus xaaIdp together with the variable that turns it on, syncClaudeAiPlugins — even though its sibling syncClaudeAiSkills is documented — and proxyAuthHelper.
Keys that exist only in the published schema. sandbox.enabledPlatforms, skippedMarketplaces and skippedPlugins — zero mentions in the documentation and the changelog; the schema remains their only public trace.
Eight environment variables. The official page lists three hundred and forty-nine of them, and these aren't among them: CLAUDE_CODE_GOAL_CHECKIN_MINUTES, CLAUDE_CODE_WORKFLOW_PREFIX_STAGGER_MS, CLAUDE_CODE_DISABLE_AGENT_VIEW, CLAUDE_CODE_DISABLE_WORKFLOWS, CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING, CLAUDE_CODE_DISABLE_CLAUDE_MDS, CLAUDE_CODE_SHELL together with CLAUDE_CODE_SHELL_PREFIX, and USE_BUILTIN_RIPGREP. Some of them have documented neighbours under different names and with slightly different meaning — for turning thinking off, say, or for switching the file search — but those aren't the same thing.
The claude plugin eval subcommand. Running check cases against a plugin: the plugin reference lists ten subcommands, and this one isn't among them.
And the absence of what doesn't exist. There is no /init-verifiers command, /alias isn't a slash command, and there's no .claudeignore file at all. The documentation is naturally silent about things that don't exist — and there's no article about them on the internet either.
The number itself deserves a separate word. The official reference has a hundred and eleven lines, and it says honestly that not every command is available to everyone. How many are registered in total isn't published; in build 2.1.251 it comes to around a hundred and fifty, skills included. Community cheat sheets claim either two hundred and seventy-two (counting the command-line flags along the way) or about seventy — and neither figure rests on anything.
Where to start if you're seeing all this for the first time
There are a lot of tables here, and the first instinct is to close the page. So here's a short practical minimum: what's worth setting up on day one, and what you come back to as the need arises.
Right away, in the user file. Tool permissions: without them you'll be asked about every build and every git status, and within an hour you'll be hitting "allow" without reading — which is exactly the habit that later gets something deleted. The status line: spending and context fill that are permanently in view change your behavior more than any good intentions do. And a bigger cleanupPeriodDays, if you ever plan on digging up an old conversation or rolling back to a checkpoint.
In the project, committed to the repository. Permissions for the commands of this particular project, hooks that hold the invariants, and a .mcp.json with the servers the whole team needs.
For later. The sandbox, self-hosted environments, enterprise keys. They solve problems you most likely don't have yet; and the section on the sandbox is worth reading on exactly the day you first launch an agent that skips confirmations.
A file that's a fine place to start:
{ "$schema": "https://json.schemastore.org/claude-code-settings.json", "cleanupPeriodDays": 365, "fileCheckpointingEnabled": true, "permissions": { "allow": [ "Bash(git status)", "Bash(git diff:*)", "Bash(git log:*)", "Bash(npm run build)", "Bash(npm test:*)" ], "ask": ["Bash(git push:*)"], "deny": ["Read(./.env)", "Read(./.secrets/**)"] }, "statusLine": { "type": "command", "command": "~/.claude/statusline.sh" }}Five permissions already means noticeably fewer questions. One deny on the file with the secrets — because deny beats allow, and it's the cheapest way to make sure the contents of .env never ride into the context. Checkpointing is turned on explicitly: without it /rewind won't bring back a single file, and you usually learn that at the worst possible moment.
Sources
Everything this article stands on, with links. The Claude Code docs live at code.claude.com/docs; the old docs.claude.com addresses redirect there, so a year-old bookmark no longer lands where you expect.
| What it covers in this article | Documentation page |
|---|---|
| Slash commands: the list, the arguments, the version gates | commands |
| Keyboard shortcuts and input behaviour | interactive-mode |
| Code review: levels, flags, target | code-review |
| Cloud review: diff limits and price | ultrareview |
| Permission rules: syntax, path anchors, protected paths | permissions |
Permission modes, dontAsk included | permission-modes |
| Settings: where they live and what overrides what | settings |
| Every settings key, one by one | settings-reference |
| Managed settings and policy sources | managed-settings |
| Environment variables — all 349 of them | env-vars |
| Telemetry, metrics and events | monitoring-usage |
| Hooks: events, exit codes, matchers | hooks |
| Terminal subcommands and launch flags | cli-reference |
| Non-interactive mode and output formats | headless |
| MCP: transports, scopes, timeouts | mcp |
Skills and the SKILL.md format | skills |
| Subagents and their frontmatter | sub-agents |
| Plugins, the manifest and marketplaces | plugins-reference |
Project memory and CLAUDE.md | memory |
| The sandbox: files, network, secrets | sandboxing |
Checkpoints and /rewind | checkpointing |
| Plan limits, credits, cost | costs |
| Fast mode and what pays for it | fast-mode |
| Models, aliases and the credit-billed variants | model-config |
| The advisor | advisor |
| Scheduled routines | routines |
| Auto mode and its rules | auto-mode-config |
| The background agent view | agent-view |
| The status line | statusline |
| Self-hosted environments for cloud sessions | self-hosted-environments-reference |
| Review in GitHub Actions | github-actions |
| Error and warning texts | errors |
| What fills up the context window | context-window |
Two sources are not documentation, and without them half of this article would not exist. The changelog in the anthropics/claude-code repository is the only place that records what was removed or renamed in which version; the product no longer has a release-notes page of its own. The settings schema knows keys the docs never mention — though it also lags behind the product: it still carries a key that was removed in 2.1.234.
Verbatim command output was hunted through the entire docs corpus as a single file — easier than walking a hundred and ninety pages one at a time.
And the third source is the installed program itself. The lists of commands, settings keys and flags were taken from it rather than from the docs: it holds more of them, and in places the two disagree. Everything that could be checked by running it was checked by running it.