Skip to main content

Claude Code

ToolSourceTargetMCP servers
Claude Codehome/dot_claude/settings.json~/.claude/settings.json (whole file)~/.claude.json top-level mcpServers
Claude Code global confighome/.chezmoidata/claude_global_config.json~/.claude.json declared top-level keysnone

Claude Code settingsโ€‹

settings.json declares the Claude settings schema with $schema. Neovim's jsonls uses it for option and value completion, K hover descriptions, and validation, including when editing home/dot_claude/settings.json. The explicit reference covers the chezmoi source path, which SchemaStore's .claude/settings.json pattern does not match. The schema can lag behind newly released options.

AreaValue
Modelclaude-opus-5-5, effortLevel: medium (also pinned in modelSettings)
Advisortool off: env.CLAUDE_CODE_DISABLE_ADVISOR_TOOL=1 (main session and subagents); advisorModel: opus stays for stop-review
ThinkingalwaysThinkingEnabled: false; Opus 5.5 rejects disabled thinking, so Claude Code sends adaptive thinking anyway and effort is the only control
PermissionsdefaultMode: bypassPermissions; dangerous-mode prompt skipped
Subagent nestingenv.CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH=1
Auto-compactautoCompactWindow: 600000: compaction near 567k instead of near 1M
Auto-memoryautoMemoryEnabled: false; ,ai-kb is the only durable memory
Away recapawaySummaryEnabled: false
Subagent cachesubagentPromptCacheTtl: "1h": prompt cache for subagents and helpers, not the 5m default
Hooksnone in settings; the mods below load through env.CLAUDE_CODE_PLUGIN_DIRS (below)
Diff paneloff: enabledPlugins sets cc-plugin-diff@builtin: false; ~/.claude.json has diffSidebarOpen: false (below)
PluginsenabledPlugins turns on rust-analyzer-lsp@claude-plugins-official; its server is the rust-analyzer component of the mise Rust toolchain
Authnative Claude account auth; no apiKeyHelper or ANTHROPIC_BASE_URL override

Instructions come from ~/.claude/CLAUDE.md (symlink to ~/AGENTS.md); skills from ~/.claude/skills โ†’ ~/.agents/skills. The only custom agent is exact_agents/k-agent-reviewer.md.tmpl (see Subagents); search uses the built-in Explore. Fullscreen mode and push notifications are on. The diff panel beside the transcript is off. enabledPlugins disables the built-in cc-plugin-diff pane. Without that plugin, Claude Code falls back to its older diff sidebar, which opens on its own in terminals at least 144 columns wide unless ~/.claude.json has diffSidebarOpen: false. run_onchange_after_07-merge-claude-global-config.sh.tmpl sets each key under claude_global_config in ~/.claude.json with scripts/merge_claude_global_config.py and keeps Claude's runtime state. /diff still opens the older sidebar and saves diffSidebarOpen: true; running /diff again closes it and saves false, and the hook sets false again only when its hash changes. To bring the pane back, delete the enabledPlugins entry; /diff then opens it and saves that choice. Keep at least one key under claude_global_config: an empty set fails the hook and stops chezmoi apply. Removing a key stops managing it but leaves its last value in ~/.claude.json. settings.llama-cpp*.json.tmpl hold the settings ,claude-llama-cpp passes for local models: model-scoped high effort, thinking off.

Modsโ€‹

Claude Code mods are TypeScript function-hook plugins (early-access API). Sources live in home/dot_claude/exact_mods/ and deploy to ~/.claude/mods/. settings.json loads them all with env.CLAUDE_CODE_PLUGIN_DIRS. Pi, OMP, and the other harnesses do not run them.

ModEventBehavior
behavior-map-guardtool.call on Edit, Write, NotebookEdit, Bash; session.endRuns ,behavior-map affected <path>. Refuses the first edit per session in an unmapped directory (each directory on a two-directory unmapped: line counts on its own); adds a context note for touched entries. After a Bash command that may write, adds the same notes as context for the files it changed.
intent-guardprompt.submit; tool.call (every tool); session.compact; classic.StopCalls ,task hook (Staying on the goal). Adds the intent card, saved preferences, and correction notes to each typed prompt, marked as the user's own words for the evidence ledger. Refuses the first Edit, Write, or NotebookEdit per session with no card; adds a note to an edit outside the card's Scope:; adds a zoom-out note with the card every 25 main-loop tool calls and after compaction. Adds keep-the-card instructions to compaction. On Stop, after any Stop hook beneath it sent nothing back and no subagent or workflow is in flight, sends the turn back while a Done when item is open or a changed file is outside Scope:. A failed ,task lets everything through.
sop-guardtool.call on Bash, Edit, Write, NotebookEditRefuses the hard-rule breaks listed below.
stop-reviewturn.start; tool.call (every tool); classic.StopChecks the final answer's format, then has advisorModel review the turn, and sends the turn back once with both (again after the wake from a pause on a subagent or workflow, since that answer is new work; a paused answer that asks the user gets the review alone). Format checks (no model needed): files changed (edits, or Bash changed the git working tree) and the final message has no Checked: list (a Checked line counts, bold or not, with or without a colon or a parenthetical; a sentence that starts with "Checked" does not); or a turn that used a tool or was woken by a task notice lists work under a heading the report has no list for (Known gaps:, Next steps:, Unverified:, โ€ฆ); or such a turn ends with a question whose last prose paragraph (before any list or code block) does not start with Decision needed: and that is not an item under Open: or Proposed:; or such a turn's final message runs past the ยง8 word budget (250 words for a report with Checked: or a turn that changed files, else 200; lists and tables count, fenced code and blockquotes do not (including fences nested in lists and lazy blockquote continuations); the message tells the agent to keep the answer when the prompt asked for detail, a write-up, or a long list, since a prompt regex misread negations, plurals, and incidental words). A turn woken by a task notice keeps the last typed prompt's ask and list exemptions; words in the notice never set them. Each message names what it found, what to do now, and the ~/AGENTS.md rule, with the limits ยง1 sets on acting without asking (the STEP text in hooks/checks.ts); the question and parked-work messages also tell the agent to put a claim only a live check could settle under Open: with that check as its blocker (ยง3 step 8); the parked-work message adds that cleanup is never a step for the user; the missing-Checked: message asks only for the checks ยง3 steps 3-4 call for, one Checked: item per Done-when item or changed behavior with each fact's verified [C<n>], and the same Open: placement for a claim only a live check could settle. Review: when a turn that used tools or asks the user something (a ? in its prose outside code and URLs, or a Decision needed: line) ends, sends advisorModel (opus) the current turn's request, messages, tool calls with cut inputs and results, and final answer, ~/AGENTS.md, and the skill procedures the SOP points to (k-git/references/commit-push.md, k-cleanup, k-long-jobs, k-review and its references/review_fixes.md; a missing file is left out), and adds up to 5 concerns; the reviewer is told what the format checks already send, so it does not repeat it. PASS adds nothing. When this session wrote an intent card (,task hook evidence), the card and evidence ledger follow the record, and the reviewer judges first whether the answer achieves its Goal and Done-when items and stayed in its Scope. Its prompt holds no rules of its own: it explains the record, asks for every break of those rules the agent can fix now (the 5 most severe if more; no preferences), names the sections to check first (ยง2, ยง1, ยง3 steps 3 and 8, ยง5), and says that unfinished work includes a Proposed: item ยง1 makes part of the task or a Decision needed: question that needs no judgment of the user's (ยง1). With ~/AGENTS.md unreadable or no advisorModel it skips the review; the format checks still run.

sop-guard rules:

RuleSourceRefusal
Edit of a chezmoi-managed target (symlinks resolved)~/AGENTS.md ยง6always; names the source path
A command that prints a secret: pass show, security โ€ฆ -w, op read, gh auth token, cat .env (quoted text, heredoc bodies, and # comments are not commands; a # inside ${โ€ฆ} or after ( in [[ โ€ฆ ]] is no comment)~/AGENTS.md ยง5always, unless $(...), a redirect, or a pipe into a non-printing command takes the output
Bare tmux kill-serverk-tmuxalways, unless -S or -L
A default-server tmux change (send-keys, source-file, attach, โ€ฆ)k-tmuxonce per subcommand per session

This repo also has a project plugin, .claude/skills/dotfiles-guard/, which loads only in sessions started in this repo. It refuses make check-full, make test, bin/check --full (repo AGENTS.md), scripts/test_runner.py, and scripts/check.py --full (user request). A command inside a quoted string, such as bash -c "make test", is not seen. It keeps a copy of sop-guard's shell.ts, because a plugin cannot import outside its folder; test_claude_mods.py fails when the copies differ.

A "once" refusal passes on retry: the model retries only when the condition in the refusal message holds.

All of them fail open: a failed hook or a missing command lets the call through. behavior-map-guard never refuses a docs-only, test-only, /tmp, or non-git edit. A Bash command cannot be refused before it runs, because its paths are unknown. For a main-agent command that may write (a redirect, sed -i/--in-place, perl -i, a scripting runtime, a file command, or git apply/checkout/restore/stash/mv), the guard creates a marker file for that call just before it runs, so parallel calls do not share one; the marker is removed after the scan. After it runs, the guard reads git status -z of the session's repo (a rename by its new path) and keeps the files whose change time is newer than the marker, so mv and cp -p count. It asks for area init when one of them is a code file in an unmapped directory, once per directory, and notes touched entries. The note does not use up the Edit refusal for that directory. It sees only the session's repo, skips subagent commands and deletions, leaves out commands that move HEAD (merge, pull, rebase, switch, cherry-pick, am, reset: code the agent did not write; a branch-switching git checkout leaves the files it switched clean, and carried changes keep their change time), and misses a write by a command that matches none of those patterns. stop-review snapshots only the git repo of the session's working directory, so Bash changes in another repo are not seen. A turn whose only change is git commit, stash, or reset also changes the snapshot, so a commit-only reply is sent back once. stop-review sends a turn back at most once per stretch (from the turn's start, a wake, or a paused send-back to the next of these), with every finding (the review's concerns, evidence-citation failures, missing Checked:, parked work, ending question, word budget) in that one message, because each extra send-back made the agent rewrite its whole answer again. A paused answer that asks the user ends a stretch with a review-only send-back, once per wake, so a turn goes back at most three times between wakes. It knows its own send-back (an intent-guard send-back reaches it as a block from beneath and is passed through, like /goal's): the send-back continues inside the same turn with no turn.start, and that continuation is not checked again, unless the send-back came on a pause. It does not read stop_hook_active, which an engine nudge (brief mode, a reply gate, a /goal check-in) and a managed-settings Stop hook's block also set, so the answer after such a nudge or block is still checked. After an answer passes, a later Stop in the turn needs Checked: only for changes made after it, so a re-delivery nudge (the answer sent again through a tool, with no text) does not go back. A failed review does not drop the format or evidence checks' findings. Missing or failed ledger access logs a message and fails open. An answer another Stop hook sends back, such as /goal or a settings hook, is passed through unchecked, since it is not final; the answer that ends the turn is checked and reviewed. An empty-text turn.start continues the turn only after a pause; otherwise it is a turn with no typed prompt, including an idle notice after an interrupted send-back, which gets its own checks. After a hot reload the format checks run at once, and the review waits for the next turn, since it needs the turn's request. The send-back ends, once, with a line telling the model that its reply replaces its last answer, so it writes the whole current answer with the fixes folded in (~/AGENTS.md ยง8). The question check stays quiet when the user's prompt asks to be asked ("ask me", "asking us"), unless a negation ("not", "never", โ€ฆ) comes up to three words before it ("don't even need to ask me"), or "stop", "quit", or "avoid" up to two words before it, not across "and", "then", or "to". "Don't hesitate to ask me" and a negation in a condition ("if not sure, ask me") stay invitations. Markdown blockquotes and fenced code are excluded from the question and parked-work checks, so quoted drafts do not trigger them. The parked-work check matches only a heading line (plain, #, or bold; not a bullet) named Known gaps, Not done, Not yet done, Still/Left to do, Remaining work/steps/items, Next step(s) or Follow-up(s) (either may start with Suggested, Recommended, or Possible), TODO(s), Unverified, Not verified, or Deferred; the one-word labels Next:, Remaining:, and Pending: count only alone on their line. A heading whose whole list is "none", "n/a", or "nothing" (no other item or line after it) passes. It stays quiet when the user's prompt asks for such a list: "list", "show (me)", "give me", or "tell me" at the start of a sentence or after "please", "and", "then", "also", "just", "can you", or "could you", up to 30 characters before "next steps", "gaps", "remaining", "left", "todo", or "follow-ups"; "what's/what is/what are" before "next", "left", "remaining", or "missing"; "what remains"; "handoff"/"hand off"; or a prompt that names the heading itself, in quotes (a "Known gaps:" list) or before "list", "section", "heading", or "block" (a Next steps section). The format checks read the Decision needed: label by form only; whether the item has a pick and is the user's to decide is judged by the review (and OMP's Gate), so it is checked only where an advisor model is set. Decision needed:, Open: and Proposed: labels also work as list items (-, * or +), matching the evidence ledger's heading rules. A subagent's own turn.start (it carries agentId) is part of the main turn and resets nothing. A Stop with a subagent or workflow still in background_tasks pauses the turn: stop-review sends nothing back unless that answer asks the user something; then only the review runs, told the answer is not final, and the format checks wait for the next answer that is not paused. The turn.start that the task notice raises (in claude -p its text starts with <task-notification>; an empty text also counts) then continues the same turn, so the answer that ends it is checked against the user's request; a typed prompt starts a new turn. A background shell task alone does not pause it, because a server never ends. stop-review is the Claude counterpart of OMP's Gate advisor: Claude's own advisor runs only when the model calls it. It reviews at most once per stretch, plus once per wake on a paused answer that asks the user (even after a send-back), not on an answer another Stop hook sends back. The turn opens at the turn.start prompt; for a turn with no typed prompt, at the last task notice after the earlier turns' last tool call and the previous final answer; else at its first tool.call id; else, for a typed turn, at its <command-name> row; else the turn under review holds only the final answer. So a skill body or an idle task notice is not read as the request. The current turn keeps up to 180,000 characters plus its request and final answer, each message cut to 4,000. Older turn parts drop first. Earlier raw chat is omitted; the card and evidence ledger preserve decisions and finding resolutions. See Evidence and decisions for claim checks, citations, freshness and exact finding deduplication. The reviewer sees only that record, not the files, so the block asks the model to reject a wrong concern with a reason. After a hot reload it waits for a new turn; a send-back's continuation does not count. It adds one model call between wakes in a turn that used tools or asks the user something (up to three when a paused answer also asks), stays off while advisorModel is unset, and logs a failed review. sop-guard reads $(...) inside double quotes as data: echo "$(pass show x)" passes. Its chezmoi rule sees only managed files: a new file written into an exact_ target directory passes, and the next chezmoi apply deletes it. Test a mod with claude plugin test ~/.claude/mods/<mod>; claude plugin validate checks what it hooks. The engine writes .claude-plugin/types/ and tsconfig.json into each mod folder, so the mod folders are not exact_.

LetsFGโ€‹

LetsFG is intentionally not exposed through the shared MCP registry.

DecisionReason
not in MCP registryflight tools are irrelevant to most sessions
skill-loaded on demandagents load k-letsfg/SKILL.md only for travel searches
local CLIletsfg uv tool comes from home/readonly_dot_default-uv-tools.tmpl
normal agent modepasses LETSFG_BROWSERS=0 per invocation
browser connectorsexplicit opt-in

Playwriter remains a fallback for rendered UI checks or booking-adjacent flows that need explicit user confirmation.