Questions & answers

Questions about Claude Code, Codex and Gemini CLI asked in public forums, answered by the editors from the official documentation, with sources.

Q. With the sandbox enabled on Linux, every Bash tool call fails with Exit code 126 and no output at all. What causes this?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #104912Related article →

This is reported when your login shell is zsh and sandbox.enabled is true. The workaround is one line:

SHELL=/bin/bash claude

The reported symptom is that "every sandboxed Bash tool call fails with Exit code 126 and zero bytes of stdout/stderr, in ~1.3s — including shell builtins (true, type echo)". Shell builtins such as true failing is the tell: it means nothing about your particular command or configuration is at fault.

According to the reporter, the script that runs inside the sandbox uses the bash-only form exec 3<&- || exit 126. Closing an already-closed file descriptor is tolerated by bash but fails under zsh, so the script exits 126 before it ever evaluates your command. That is the reporter's analysis, not documented behaviour.

AspectDetail
ConditionsLinux, zsh as the login shell, sandbox.enabled: true
SymptomEvery Bash tool call exits 126 in about 1.3s with no output
Working versionsThe reporter verified 2.1.270, 2.1.286, 2.1.289 and 2.1.291
Failing versionsThe reporter reproduced it on 2.1.302 and 2.1.309
WorkaroundLaunch with SHELL=/bin/bash claude

Check the shell before you suspect your settings

The reporter says it reproduces in interactive mode and under -p, in fresh sessions, and with permissions.deny emptied — so trimming permission rules will not help. When you see exit 126 with zero output, check echo $SHELL first.

A similar report exists for Seatbelt on macOS (#77466). If you turn the sandbox off to keep working, remember that it changes what gets auto-approved; see bypassPermissions in Claude Code and how dangerous operations are handled.

Q. I denied rm in my Gemini CLI policy, but the same thing still gets done another way. What do deny rules actually block?

Answer by the editorsSource: GitHub google-gemini/gemini-cli Issue #29889

A commandPrefix deny rule blocks a command name, not an effect. The documentation defines commandPrefix as "A string or array of strings that a shell command must start with" — a prefix filter on the name.

So a deny with commandPrefix = "rm" matches commands starting with rm, but not:

  • /bin/rm, which starts with an absolute path
  • xargs rm, which starts with a different command
  • eval "rm ...", likewise
  • unlink, a different command with the same effect

The reporter tried 45 rewrites of commands they had forbidden and found that deny rules for six commands let 38 of them (84%) through. Forms such as true; rm file and echo $(cat secret) were caught, so the policy engine behaves as documented. The gap is not in the behaviour but in what readers expect a deny rule to guarantee.

For unattended runs, list what may run rather than what may not, and let everything else fall through to deny or ask_user. In non-interactive mode ask_user is treated as deny, so that fallback fails safe.

[[rule]]
toolName = "run_shell_command"
commandPrefix = ["npm test", "npm run lint", "git status"]
decision = "allow"
priority = 100

[[rule]]
toolName = "run_shell_command"
decision = "ask_user"
priority = 10
KeyWhat it is
commandPrefixA string, or array of strings, the command must start with
commandRegexA regex against the whole command; cannot be combined with commandPrefix
decisionallow, deny or ask_user
priority0 to 999; higher wins

commandRegex is tested against the JSON representation

Per the documentation, commandRegex is tested against the JSON form of the arguments, {"command":"<your_command>"}. Because "command":" is prepended, anchors such as ^ and $ apply to the full JSON string, and the docs advise against using ^ here.

A global deny rule — one without an argsPattern — does something stronger as well: the denied tool is completely excluded from the model's memory, so the model never sees it as an option at all. For a tool you want genuinely unavailable, that is the firmer lever.

Q. The desktop app's Authenticate button never saves OAuth tokens for my pre-registered MCP client, though codex mcp login works. Which is the supported path?

Answer by the editorsSource: GitHub openai/codex Issue #56002Related article →

The documented way to perform an OAuth login is the CLI command: "For a server that supports OAuth, run codex mcp login <server-name>." The docs say nothing about a button in the desktop app. If the CLI works for you, treat it as the supported path.

Configuration is shared between the three clients — the ChatGPT desktop app, Codex CLI and the IDE extension — and lives in ~/.codex/config.toml by default. A login you complete from the CLI is therefore usable from the other clients that read the same configuration.

For a pre-registered client, pass the client ID when you add the server:

codex mcp add example --url https://mcp.example.com --oauth-client-id my-client

For a confidential client, pass the secret too, read from an environment variable:

codex mcp add example --url https://mcp.example.com \
  --oauth-client-id my-client --oauth-client-secret "$MCP_CLIENT_SECRET"

The secret is stored in config.toml in plain text

The documentation is explicit: "Codex saves the secret as mcp_servers.example.oauth.client_secret in config.toml. Keep that file private and out of version control."

The client ID and callback are stored like this:

[mcp_servers.example]
url = "https://mcp.example.com"

[mcp_servers.example.oauth]
client_id = "my-client"
callback_url = "http://127.0.0.1/callback"

The default callback is http://127.0.0.1/callback. Override the port or URL with mcp_oauth_callback_port and mcp_oauth_callback_url. To pick a registration method for one login, use codex mcp login <server-name> --oauth-client-registration cimd (or dcr); the default is auto, and the choice is not stored in config.toml.

codex mcp list shows configured servers, and /mcp shows their status during a session. For adding servers in the first place, see Adding an MCP server to Codex CLI.

Q. Gemini CLI says a node_modules path "resolves outside the allowed workspace directories" when I run list_directory on it, but it is inside my project. Why?

Answer by the editorsSource: GitHub google-gemini/gemini-cli Issue #29863Related article →

The message does not describe the actual cause, which is why changing your workspace configuration does not help.

The error reads:

Path not in workspace: Attempted path "/home/you/node_modules" resolves outside
the allowed workspace directories

It says the path is outside the workspace, but the reported case is a node_modules directory inside the project. Tracing the source, the reporter found that any path containing a node_modules, .git or .env segment is blocked unconditionally, after which the workspace containment check returns false and the tool falls back to the "outside workspace" message. That is the reporter's analysis, not documented behaviour.

Adding directories to the workspace will not fix it, because the cause is different. The documented way to add directories exists for directories genuinely outside your workspace:

gemini --include-directories ../lib,../docs

If you need the agent to look at a dependency's contents, the options today are:

ApproachWhat to do
Don't pass the pathAsk about the dependency's implementation and let the model locate it
Copy the file inCopy the specific file into your working directory first

The same message can also mean what it says

If you see this error for a path that contains none of node_modules, .git or .env, it is literally outside the workspace, and --include-directories is the fix. Whether those three names appear in the path is how you tell the two cases apart.

Note that v0.65.0 optimised ignore filtering and enabled subtree pruning (PR #29582). That is a file-discovery speed change, not a fix for this error. For the rest of that release, see Gemini CLI v0.65 enforces read-only settings in untrusted folders.

Q. When I pick "Yes, and don't ask again" on a permission prompt, how much have I actually allowed? Does it also change the session's permission mode?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #103615Related article →

The scope depends on the tool type, and the documentation's table answers it directly.

Tool typeWhat "Yes, and don't ask again" does
Read-only (file reads, Grep)N/A — it doesn't prompt in the first place
Bash commandsPermanently per repository and command
File modification (Edit / Write)Until session end
WebFetchPermanently per repository and domain
WebSearchPermanently per repository

When the approval does save permanently, it goes to .claude/settings.local.json at the root of the git repository, resolved through worktrees to the main checkout. A file-modification approval is not written to the file at all; as the table says, it lasts until the session ends.

On the permission mode: no official documentation says that "don't ask again" changes it. There is a separate option for that, the third one on the prompt, labelled "Yes, and switch to auto mode", and the docs note it does not appear on every prompt.

You can switch modes with Shift+Tab and list your current rules with /permissions. Those two are how to check whether anything changed unexpectedly.

One behaviour worth knowing: approving a compound command saves a separate rule per subcommand that required approval. Approving git status && npm test saves a rule for npm test, so future npm test calls are recognised regardless of what precedes the &&. At most 5 rules are saved for one compound command.

For a file path, gitignore pattern characters such as [, ] and * are escaped, so the generated rule matches only the literal path you approved. Rules you write yourself are not escaped.

A rule saved from a prompt covers only what the prompt showed

Some prompts offer a one-time approval only. The documentation explains that the "don't ask again" option appears only when the prompt can show you everything it would allow. For anything broader, write the rule yourself in /permissions.

For rule syntax and scope precedence, see Claude Code permissions in settings.json.

Q. The output feels needlessly long and I suspect tokens are being wasted. How do I see what is actually consuming them, and can I rein the output in?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #103616Related article →

Start by measuring rather than guessing. /usage gives you the breakdown.

The Session block at the top shows token statistics for the current session. The dollar figure is computed locally from token counts at list price, unless your organization has a modelPricing table in effect, in which case the Total cost line carries the note at your organization's configured rates. For authoritative billing, use the Usage page in the Claude Console.

On a Pro, Max, Team or Enterprise plan, the same screen also breaks down what counts against your plan limits.

SectionWhat it shows
AttributionRecent usage attributed to skills, subagents, plugins and individual MCP servers, each as a percentage
Behavior flagsBehaviours such as long context or cache misses, flagged when one accounts for 10% or more of recent usage
LoopsThe heaviest /loop or other session-scoped scheduled tasks that ran recently, ordered by total tokens

If long output is the complaint, check first whether Behavior flags shows long context, and whether Attribution puts one MCP server or subagent far ahead of the rest. An MCP server's tool definitions consume context simply by being connected, so a large share there is common.

No documented setting caps comment volume

As of 2026-10-21 there is no settings key in the reference for "write fewer comments" or "be less verbose". The place to put that instruction is CLAUDE.md, and it works better as a concrete standard — "comment only where the intent is not obvious from the code" — than as a bare "be concise".

CLAUDE.md is reloaded from disk at session start and after compaction. An overlong file dilutes its own instructions; see How long should CLAUDE.md be for the sizing guidance.

For the levers that actually reduce spend, and how the plan limits behave, see Claude Code cost and usage with /cost and /usage.

Q. A command that moved to the background has been running for hours. Is there a setting that gives background commands a time limit in an interactive session?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #103047Related article →

As far as the official documentation goes, there is no setting that gives background commands a time limit in an interactive session. This is documented behaviour, not a bug.

The tools reference says: "In a session that runs unattended, such as a run with the -p flag, an Agent SDK application, a CI job, or a cloud session, background Bash and PowerShell commands have a time limit. A local session you work in from a terminal, the desktop app, or the VS Code extension has no time limit on background commands."

SessionTime limit on background commands
-p runs, Agent SDK, CI jobs, cloud sessionsYes (30 minutes by default, 2 hours maximum)
Terminal, desktop app, VS Code extensionNone

The split arrived in Claude Code v2.1.288. From v2.1.285 to v2.1.287 the limit applied in every session, so if you remember it behaving differently, that change is why.

On the unattended side the limit can be raised, though neither variable can shorten it:

# Replace the 30-minute default with one hour (unattended sessions only)
export BASH_DEFAULT_TIMEOUT_MS=3600000
# Raise the 2-hour maximum to four hours
export BASH_MAX_TIMEOUT_MS=14400000

The one documented way to stop an interactive session running something indefinitely is to disable backgrounding itself:

export CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1

That variable disables the run_in_background parameter, auto-backgrounding at a timeout, and the Ctrl+B shortcut together. A foreground command that reaches its timeout then stops instead of moving to the background. It is a blunt instrument, so it fits poorly with work that involves genuinely long-running jobs.

backgroundDeadlineDisabled is not in the official docs

A setting named backgroundDeadlineDisabled comes up in discussions of this behaviour. As of 2026-10-19 that key appears in neither the settings reference, the environment variable list, nor the tools reference, so it could not be confirmed in the official documentation.

Foreground timeouts are controlled by BASH_DEFAULT_TIMEOUT_MS (2 minutes by default) and BASH_MAX_TIMEOUT_MS (10 minutes). See Raising Bash command timeouts with environment variables for those.

Q. Idle compaction never runs for me. A session well past 200K tokens sat idle for 70 minutes without being compacted, and it never happens in the desktop app's Code tab. What are the conditions?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #103040Related article →

The settings reference turns idle compaction on by default only for conversations that meet all five of its conditions. Token count and idle time are two of them, so a conversation can satisfy both and still be excluded by another.

ConditionWhat it requires
SessionAn interactive terminal session
Prompt cacheThe conversation is on the one-hour TTL
Feature flagsClaude Code can fetch feature flags from Anthropic
SizeThe context has reached the threshold, 200,000 tokens by default
Idle timeAbout 54 minutes since the last request, with your computer awake at that point

The desktop app's Code tab is excluded by the first condition. The documentation names an "interactive terminal session" and says nothing about other session types.

The last condition is the one most easily missed: if the machine sleeps during those 54 minutes, nothing runs when it wakes.

A conversation that was actually compacted shows Compacted while idle, before the prompt cache expired, so that message tells you whether it ran.

To change the threshold or turn it off:

{
  "idleCompaction": false
}
# Lower the threshold to 150,000 tokens
export CLAUDE_CODE_IDLE_COMPACT_MIN_TOKENS=150000

CLAUDE_CODE_IDLE_COMPACT_MIN_TOKENS accepts a positive whole number and ignores anything else. Values below 100000 are raised to 100000, the lowest threshold. Both the key and the variable require Claude Code v2.1.290 or later; on an earlier version, setting autoCompactEnabled to false stops it. Turning auto-compact off turns idle compaction off with it.

From v2.1.302, /config has an Idle compaction row you can toggle.

For the auto-compact window itself, see Making Claude Code compact earlier, or never.

Q. My Codex PreToolUse hook calls sys.exit(2) but nothing is blocked on Windows — the command runs anyway, and PowerShell seems to turn exit 2 into 1. Is there a way to deny reliably?

Answer by the editorsSource: GitHub openai/codex Issue #54072Related article →

Codex documents two ways for a PreToolUse hook to signal a block. Use the one that does not depend on the exit code and a shell rewriting it stops mattering.

Option 1 (exit code): the documentation says "You can also use exit code 2 and write the blocking reason to stderr." The word also is a hint that this is the secondary form.

Option 2 (JSON on stdout): emit a hookSpecificOutput object. This works at exit 0.

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "Production config files cannot be modified"
  }
}

The docs also accept an older form with a top-level decision set to "block" and a reason string. Note that for PreToolUse, "Plain text on stdout is ignored" — it has to be JSON.

There is also a Windows-specific command override. Hook configuration takes commandWindows (written command_windows in TOML), documented as "an optional Windows-only command override". The managed-hooks example uses py -3 against a script path as its Windows command. If a shell difference is what mangles your exit code, that is the right place to put an invocation that preserves it.

Which shell runs a hook is not documented

The official hooks page says only that commands "run with the session cwd as their working directory"; it does not name the shell, and it never mentions PowerShell. So "Windows PowerShell 5.1 turns exit 2 into 1" could not be confirmed in the official documentation. That uncertainty is itself the argument for the JSON form: it does not depend on how the exit code travels.

Hooks also have to be enabled. The configuration reference describes features.hooks as "Enable lifecycle hooks loaded from hooks.json or inline [hooks] config".

More detail: What you can configure in Codex's config.toml.

Q. After resuming from a compacted context, the agent starts work without reading the files CLAUDE.md tells it to read first. Are instruction files not reloaded after compaction?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #102190Related article →

Part of it is reloaded and part of it is not. The documentation describes each request in three layers, and compaction affects them differently.

LayerContentChanges when
System promptCore instructions, tool definitionsThe set of loaded tool definitions changes
Project contextCLAUDE.md, auto memory, unscoped rulesSession starts, or after /clear or /compact
ConversationYour messages, Claude's responses, tool resultsEvery turn

CLAUDE.md itself is reloaded. The prompt-caching documentation says of compaction: "It reloads project context from disk, which cache-hits only if CLAUDE.md and memory are unchanged since the session started." From disk, explicitly.

What is not reloaded is the files CLAUDE.md told Claude to read. Those arrived through the Read tool, so they live in the conversation layer — and "Compaction replaces your message history with a summary." The instruction survives; the content it pulled in gets folded into the summary.

Survives compaction:  the CLAUDE.md line "read the memory index first"
Does not survive:     the actual contents of the memory index and protocol files

Subdirectory CLAUDE.md files and rules with paths: frontmatter are in the conversation layer too: "After it loads, the content is part of the conversation history."

A PostCompact hook cannot add context

If you are looking for a way to force the re-read automatically, check the hook event table first. PostCompact fires "After context compaction completes", but its exit-code-2 behavior is "Shows stderr to user only" and it has no JSON decision fields. The events that can inject context, such as SessionStart with additionalContext, do not include PostCompact.

In practice, the reliable move is one explicit instruction right after compaction: "re-read the memory index before continuing." Running /compact yourself at a break between tasks is also easier to manage than letting auto-compaction fire mid-task.

Separately, Claude Code v2.1.293 fixed a bug where Claude sometimes treated its own actions from before a compaction as done after it. If you are on an older version, update first.

More detail: Context management with /compact and /clear.

Q. Auto mode blocks harmless actions, like reading project context files. I thought read-only actions never reached the classifier — why are they being denied?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #101663Related article →

The documentation's "How the classifier evaluates actions" describes auto mode as a fixed four-step decision order where the first matching step wins. Which step your read is landing on is what tells you why it stopped.

Step 2 is the behavior you were expecting: "Read-only actions and file edits in your working directory are auto-approved." A read inside the working directory does not reach the classifier at all. So if one is still being blocked, it is hitting one of that step's exceptions.

The likely causes, roughly in order:

  1. Server-side classifier review is in effect. Listed as an exception to that same step: "In a session with server-side classifier review, read-only and sandboxed shell commands wait for that review and are blocked if it flags them." A read-only command waiting on a review and then being blocked is documented only here.
  2. The file is outside your working directories. "The first read outside the working directories" prompts you. A context file that lives outside the repository qualifies. Adding it with /add-dir or the additionalDirectories setting changes that.
  3. A deny rule matches. Those resolve at step 1, and deny rules block in every mode.
  4. The read is from a network (UNC) path. That prompts you even when an allow rule matches.

Entering auto mode drops some of your allow rules

If the pattern is "this used to go through, and only auto mode stops it", this is why. On entering auto mode, broad allow rules that grant arbitrary code execution are dropped: blanket Bash(*) or PowerShell(*), wildcarded interpreters like Bash(python*), package-manager run commands, Agent allow rules, and Monitor allow rules. Narrow rules like Bash(npm test) stay in effect, and the dropped ones are restored when you leave auto mode.

There is also a documented reason why the denials read as unexplained: "If the classifier blocks, Claude receives the reason. In most sessions the reason names the rule the classifier matched, such as [Data Exfiltration], rather than giving a written explanation."

More detail: Claude Code permission modes.

Q. A single code review consumed about 5% of my weekly usage allowance. Is one task really supposed to cost that much?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #101620Related article →

The documentation has a section called "Why usage climbs in a long session", and a code review hits most of the conditions in it.

The dominant one is context length: "Claude Code sends your full conversation with every request, and each time Claude uses tools it sends another request carrying that batch of tool results." A review reads file after file, so each tool call is another request — and that request carries the whole conversation, including every file read so far. Consumption therefore grows faster than linearly in the number of files reviewed.

Next is cache misses. The prompt cache lifetime is one hour on a subscription, dropping to five minutes once you are drawing on usage credits. Your first message after a longer break reprocesses the full context.

If subagents were involved, each sends its own requests on top of the main conversation. Agent teams are heavier still: teams whose teammates run in plan mode use approximately 7x the tokens of a standard session.

To see which of these actually applied, run /usage. On Pro, Max, Team and Enterprise it flags behaviors that account for 10% or more of recent usage — long context and cache misses among them — and d / w switch between the last 24 hours and the last 7 days.

What the documentation suggests for next time:

  1. /clear when switching to unrelated work. /compact reads the conversation it summarizes, so it is itself a large request
  2. Delegate verbose operations to subagents, so the output stays in their context and only a summary returns
  3. Lower the effort level with /effort or in /model — thinking tokens are billed as output tokens
  4. Match the model to the job: Sonnet handles most coding work and costs less than Opus

注意

Whether that 5% is correct for your plan is not something the documentation can settle, since per-plan limit figures are not published there. For an account-specific billing question, the documented route is to sign in at claude.ai, click your initials in the lower left, and select Get help.

More detail: Check Claude Code usage and cost.

Q. Since Gemini CLI 0.63.0 an "Untrusted Command Flags" warning interrupts even in YOLO mode, on basic file operations through MCP servers. Is there a setting to cut the confirmations down?

Answer by the editorsSource: GitHub google-gemini/gemini-cli Issue #29680Related article →

The "Untrusted Command Flags" warning itself could not be found in the official configuration or command references as of 2026-10-12, and there is no documented key that turns that particular check off. What follows is therefore the set of documented levers for reducing MCP tool confirmations.

1. Trust the server (settings file)

mcpServers.<SERVER_NAME>.trust is documented as a boolean that "trusts the server and bypasses tool call confirmations." It skips the confirmation for that server's tool calls.

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/project"],
      "trust": true
    }
  }
}

Put it in ~/.gemini/settings.json for your user or .gemini/settings.json for the project.

2. Name the tools instead (launch flag)

--allowed-tools is documented as "A comma-separated list of tool names that will bypass the confirmation dialog." That narrows the bypass to specific tools rather than a whole server.

3. Re-check the approval mode

general.defaultApprovalMode takes default, auto_edit or plan. YOLO mode cannot be enabled from a settings file at all — only from the command line with --yolo or --approval-mode=yolo — and --approval-mode cannot be used together with --yolo. Note also security.disableYoloMode: when it is true, YOLO stays off even if a flag enables it (it requires a restart). If your machine is managed, it is worth checking that this is not switched on without your knowing.

注意

trust: true waives the confirmation for every tool call that server makes. On a filesystem server, or any server that can run arbitrary commands, that widens what runs unattended to everything that server can do. Reserve it for servers whose arguments and reachable paths you have pinned down yourself.

More detail: Add an MCP server to Gemini CLI.

Q. In the Codex desktop app, "Always allow" for an MCP tool stops working in a new chat — the prompt returns. I have a per-tool approval_mode in config.toml. Can I authorize across chats?

Answer by the editorsSource: GitHub openai/codex Issue #52963Related article →

It helps to separate what the documentation settles from what it does not.

What it settles: per-tool approval is a documented setting. default_tools_approval_mode is the server-wide default and tools.<tool>.approval_mode is the per-tool override. The docs read: "Default approval behavior for tools from this server. Supported values are auto, prompt, writes, and approve" and "Per-tool approval behavior override."

[mcp_servers.google-ads]
command = "..."
default_tools_approval_mode = "prompt"

[mcp_servers.google-ads.tools.list_accounts]
approval_mode = "approve"

What it does not settle: of those four values, the only one the documentation explains is writes — "The writes mode prompts for tools that aren't marked read-only." What auto, prompt and approve actually do is stated neither in the configuration reference nor on the MCP page.

The official example is still informative: it sets the server default to prompt and then overrides one tool with approval_mode = "approve". That arrangement reads as approve being the more permissive side, the one that does not prompt — but the documentation does not say so outright.

How long "Always allow" lasts: whether the UI's "Always allow" survives into a new chat could not be confirmed in the official documentation. Where the Codex docs do discuss a persisting "Always allow", it is for Browser Use and for Windows Computer Use app entries; there is nothing equivalent for MCP tools.

注意

So the reliable route today is config.toml rather than the UI's "Always allow". If approval_mode = "approve" still prompts every time, the setting may not be reaching the session: check that the [mcp_servers.<server>.tools.<tool>] table name matches the server id and tool name exactly. Whether this key takes effect through the desktop app's path specifically is not stated in the documentation.

A different lever worth knowing: enabled_tools is an allow list of the tool names a server exposes and disabled_tools is a deny list applied after it. Those control whether a tool is offered at all, not how it is approved.

More detail: Set up MCP servers in Codex.

Q. A server I added with claude mcp add never shows up in /mcp, and I can't use it until I fully restart Claude Code. Is there a documented way to load a newly added MCP server mid-session?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #100367Related article →

One thing to separate out first: the Added ... line from claude mcp add only tells you the configuration was written. The documentation says so — "claude mcp add confirms a successful add by printing an Added ... line, which means the configuration was written" — and points you elsewhere to verify the connection: "To check that Claude Code connected, run claude mcp get <name>." Start there.

If you added it at project scope (.mcp.json), it is unusable until approved. /mcp shows ⏸ Pending approval (run claude to approve), and the docs say "Run claude interactively to review and approve it." A server stuck at that step looks exactly like "a restart fixed it."

The documented mid-session mechanisms are these:

MechanismCoversNotes
Reconnect from a server's menu in /mcpOne serverOn a connected or failed server it also discards the cache entry
/mcp reconnect allEvery server that failed or needs authenticationIn the interactive terminal this requires v2.1.284 or later; earlier versions print MCP server "all" not found
/reload-pluginsPlugin-provided serversIn a session without an interactive terminal it doesn't connect or disconnect them; those changes take effect in your next session
Moving the session with /cdServers of plugins the new directory's settings enablev2.1.246 or later; no /reload-plugins needed after the move

注意

Whether a newly added non-plugin server is picked up without a restart could not be confirmed in the official documentation. The mid-session mechanisms it names are the reconnect paths above, plus list_changed notifications that refresh the tool list of a server that is already connected — "An MCP server can change the tools, prompts, or resources it offers while connected."

Note also that toggling a server off in /mcp keeps its configuration: "Toggle a server off in the /mcp panel to stop Claude Code from connecting to it without losing its configuration." Removal is claude mcp remove, and removing a remote server also deletes the OAuth tokens and client registration Claude Code stored for it.

More detail: MCP server scopes in Claude Code.

Q. I set omitClaudeMd: true on a subagent, but a subdirectory CLAUDE.md and path-scoped rules still get loaded, and it does nothing at all for a session started with --agent. Is that intended?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #100366Related article →

omitClaudeMd excludes files from the initial context a subagent starts with. It has no effect on anything loaded later in the session. The documentation places it under the heading "What loads at startup," and that is its scope.

The frontmatter reference reads: "Set to true to launch this subagent without the user, project, and local CLAUDE.md files; managed policy files still load, except for managed subagents." Three things come off — the user, project and local CLAUDE.md — and managed policy files stay.

The memory documentation, describing even the strictest project-instruction setting (managed-only), says: "A subdirectory's CLAUDE.md and .claude/rules/ files, and path-scoped rules, still load on demand." Those load the moment a file in that directory is read. No startup-time exclusion documented anywhere stops that.

For --agent the answer is simpler. The omitClaudeMd row says it is "Ignored when the agent runs as the main session agent via --agent or the agent setting," and "Run the whole session as a subagent" repeats it: "CLAUDE.md files and project memory still load through the normal message flow, even when the agent's definition sets omitClaudeMd." Being ignored there is the documented behavior.

---
name: doc-writer
omitClaudeMd: true
---
This writing agent works only from what the delegation prompt gives it.

That setting does nothing under claude --agent doc-writer. It applies only when the agent is invoked as a subagent.

For a rule that genuinely has to reach the subagent, the documented route is the delegation prompt: "If a rule must, such as "ignore the vendor/ directory," restate it in the prompt you give Claude when delegating." The docs also note that "The main conversation still has your full CLAUDE.md when it reads these subagents' results, so most rules don't need to reach the subagent itself" — the design assumes rules live on the parent side.

注意

Whether an --agent session receives the git status snapshot could not be confirmed in the official documentation. What the docs state about git status is that it is part of a non-fork subagent's initial context, that only Explore and Plan skip it, and that you can't change which subagents receive it; turning the snapshot off at all is the includeGitInstructions setting.

More detail: Claude Code path-scoped rules.

Q. I am on Max and used Fable 5.1 at high effort, and after about 24 hours it said I had exhausted my weekly limit. Is that correct, and which model and effort should I use to keep working?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #100094Related article →

The "weekly limit" message is a plan-side usage window that is shared across models. The official documentation describes it as "a seat-based usage window on a subscription plan, shared across all models, so the developer can't restore access by switching models with /model." Only the model-specific messages — "You've hit your Opus limit" or "You've hit your Sonnet limit" — can be worked around by switching to a model outside that family.

Whether the window you got is the right size for your plan is not something the documentation can settle. Per-plan limit figures are not published in the docs; they point to the pricing page and the Help Center instead. For an account-specific billing question, the documented route is to sign in at claude.ai, click your initials in the lower left, and select Get help.

What the docs do explain is why usage climbs faster than your activity suggests. Claude Code sends your full conversation with every request, so a one-line question in a session that has been open all day still draws usage for the whole conversation. The prompt cache lifetime is one hour on a subscription, and your first message after a longer break misses the cache and reprocesses the full context.

The documented ways to stretch the allowance:

  1. Run /usage. On Pro, Max, Team and Enterprise it flags behavior flags — behaviors such as long context or cache misses that account for 10% or more of recent usage. Press d or w to switch between 24 hours and 7 days.
  2. Lower the effort level with /effort or in /model. Thinking tokens are billed as output tokens. Note that you cannot turn thinking off on Opus 5.5, Sonnet 5.5, Haiku 5.5 or the Fable models.
  3. Match the model to the job. Sonnet handles most coding tasks and costs less than Opus; reserve Opus for complex architectural decisions and multi-step reasoning.
  4. Run /clear when switching to unrelated work. /compact reads the conversation it summarizes, so it is itself a large request.
  5. If you use agent teams, use fewer teammates. Teams whose teammates run in plan mode use approximately 7x the tokens of a standard session.

Once you are at the limit, /usage-credits requests usage beyond the allowance (it isn't available with API key authentication). On Claude Code v2.1.234 or later you can also wait for the reset and have the interrupted task continue automatically, selectable from /rate-limit-options.

More detail: Check Claude Code usage and cost.

Q. Codex stops with "approval required by policy, but AskForApproval::Granular.sandbox_approval is false". The UI is set to "Ask for approval" and my config.toml has no approval_policy. What do I set?

Answer by the editorsSource: GitHub openai/codex Issue #51509Related article →

That error text means a granular approval policy is in effect, whatever the UI shows. approval_policy takes one of three forms — on-request, never, or { granular = { ... } } — and the granular form decides, per category of prompt, whether it surfaces or is auto-rejected. The configuration reference documents five fields:

FieldWhat true means
sandbox_approvalSandbox escalation approval prompts are allowed to surface
rulesApprovals triggered by execpolicy prompt rules are allowed to surface
mcp_elicitationsMCP elicitation prompts surface instead of being auto-rejected
request_permissionsPrompts from the request_permissions tool are allowed to surface
skill_approvalSkill-script approval prompts are allowed to surface

With sandbox_approval set to false, a sandbox escalation approval is rejected without prompting you — which is exactly what the error states. To get the prompt instead, put one of these in ~/.codex/config.toml:

# Surface every approval prompt (the documented choice for interactive runs)
approval_policy = "on-request"
# Pick which categories surface
[approval_policy.granular]
sandbox_approval = true
rules = true
mcp_elicitations = true
request_permissions = true
skill_approval = true

The docs also note that untrusted is unsupported and on-failure is deprecated, and to use on-request for interactive runs.

If your own config.toml sets no approval_policy and you still see this, the value is arriving from somewhere else. The reference documents managed requirements, where an administrator sets "Allowed approval policies" in the Agent Security UI — an admin control, not a user setting. One more related key is approvals_reviewer, which decides "who reviews eligible approval prompts under on-request or granular approval policies" and defaults to user; it does not change sandboxing or actions already allowed inside the sandbox.

注意

How the desktop app's "Ask for approval" setting maps onto these approval_policy keys could not be confirmed in the official documentation. When the UI and the policy actually in force disagree, writing the value explicitly in config.toml is the reliable route.

More detail: Codex approval policy and sandbox settings.

Q. Codex says "requires approval, but approval policy is never" and won't run the task. What do I change?

Answer by the editorsSource: GitHub openai/codex Issue #51161Related article →

The message describes a deadlock: the action needs approval, but your approval policy is never, so there is no one to ask. With no way to prompt, it is rejected.

As of October 6, 2026, the configuration reference lists three forms for approval_policy:

ValueBehavior
on-requestFor interactive runs. Prompts when approval is needed
neverFor non-interactive runs. Never prompts
{ granular = { ... } }Decides per category of prompt whether it surfaces or is auto-rejected

The documentation puts it plainly:

untrusted is unsupported, and on-failure is deprecated; use on-request for interactive runs or never for non-interactive runs.

If you are sitting at the keyboard driving it, on-request is the intended value, not never:

approval_policy = "on-request"

To surface only some prompts, use granular. Categories set to true surface; categories set to false are auto-rejected.

[approval_policy.granular]
sandbox_approval = true      # sandbox escalation prompts
rules = true                 # prompts from execpolicy rules
mcp_elicitations = true      # MCP elicitations
request_permissions = true   # prompts from the request_permissions tool
skill_approval = true        # skill-script approval prompts

If what's failing is an action against an external service, mcp_elicitations is the relevant one: under never, an MCP server's request for confirmation is auto-rejected, so anything that needs a sign-in or a grant can't proceed.

注意

A category set to false under granular does not mean "runs without asking" — it means auto-rejected. To actually restrict what runs, narrow sandbox_mode and the permissions instead of the approval policy.

One caveat about the report this came from: it describes the same action succeeding on the web and failing in the desktop app, and it carries a bug label. Why the effective approval policy differs between platforms could not be confirmed in the official documentation. If fixing the setting doesn't resolve it, follow that report.

For how approval policies and the sandbox combine, see Codex approval modes and sandbox.

Q. In acceptEdits, writes under .git/ are refused even with --add-dir and an explicit allow rule. What am I missing?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #99809Related article →

Nothing is missing from your configuration. .git is a protected path, and permissions.allow cannot pre-approve one by design. The documentation says so directly:

permissions.allow rules in settings files do not pre-approve protected-path writes. The safety check runs before Claude Code evaluates allow rules from settings.

Because the check runs first, an allow rule such as Edit(.git/**) changes nothing. --add-dir only widens the working directories; it has no bearing on the protected-path check.

The per-mode behavior:

ModeProtected-path writes
default, acceptEditsPrompted
planAllowed in interactive terminal sessions with bypass permissions available; otherwise routed to the classifier when auto mode is available, and prompted when it isn't
autoRouted to the classifier
dontAskDenied
bypassPermissionsAllowed

In acceptEdits the write is not auto-approved, which is not the same as forbidden: answer the prompt and it goes through. On a path where no prompt can be shown — dontAsk, or an environment that cannot surface one — that reads as a refusal.

.git is not the only one. The protected directories are:

.git  .config/git  .vscode  .idea  .husky  .cargo
.devcontainer  .yarn  .mvn  .claude (with a few exceptions)

Protected files are listed too, including .gitconfig, .gitmodules, shell configuration (.bashrc, .zshrc, .envrc and friends), package manager configuration (.npmrc, .yarnrc, bunfig.toml), .pre-commit-config.yaml, .mcp.json and .claude.json.

注意

In a session started with --restricted (v2.1.248 or later), the classifier cannot approve protected-path writes either, so auto mode won't let them through.

If you genuinely need these writes unattended, the only documented route is bypassPermissions mode — and since that skips the protected-path check wholesale, the docs limit it to isolated environments like containers or VMs. Rewriting .git is usually better done through git commands than by letting the Edit tool at it.

For how rules are written and in what order they're evaluated, see Configuring permissions in Claude Code's settings.json.

Q. Token usage is still high on Sonnet 5.5 even with reasoning set to low. Why?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #99496Related article →

Two reasons.

1. Extended thinking cannot be turned off on Sonnet 5.5. The model configuration documentation says so directly:

You can't turn thinking off on Opus 5.5, Sonnet 5.5, or the Fable models.

The same passage adds that on these models the session toggle and the /config row read Thinking can't be turned off, and that a saved alwaysThinkingEnabled: false or MAX_THINKING_TOKENS=0 has no effect there. Sonnet 5.5 always uses adaptive reasoning, where the effort level is the primary control over how much thinking happens.

ModelEffort levels
Opus 5.5, Sonnet 5.5, Opus 5, Sonnet 5, Opus 4.8, Opus 4.7low, medium, high, xhigh, max
Opus 4.6, Sonnet 4.6low, medium, high, max

Run /effort with no arguments for a slider, /effort low to set it directly, or /effort auto to clear the level saved for the active model.

2. In a long session the cost driver is context, not thinking. Claude Code sends the whole conversation with every request, and each time it uses tools it sends another request carrying those results. The documentation's "Why usage climbs in a long session" names long context, cache misses, scheduled tasks, subagents and compaction as the causes:

a one-line question in a session that has been open all day still draws usage for the whole conversation

Lowering effort does nothing about that part. What does:

ActionEffect
/clear between tasksDrops the conversation history from later requests
/compact when a session runs longSummarizes history, cutting tokens per request
Narrow what gets readAsk for "20 lines either side of the error", not "the log"
Match the model to the taskSend routine work to a lighter model

On Pro, Max, Team and Enterprise plans, /usage flags any behavior accounting for 10% or more of your recent usage, such as long context or cache misses. That is the fastest way to see which one is actually costing you. The full picture is in Claude Code cost and usage.

Q. I configured Claude Code to answer in my language, but it keeps reverting to English. How do I make it stick?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #99494Related article →

The feature for keeping every response in a given voice is an output style. From the documentation:

An output style is a set of instructions that sets Claude's role, tone, and response format for every response in a session.

You can also put "answer in Korean" in CLAUDE.md, but that file is for what Claude should know about your project, and following it is not guaranteed. The docs' own comparison table routes "every response in a certain voice, length, or format" to an output style.

The usual reason it seems to revert is where the choice is saved. The /output-style command and both menus save your selection to .claude/settings.local.json at the local project level. Open a session in a different project and the setting isn't there. To make it your default everywhere, set it in ~/.claude/settings.json:

{
  "outputStyle": "Concise"
}

The value is case-sensitive. The built-in names are Proactive, Concise, Explanatory and Learning; a value that doesn't match exactly, such as explanatory, silently gives you the Default style. (The /output-style command itself ignores case.) A project's settings files take precedence over your user-level value.

For a language instruction specifically, write a custom style as a Markdown file in ~/.claude/output-styles (user), .claude/output-styles (project), or the managed policy directory:

---
name: Korean
description: Always respond in Korean
keep-coding-instructions: true
---

Always write your responses to the user in Korean. Leave code, commands, file paths and verbatim error messages in their original form.

Without keep-coding-instructions: true, a custom style drops Claude Code's built-in software engineering instructions. If you only want to change the language of responses, always include it.

注意

The documentation is explicit that an output style "applies to every response in a session. It's an instruction Claude follows, so nothing enforces it." For something that must happen without exception, use a hook instead.

In the terminal, style files are read at startup, so restart Claude Code after creating or editing one mid-session. For how the settings files rank against each other, see Configuring permissions in Claude Code's settings.json.

Q. Why can't I use my credit in Claude Code?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #99337Related article →

The thing to establish first is that Claude Code has two billing paths, and credit means something different on each. /status tells you which one your session is on.

PathBillingWhat credit applies
A claude.ai subscription (Pro / Max / Team / Enterprise)Monthly, with a per-seat allowance"Usage credits", which let you keep working past the allowance
A Claude Console API keyPer tokenYour Console account balance

Usage credits are the subscription-side mechanism. Per the documentation, you manage them by signing in to your claude.ai subscription with /login and then running /usage-credits. The important line:

the command isn't available with API key authentication

So a session running on an API key cannot reach the usage-credits screen at all, and a session signed in with a subscription does not draw down a Console balance. When credit appears to exist but is never used, the usual cause is that the credit sits on one path while the session authenticates on the other.

What /usage-credits opens depends on your role:

Your roleWhat it does
Pro or MaxOpens Settings > Usage on claude.ai, where you turn usage credits on or off and see your balance, this month's spend, and your monthly spend limit
Team or Enterprise with billing accessOpens Organization settings > Usage
Team or Enterprise without billing accessAsks you to confirm, then sends a request to your organization's admins

One caveat: the term "promotional credit" could not be found in the official documentation. Where a promotional balance can be spent depends on the terms it was granted under. For billing questions about a specific account, the docs point to support: on a subscription, sign in at claude.ai, click your initials in the lower left and choose Get help; for Console billing, do the same at platform.claude.com.

For the two billing models and how to read your usage, see Claude Code cost and usage.

Q. I told Claude Code to work only inside one folder, but it edited files under ~/.claude/ without asking. How do I actually enforce the boundary?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #99334Related article →

Saying "only this folder" in a prompt is not a boundary. What defines Claude Code's reach is the directory you launched it in, plus any directories added to it. From the documentation:

By default, Claude has access to files in the directory where you launched it.

Launch inside a project and everything under it is in scope. Naming a subfolder in your prompt does not narrow that. If files under your home directory were edited, they were in scope by some other route: the session was launched there, a directory was added with --add-dir, or additionalDirectories lists one. /status shows the current set.

To actually stop it, use settings rather than prose:

{
  "permissions": {
    "deny": [
      "Edit(~/.claude/**)",
      "Edit(//**)"
    ],
    "ask": [
      "Edit"
    ],
    "blockReadsOutsideWorkingDirectories": true
  }
}

注意

Path rules are only evaluated for Edit(path) and Read(path). The documentation states that Claude Code checks file permissions against Edit(path) and Read(path) rules only: a path rule written for Write, NotebookEdit or Glob is accepted but never consulted, and you get a startup warning. Write Edit(docs/**), not Write(docs/**).

Rules are evaluated deny → ask → allow, and the first match decides. Specificity does not change that order, so a broad deny beats a narrower allow.

Setting permissions.blockReadsOutsideWorkingDirectories to true makes the file tools refuse the paths it fences in every permission mode. In auto mode, Claude Code offers to turn it on the first time Claude reads outside the working directories.

To narrow the reach itself, launch in the folder you mean, or move the session with /cd <path>. For assembling the whole permissions block, see Configuring permissions in Claude Code's settings.json.

Q. Auto mode denied my git history-rewrite command as [Git Destructive], and saying yes in chat gets the same denial. Is there no approval path?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #98569Related article →

There is one — four, in fact, all documented on the auto mode configuration page.

First, why "yes" doesn't work. Per the docs, the explicit user intent that overrides a classifier soft_deny is a message that directly and specifically describes the exact action Claude is about to take. General requests don't count: asking Claude to "clean up the repo" doesn't authorize force-pushing, but asking it to "force-push this branch" does. A bare "yes" names no action, so it isn't treated as intent.

The options:

What you wantHow
Allow this kind of action from now onAdd a prose rule to autoMode.allow; allow rules act as exceptions to soft_deny
Allow it just this onceSay specifically what the action is in your next message and let Claude retry
Recover the denied callOpen /permissions, select the Recently denied tab, press r on the action; exiting the dialog lets Claude retry it
Add the rule without editing a fileThe Auto mode tab in /permissions (v2.1.246 or later)

autoMode.allow goes in ~/.claude/settings.json. The classifier does not read autoMode from .claude/settings.json or .claude/settings.local.json — both live in the repo directory, so a checked-in repo could otherwise inject its own allow rules. Include the literal "$defaults" in the array to keep the built-in rules.

{
  "autoMode": {
    "allow": [
      "$defaults",
      "git commit --amend --reset-author on unpushed commits is allowed: it only corrects authorship and never rewrites published history"
    ]
  }
}

To read the full wording of the rule that fired, run claude auto-mode defaults --label 'Git Destructive' (v2.1.208 or later). That rule also clears "when the user asked to amend/reword/fixup", so how you phrase the request can be enough on its own.

Q. CLAUDE.md is injected into the system prompt at session start, so why is it not applied before the first answer?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #98533Related article →

The premise doesn't match the documentation: CLAUDE.md is not in the system prompt. The memory documentation states it directly:

CLAUDE.md content is delivered as a user message after the system prompt, not as part of the system prompt itself. Claude reads it and tries to follow it, but there's no guarantee of strict compliance, especially for vague or conflicting instructions.

So the expectation that it must be applied because it is in the system prompt doesn't hold. You can confirm the file loaded by running /context and checking the list under Memory files — if it is listed, Claude can see it.

For better adherence, the docs name three things:

  • Make instructions concrete enough to verify. "Use 2-space indentation" rather than "format code properly"
  • Look for conflicting instructions across your CLAUDE.md files, nested CLAUDE.md files in subdirectories, and .claude/rules/. When two rules contradict each other, Claude may pick one arbitrarily
  • Keep each file under 200 lines. Longer files consume more context and reduce adherence, per the docs

For an instruction that must run at a specific point — before every commit, after each file edit — write it as a hook instead of prose. Hooks execute as shell commands at fixed lifecycle events and apply regardless of what Claude decides to do.

If you want instructions at the system prompt level, pass --append-system-prompt at launch. It is better suited to scripts and automation than to interactive use.

Q. My CLAUDE.md lists 11 mandatory project rules, but they are ignored across sessions. Can CLAUDE.md rules be enforced?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #97999Related article →

CLAUDE.md shapes what Claude tries to do. It is not the mechanism that decides what is allowed. The official permissions documentation states this directly:

Permission rules are enforced by Claude Code, not by the model. Instructions in your prompt or CLAUDE.md shape what Claude tries to do, but they don't change what Claude Code allows.

So a rule like "nothing executes without an explicit go-ahead in this session" is not guaranteed by writing it in CLAUDE.md. The file is loaded, but following it is left to the model's judgement. The same page names the four things that do enforce: /permissions, permission rules, a permission mode, and a PreToolUse hook.

For anything you genuinely need blocked, write it in permissions in settings.json. Rules are evaluated deny → ask → allow, and the first match in that order determines the outcome. Specificity does not change the order, so a broad deny beats a narrower allow.

{
  "permissions": {
    "ask": [
      "Bash",
      "Edit"
    ],
    "deny": [
      "Bash(rm -rf *)"
    ]
  }
}

For conditions that rules cannot express, use a PreToolUse hook. Per the docs, PreToolUse hooks run before the permission prompt on every tool call, and their output can deny the call, force a prompt, or skip the prompt. A hook that exits with code 2 stops the call before permission rules are even evaluated.

Hook decisions do not bypass permission rules, though: deny and ask rules are evaluated regardless of what the hook returns, so a matching deny still blocks the call and a matching ask still prompts even when the hook returned "allow".

On the cross-session part: CLAUDE.md is loaded every session, but how the model treats a summary of earlier context is its own judgement. If that behavior has to be fixed, pin it with permissions or a hook rather than with prose.

For the full setup, see Configuring permissions in Claude Code's settings.json.

Q. Can I reload plugins, skills and slash commands inside an open session? I enabled the plugin in settings and ran reload, but no slash commands show up.

Answer by the editorsSource: GitHub anthropics/claude-code Issue #95924Related article →

You can. The command is /reload-plugins, and it reloads plugins, skills, agents, hooks, plugin MCP servers and plugin LSP servers together. Starting a new project is not required.

If slash commands still do not appear, the documentation names three causes.

1. The change is pending because of the prompt cache

Closing the /plugin menu makes Claude Code run /reload-plugins for you — but if the reload would invalidate the prompt cache, it warns and leaves the changes pending instead. Apply them anyway with:

/reload-plugins --force

The same applies when the install summary said Run /reload-plugins to activate.

2. You did not type it into the session directly

/reload-plugins does run in sessions without an interactive terminal — the desktop app, the Agent SDK, and -p — as of v2.1.260. But it runs only when you type it directly into that session. Sent over a remote connection, such as Remote Control or a relayed chat message, the command declines without reloading anything. In the desktop app, type it into the prompt box yourself.

3. A stale cache

The official troubleshooting entry for plugin skills not appearing is to clear the cache:

rm -rf ~/.claude/plugins/cache

Then restart Claude Code and reinstall the plugin.

One limit to know about: in a session without an interactive terminal, the reload does not connect or disconnect plugin MCP servers. Those changes take effect in your next session. Plugins enabled on your claude.ai account sync into terminal sessions on v2.1.273 or later.

Q. Gemini CLI's sandbox fails with EACCES during builds when I run it under rootless podman.

Answer by the editorsSource: GitHub google-gemini/gemini-cli Issue #29338Related article →

Rootless podman uses a user namespace by default, so the UID inside the container does not map directly to your host UID. Bind-mounted files then become unwritable, and tools that recreate build directories — node-gyp, for one — fail with EACCES.

Gemini CLI provides a hook for passing arbitrary flags to the container runtime. The documentation states that for container-based sandboxing you can inject custom flags into the docker or podman command using the SANDBOX_FLAGS environment variable. Multiple flags are space-separated.

The podman flag that lines the UIDs up is --userns=keep-id:

export GEMINI_SANDBOX=podman
export SANDBOX_FLAGS="--userns=keep-id"
gemini --sandbox

If you also hit mount permission errors on a system with SELinux enabled (Fedora and relatives), add the flag the documentation gives as its example:

export SANDBOX_FLAGS="--userns=keep-id --security-opt label=disable"

One caveat: --userns=keep-id is a podman flag, and the example the Gemini CLI documentation shows is --security-opt label=disable. --userns=keep-id itself does not appear in the official docs — what is documented is the SANDBOX_FLAGS mechanism for passing runtime flags through.

GEMINI_SANDBOX accepts true, docker, podman, sandbox-exec, runsc and lxc. Use --security-opt label=disable only where you need it, since it turns off SELinux labeling.

Q. Can a deny rule for .env in Claude Code be overridden by an allow rule in settings.local.json?

Answer by the editorsFrequently searched questionRelated article →

No. deny wins over allow regardless of the scope it is written in (user, project or local). With this in the project .claude/settings.json, a broad Read allow in someone's settings.local.json still cannot read .env:

{
  "permissions": {
    "deny": ["Read(./.env)", "Read(./.env.*)"]
  }
}

Note that deny rules govern Claude Code's tool calls. Reading through a shell command such as cat .env is a separate rule, and prefix matches like Bash(cat .env:*) are easy to sidestep. For values that truly matter, keep .env outside the workspace or inject secrets at run time from a secrets manager.

Q. My hook is in settings.json but never runs. What should I check?

Answer by the editorsFrequently searched questionRelated article →

Work through these in order.

  1. Run /hooks and check the hook is listed. If not, the JSON is invalid (trailing comma, quotes) or the file is in the wrong place (.claude/settings.json or ~/.claude/settings.json).
  2. matcher is a regular expression on the tool name: Edit|Write|MultiEdit for file edits, Bash for commands. Check the event name spelling too (PreToolUse / PostToolUse).
  3. Make sure the script is executable (chmod +x), has a shebang line, and that jq is installed. Calling it as bash .claude/hooks/format.sh avoids the permission issue.
  4. Start with claude --debug to see each hook's execution, exit code and stderr.

Restart the session after editing settings to be sure the change is loaded.

Q. An MCP server I added with claude mcp add shows as failed in /mcp. How do I find out why?

Answer by the editorsFrequently searched questionRelated article →

In most cases the server itself is failing to start. The quickest way to see the real error is to run the same command outside Claude Code.

npx @playwright/mcp@latest

Three causes account for most of these:

  • The first npx run times out: it is still downloading the package. Start it manually once so it lands in the cache, then reconnect
  • Environment variables aren't reaching the server: check that the value you passed with --env KEY=value, or a ${VAR} in .mcp.json, exists in the shell you launched Claude Code from, with echo $VAR
  • Node.js is too old: check node -v against the version the server requires, usually 18 or later

There is also an argument-order trap the documentation calls out. If the server name comes directly after --env, the CLI reads that name as another KEY=value pair and rejects it. Put at least one other option, such as --transport stdio, between --env and the server name.

claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY --transport stdio airtable \
  -- npx -y airtable-mcp-server

Everything after -- is passed to the server untouched. Without it, Claude Code tries to parse the server's own flags, such as --port, as its own options.

Once it starts, check the state with claude mcp list, and re-run /mcp inside the session.

Q. npm install fails inside Codex. Is the sandbox blocking it?

Answer by the editorsFrequently searched questionRelated article →

Yes. The workspace-write sandbox blocks network access by default, so package downloads fail. With the on-failure approval policy Codex asks whether to rerun the command outside the sandbox; approve it and the install goes through. To stop being asked, allow the network in ~/.codex/config.toml:

sandbox_mode = "workspace-write"

[sandbox_workspace_write]
network_access = true

Allowing the network also allows data to leave the machine, so enable it only for repositories you trust. Research-only sessions can stay in read-only.

Q. Gemini CLI stopped responding partway through on the free tier. Have I hit a limit?

Answer by the editorsFrequently searched questionRelated article →

Free use with a personal Google account has both a per-minute and a per-day request limit. A single instruction is rarely a single request: the model is called again each time the CLI reads a file or runs a command, so one instruction often costs several requests. Work through a long task and you can reach the daily limit by the afternoon.

There are two ways forward:

  • Wait for the reset. Both the per-minute and per-day limits recover on their own
  • Set GEMINI_API_KEY to switch to the paid tier, which is metered from that point on
export GEMINI_API_KEY="your-key"
gemini

The limit figures are revised from time to time, so check the official documentation for the current numbers rather than relying on one written down somewhere. For work code, an API key or Vertex AI is the better choice anyway, because the data-use terms differ from the free tier's.

Q. I accidentally let an AI tool read a file containing an API key. What should I do now?

Answer by the editorsFrequently searched questionRelated article →

There is no way to unsend data, so revoking the key and issuing a new one is the only reliable response. Work through it in this order:

  1. Revoke the key at the issuing service and issue a replacement
  2. Check that service's own usage logs for anything unexpected between exposure and revocation
  3. Identify how the file was read and close that path: a Read(./.env) deny rule in Claude Code, moving the file outside the workspace for Codex, or .geminiignore for Gemini CLI
  4. If the key was also committed, revoking is still step one; removing it from git history is a separate job on top

Do not skip the revocation on the grounds that only you saw it. How the data is handled during its retention period depends on your plan and contract, and that is not something you can verify after the fact.

Questions are summarized from public posts (GitHub issues, community forums) with a link to the source. Answers are written by the editors from the official documentation.