Hidden tricks and gotchas
The things that don’t make the front page of the docs but consistently bite or empower. Sources: GitHub release notes, source-code spelunking, Anthropic engineer blog posts, community discoveries, and observed behavior across long-running production deployments. Each entry is tagged with its source — [official] for documented but easily missed, [observed] for undocumented-but-stable as of 2026-05-25.
See also
- claude-code-cli — the documented CLI surface
- prompt-caching — the cache layer where most cost surprises live
- claude-models-and-capabilities — model-specific quirks
1. CLI flags missing from --help [official]
Per code.claude.com/docs/en/cli-reference: “claude --help does not list every flag, so a flag’s absence from --help does not mean it is unavailable.” The web docs are authoritative.
Flags you’ll never see in --help but exist:
--bare— skip all auto-discovery, fast scripted calls--exclude-dynamic-system-prompt-sections— share prompt-cache across users/machines--include-hook-events— stream hook fires instream-jsonoutput--allow-dangerously-skip-permissions— let user toggle to bypass mid-session without starting there--from-pr <ref>— resume sessions linked to a PR--max-budget-usd <amount>— hard cap on-pmode spend--init/--init-only/--maintenance— explicit Setup-hook triggers--teleport— pull a web session into the local terminal--remote "task"— create new claude.ai web session from CLI--no-session-persistence— for hermetic CI runs--replay-user-messages— echo stdin user messages back on stdout
2. Environment-variable overrides that change everything [official]
[official] but easily missed:
| Env var | Effect |
|---|---|
CLAUDE_CODE_SUBAGENT_MODEL | Override every subagent’s model regardless of definition. Useful for cost A/B testing. |
CLAUDE_CODE_MAX_OUTPUT_TOKENS | Cap output tokens per request — useful to force concise behavior or prevent runaway generation. |
MAX_THINKING_TOKENS | Cap extended-thinking budget — useful for cost control. |
MAX_MCP_OUTPUT_TOKENS | Default 25,000. Bump for servers returning large outputs. |
ENABLE_TOOL_SEARCH | true / false / auto / auto:N — controls MCP tool deferral. Default behavior depends on platform (Vertex AI defaults to false). |
ENABLE_CLAUDEAI_MCP_SERVERS | Set false to disable claude.ai-side MCP servers. |
SLASH_COMMAND_TOOL_CHAR_BUDGET | Fixed char budget for skill descriptions (overrides skillListingBudgetFraction). |
CLAUDE_CODE_USE_POWERSHELL_TOOL | Enable native PowerShell tool on Windows. |
CLAUDE_CODE_DISABLE_AUTO_MEMORY | Disable auto-memory writes. |
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD | Load CLAUDE.md from --add-dir paths (off by default). |
CLAUDE_CODE_SKIP_PROMPT_HISTORY | Disable transcript writes — for sensitive sessions. |
CLAUDE_CODE_NO_FLICKER | Force fullscreen renderer (better for tmux). |
CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS | Throttle OTel header refresh. |
CLAUDE_REMOTE_CONTROL_SESSION_NAME_PREFIX | Prefix for auto-named remote-control sessions. |
ANTHROPIC_SMALL_FAST_MODEL | Model used for statusline / fast operations. Default Haiku. Set to your favorite cheap model. |
BASH_MAX_OUTPUT_LENGTH | Cap bash tool output. Default 30000 chars. |
BASH_DEFAULT_TIMEOUT_MS / BASH_MAX_TIMEOUT_MS | 120s / 600s defaults. Crank for long builds. |
3. Prompt-caching breakpoint placement tricks [official]
Per the prompt-caching docs (and easy to miss):
-
Breakpoint on the LAST identical block. Most people put
cache_controlon the long doc and forget about it; correct is to put it on the last static block (the doc OR the system prompt tail, whichever is later). -
Lookback window = 20 blocks. Growing conversations past 20 blocks need additional breakpoints. In practice this only matters for >20-turn conversations — most agents are safe.
-
Hidden tool-use system prompt is cached as part of the tools level. The 346-token overhead is “free” once cached. So with cached tools, you pay it once per cache lifetime, not per request.
-
Cache pre-warming via
max_tokens: 0: only works on Claude API and Microsoft Foundry; silently ignored in batches (per docs). -
Cross-workspace isolation as of 2026-02-05: a shared prompt across two workspaces doesn’t share a cache. Per-workspace on Claude API / Claude Platform on AWS / Foundry; per-organization on Bedrock / Vertex.
-
extended-cache-ttl-2025-04-11beta header is opt-in for 1-hour TTL. Forgetting it silently downgrades to 5-min on the samettl: "1h"param. -
The longer-TTL ordering rule: if you mix 1h and 5m breakpoints, the 1h ones must come first in the request. Out-of-order returns 400.
-
Cache invalidation matrix:
tool_choicechanges invalidate tools+system; images invalidate tools+system; thinking-param changes invalidate tools+system+message-cache. See prompt-caching §3.4. -
cache-diagnosis-2026-04-07beta — adds enhanced cache-attribution to response usage. Useful for debugging.
4. Tool-use parallelism quirks [observed]
disable_parallel_tool_use: false(default) lets Claude emit multipletool_useblocks per turn. Order doesn’t matter for execution — run all in parallel. Order may matter for your business logic — if tool A’s result affects tool B’s execution, sequence them.tool_choice: {"type": "any"}or{"type": "tool", "name": ...}silently errors when extended thinking is on. Per docs: “thinking + forced tool use” not supported.- Tool inputs with very large strings (>10k tokens) sometimes cause Claude to truncate mid-token — wrap in
tool_resultblocks with text wrappers instead of trying to pass large inputs. strict: trueon tools adds 5-10% latency but eliminates “missing required field” loop bugs. Worth it for any production tool.token-efficient-tools-2025-02-19beta reduces tool-encoding overhead — useful for high-parallel-tool-call agents.
5. Vision / image token-counting surprises [official]
- Formula:
tokens ≈ (width × height) / 750. Worked example: 4032×3024 iPhone photo = 16,256 tokens before you’ve asked a question. Downsample to ~1280px max edge for nearly the same accuracy at 1/10 the cost. - 8000×8000 (max) image = 85,334 tokens by itself. Don’t.
- Animated GIFs: first frame only — silent for the rest.
- HEIC/HEIF from iPhone: unsupported — convert to JPEG.
- Base64 must be standard, not URL-safe —
-and_chars break the parser. Common bug. media_typemismatch (PNG bytes withimage/jpegheader) → silent corruption or 400.- 200k-context models cap at 100 images / request; 1M-context models (Opus 4.7, Opus 4.6, Sonnet 4.6) cap at 600. But 32 MB body limit usually hits first — use Files API references for many large images.
- PDF pages count as both text + image — each page ~1,500-3,000 image tokens plus extracted text tokens.
- Image tokens count toward cache-minimum thresholds — a 4,000-token image hits Opus’s 4,096-token cache threshold by itself.
6. MCP stdio buffering — the classic hang [observed]
The single most common MCP server bug: stdio servers must flush after each JSON-RPC line. Python:
import sys
sys.stdout.write(json.dumps(response) + "\n")
sys.stdout.flush() # ← without this, Claude Code hangsNode:
process.stdout.write(JSON.stringify(response) + "\n");
// stdout.write is sync by default in Node when connected to a pipe; usually OKIf a stdio server hangs on startup, 90% of the time it’s missing flush or running with a logging library that buffers.
7. MCP tool-output size limits [official]
- Default: 25,000 tokens per MCP tool call (
MAX_MCP_OUTPUT_TOKENS) - Warning at 10,000 tokens
- Hard ceiling: 500,000 chars per tool, but only for tools that opt in with
_meta: {"anthropic/maxResultSizeChars": N}in theirtools/listresponse - Excess output is persisted to disk and replaced with a file reference
8. Streaming chunk boundaries [observed]
text_delta events can split words and even tokens in arbitrary places. Don’t write code that assumes deltas are word- or sentence-aligned. Concatenate deltas, then process the accumulated buffer.
For input_json_delta events on tool use, accumulate all partial_json strings, then parse the full JSON at content_block_stop. Don’t try to parse partial JSON — it’s almost never valid.
9. Model-specific quirks [observed + docs]
Opus 4.7
- Sampling parameters silently ignored —
temperature,top_p,top_khave no effect. Useeffortlevels instead. - Adaptive thinking only. Manual
budget_tokensreturns 400. Use{"type": "adaptive"}. - More literal instruction following — won’t generalize a rule from one item to all. Spell it out (“Apply to every section, not just the first”).
- Uses tools less than 4.6 — to encourage tool use, raise effort to
xhigh. - More direct / less validation-forward voice — if you need warmer, prompt explicitly.
- Spawns fewer subagents by default. Tell it when subagents are desirable.
- New tokenizer — old token-counting code under-counts. Use
count_tokensAPI. - Strong house style (cream backgrounds, serif fonts) — break with concrete alternatives.
Sonnet 4.6
- Cheap and fast — default for most agents.
- Adaptive thinking recommended; manual deprecated.
- Tends to guess values for missing required tool args; use Opus for ambiguous-input flows or set
strict: trueand rely on description quality.
Haiku 4.5
- 200k context (not 1M).
- 4.5 is the only Haiku with adaptive thinking absent (manual only).
- Excellent for routing, classification, draft-and-review pipelines.
- Often misses subtle instructions that Opus / Sonnet catch — use shorter, more explicit prompts.
Haiku 3.5 (Bedrock / Vertex only)
- Different tool-use overhead: 264 / 340 tokens vs 346 / 313 for Claude 4.
- 2,048 minimum cacheable tokens vs 1,024 for newer.
10. Hooks gotchas [official]
- Exit code 2 ignores stdout JSON — pick one path: either exit non-zero for stderr-based error, or exit 0 with JSON output.
- Hook stdout cap at 10,000 chars — larger output saved to file. Preview path provided.
CLAUDE_ENV_FILEletsSessionStart/Setup/CwdChanged/FileChangedhooks mutate Bash env for the rest of the session. Powerful, easy to miss.- Hook dedup: identical handlers (same command+args) run once per event. Add a no-op arg to force a duplicate.
async: trueis fire-and-forget. UseasyncRewake: trueto wake Claude on exit code 2.- Plugin hooks ignore
mcpServers,permissionMode,hooksfrontmatter (security). - Managed hooks immune to
disableAllHooks— admins can enforce policy. SessionStartandSetupevents only supportcommandandmcp_toolhandler types — not HTTP/prompt/agent.WorktreeCreatenon-zero exit aborts worktree creation.
11. Permission escape hatches [official]
--dangerously-skip-permissions=--permission-mode bypassPermissions. Skips most checks, but per docs not literally everything — some safety checks remain.--allow-dangerously-skip-permissionsadds the bypass mode to the Shift+Tab cycle without starting in it. Lets you start inplanand switch later.permission_prompt_toolMCP tool: handles permission prompts in non-interactive mode. Useful for headless agents.permissions.ask[]is the middle ground — requires confirmation, doesn’t auto-deny.Skill(*)denies all skills;Skill(deploy *)denies only matching skill invocations.
12. Slash-command / skill internals [official]
- Skills and commands are the same thing now —
.claude/commands/X.mdand.claude/skills/X/SKILL.mdboth create/X. disable-model-invocation: trueremoves the skill from Claude’s context entirely — Claude won’t know it exists. Sparingly.${CLAUDE_SKILL_DIR}is a critical substitution for plugin skills — lets bundled scripts find themselves regardless of cwd.!`backtick`execution can be disabled per-policy viadisableSkillShellExecution: true. Bundled skills exempt.- Skill content stays in context for the session — keep it lean. Detail goes in
reference.md. - After auto-compaction, only 25,000 tokens total budget for re-attached skills (5,000 per skill, most-recent-first).
13. Background-agent supervisor [observed]
- The daemon (
claude daemon) supervises up to 12 background workers by default. claude respawn <id>restarts a session — useful after aclaude updateto pick up the new binary across all running agents.claude rm <id>removes from list; transcript persists for--resume.- Background sessions appear in
--resumepicker as of v2.1.144, markedbg.
14. Settings file precedence [official]
Highest to lowest:
- Managed (system / MDM)
- Command-line args
- Local (
.claude/settings.local.json) - Project (
.claude/settings.json) - User (
~/.claude/settings.json)
parentSettingsBehavior (“first-wins” or “merge”) controls how nested project paths merge. Easy bug: a user-level rule looks ignored because a stricter project rule overrides.
15. Auth precedence [official]
- CLI flag
- Env var (
ANTHROPIC_API_KEYetc.) apiKeyHelperscript in settingsclaude.aisession via/login
claude.ai-side MCP connectors only show when claude.ai is active auth. Setting ANTHROPIC_API_KEY env var or using apiKeyHelper silently hides them. Run /status or claude auth status to see which is active.
16. Citation / RAG edge cases [official]
citations.enabled: truemust be set on all-or-none documents in a request — mixing returns 400.cited_textdoesn’t count toward output or input tokens (free quotes!).- Citations incompatible with
output_config.format(structured outputs) — returns 400. - PDF
page_locationis 1-indexed, exclusive end.[5, 6)= page 5 only. - Scanned PDFs without text layer → citations don’t work. Run OCR first.
- Custom-content documents aren’t sentence-chunked — chunk granularity = your block granularity.
17. Files API quirks [official]
- Beta header
files-api-2025-04-14always required — silent 404 without. - 32 MB max file size (matches request body limit).
- 30-day retention (per file).
purposefield used for routing —"vision"for image/PDF,"code_execution"for sandbox-loaded files.- Files are per-workspace. Another workspace can’t reference your
file_id. - Files API result retention is 29 days for batches, 30 days for files — gap of 1 day means “fire and forget” is risky.
18. Batches API quirks [official]
- 100,000 messages OR 256 MB max per batch.
- 24-hour hard deadline; SLA most under 1h.
max_tokens: 0(cache pre-warming) not allowed in batches — silently? per docs explicit error.- 50% discount applies to everything including cache reads/writes and server-tool surcharges.
custom_idmust match^[a-zA-Z0-9_-]{1,64}$; collisions cause undefined which-wins.- Streaming silently ignored in batches.
- Results retained 29 days.
- Use 1-hour cache TTL with batches — 5m TTL is wasted (most batches > 5m).
19. Computer use safety + UX [official + observed]
- 1024×768 is the safe default; higher resolution often degrades performance despite intuition.
- 1080p is the documented sweet spot per Opus 4.7 docs; 720p / 1366×768 for cost.
- Anthropic auto-runs a prompt-injection classifier on screenshots — flags potential injections, steers Claude to ask for confirmation. Opt out via support.
- Always screenshot after every action — verify state. Don’t click from memory.
- The PyAutoGUI failsafe (mouse to top-left corner) is on by default in the reference impl — kill switch. Don’t disable.
- Hard rule: confirm with user before Delete / Remove / Sign out / Disconnect / Reset / Discard / Don’t-Save / payment / financial / firewall / antivirus / closing window with save prompt.
20. Effort-level surprises [official]
- Opus 4.7
lowactually means low — won’t go above-and-beyond. Under-thinking risk on complex tasks at low effort. xhighis the documented Opus 4.7 recommendation for coding/agentic.highis the floor for intelligence-sensitive use cases.maxshows diminishing returns; sometimes prone to overthinking.- Effort can be overridden per skill (
effort:in SKILL.md) or per subagent — settings inherit.
21. Statusline tricks [official]
- Statusline command receives full session JSON on stdin:
{session_id, model, cwd, transcript_path, ...}. Usemodelto color-code Opus vs Sonnet vs Haiku. - Cap output at ~80 chars or it’ll wrap weirdly.
- Runs every ~5 seconds — keep it fast (no network calls).
22. Tokenizer differences [official]
Opus 4.7 has a new tokenizer vs Opus 4.6 and earlier. Token counts differ. Old token-counting libraries under-count Opus 4.7. Always use messages.count_tokens() (or client.messages.batches.count_tokens for batches).
For tokenizer ratios (per docs):
- Opus 4.7: ~555k English words per 1M tokens
- Other Claude 4: ~750k English words per 1M tokens
- Roughly the same characters/token (~3.4 chars/token) but Opus 4.7 has shifted token boundaries
23. Skill-discovery directory tricks [official]
.claude/skills/is walked up from cwd to repo root. Starting in a subdirectory still picks up root-level skills.- Nested
.claude/skills/inside--add-dirpaths are discovered on demand when working with files there. Monorepo-friendly. - Adding a top-level
.claude/skills/dir mid-session requires restart; editing existing skills is hot. - Project skills win over user skills which win over enterprise — except plugin skills which use namespacing
<plugin>:<name>.
24. The --bare shortcut [official]
For scripted Claude Code calls in CI:
claude --bare -p "task" --output-format jsonSkips auto-discovery of hooks, skills, plugins, MCP, auto-memory, CLAUDE.md. Drastically faster startup (~10x). Tools available: Bash, Read, Edit only. Sets CLAUDE_CODE_SIMPLE=1.
Use for: lint hooks that invoke Claude inline, fast CI checks, throwaway transformations.
25. The Pro/Max subscription vs API key tradeoffs [official]
- Claude Pro / Max (
claude auth logindefault): subscription quota covers usage. Better for individuals. - API key (
claude auth login --console): pay-per-use. Better for predictable / scriptable / shared workloads. - As of 2026-06-15: Agent SDK and
claude -pusage on subscription plans draws from a new monthly Agent SDK credit, separate from interactive usage.
26. Rate-limit header tier scaling [official]
Rate limits scale with usage tier (Tier 1 → 4+). Auto-promotion based on spend over time. Headers show your current tier limits:
anthropic-ratelimit-requests-limit: 4000 # per minute
anthropic-ratelimit-tokens-limit: 400000 # per minute (combined)
anthropic-ratelimit-input-tokens-limit: 200000
anthropic-ratelimit-output-tokens-limit: 200000
Track these and back off proactively — 429s eat into your latency budget.
27. The 529 overload code [observed]
529 overloaded_error is distinct from 429 rate_limit. 529 means organization has more load than current capacity. Different retry semantics: don’t immediately retry, wait 30-60s with jitter. Common during peak hours or after model launches.
28. The Claude.ai connector loophole [observed]
Connectors added in claude.ai/customize/connectors auto-flow to Claude Code when logged in via subscription. Way faster to set up than claude mcp add — but only works with claude.ai-side auth, hidden when using API key.
29. Persistent memory across sessions via subagent definitions [official]
Subagents can set memory: user / memory: project / memory: local in frontmatter. Creates ~/.claude/agent-memory/<name>/ directory. The subagent persists insights across sessions. Distinct from the memory_20250818 tool (which is for explicit file ops by the agent).
30. Top 10 “most-useful hidden tricks” — TL;DR
For the impatient, the highest-leverage gotchas from above:
- Use
--exclude-dynamic-system-prompt-sectionsin scripted multi-user workloads — dramatic cache-hit improvement. extended-cache-ttl-2025-04-11for any session > 5 min — 1h cache pays off after 2 hits.CLAUDE_CODE_SUBAGENT_MODEL=haikuto A/B test cost on agent-team workloads.MAX_THINKING_TOKENS=8000to cap thinking-budget spend on Opus 4.7.token-efficient-tools-2025-02-19beta for high-parallel-tool-use agents.--bare -pfor CI / lint hooks — 10× faster startup.- Skill
context: fork+agent: Explorefor read-only research tasks that don’t pollute main context. - Memory tool + 1h cache + Sonnet is the cheapest long-running-agent recipe.
- Always
additionalProperties: falseon tool schemas — eliminates a class of loop bugs. - Pre-fill assistant turn with
{to force JSON output without function calling.
31. Further reading
- Claude Code releases on GitHub — the changelog is where many of these surfaces
- Python SDK README + CHANGELOG
- TypeScript SDK README + CHANGELOG
- Anthropic engineering blog — operational posts often surface undocumented patterns
- Claude Code troubleshooting
- Beta headers enum — the authoritative list of beta header strings
- Service tiers — Priority Tier behavior
- Rate limits — full tier breakdown