# Personal preferences ## Workflow - **Specs, plans, and design docs go into the repo they describe.** When brainstorming, plan-mode, or any flow produces a persistent document (design spec, implementation plan, ADR, etc.), the final destination is always the working tree of the project it belongs to — typically under `docs/` (or wherever the project conventionally keeps them). Scratch locations like `~/.claude/plans/.md` are fine *during* plan mode, but the moment plan mode exits with an approved artifact, copy it into the repo and `git commit` it. Don't ship a feature while its spec or plan still lives only in a scratch file. If a project's `AGENTS.md` / `CLAUDE.md` specifies a different directory, that wins. ## Code health Strategic over tactical, with follow-through. Each change should leave the codebase at least as coherent as it was — don't just *flag* messiness, address it. - **Default to acting on cleanups, not just mentioning them.** If you notice duplication, a band-aid, or an inconsistency, fix it as part of the work rather than leaving it as an observation. "I noticed X but didn't do it" is the anti-pattern — it leaves the user with both the mess *and* the homework of cleaning it up. - **Scope boundary for inline cleanups: on-path AND reversible AND within files already being touched.** Inline when all three hold. If the cleanup crosses files, would be hard to undo, or is parallel to the task — surface it in 2-3 sentences and ask before pursuing. - **Tolerate duplication until the pattern is real.** Removing existing duplication is welcome; inventing new abstractions speculatively is not. Rule of three: don't unify two instances, wait for the third. - **Treat friction as architectural data.** Awkward expression, edits that ripple across files, patterns that recur with subtle variations, structure fighting the task — these are the architecture telling you something, not just noise to push through. Propose architectural changes when they'd make the code more sustainable. Frame as proposals with a clear ask ("now, or follow-up?"), not silent rewrites. ## Interpreting requests Treat vague input and question-back responses critically, not as instructions. - **Vagueness is not authorization.** "Make it cleaner", "maybe X?", "looks good but…" are signals to ask one clarifying question, not green lights to pick an interpretation and run. - **A tangent is not an answer.** If you ask "A or B?" and get "maybe X?", that's a new question, not a pick. Surface the mismatch and ask which the user meant — don't bundle the tangent into the active task as if it were direction. ## Sandbox - **Always run commands sandboxed first.** Only use `dangerouslyDisableSandbox: true` as a last resort after a sandbox-related failure — never preemptively. - **On sandbox failure:** analyze the error message for the blocked path, then suggest adding it to `sandbox.filesystem.allowWrite` in `~/.claude/settings.json`. Only fall back to `dangerouslyDisableSandbox: true` if the path can't be determined or the user prefers it. ## Temporary Files - **Use `$TMPDIR` or `.tmp/` (project-local) for temporary files.** Never use `/tmp` directly or paths like `/Library/Application Support` — those are not in the sandbox allowlist and trigger permission prompts. - `$TMPDIR` is set by the sandbox to a writable path. `.tmp/` inside the project directory is always writable without prompts. - Ensure `.tmp/` is listed in `.gitignore` when creating temp files in a tracked repo. ## Shell — literal `!` in Bash commands - **Never put a literal `!` in an inline Bash command.** Claude Code's Bash tool escapes every `!` to `\!` at the transport layer before any shell sees it — even inside single/double quotes and in non-interactive shells (anthropics/claude-code#61121, a regression of a fix shipped in 2.1.87). The stray backslash corrupts downstream tools: Python `!=` → SyntaxWarning + broken string, jq, Jira JQL (`status != Done` → server 400), branch names, etc. `bash -c '...'` and quoted heredocs do **not** avoid it. - **One rule covers everything:** if a command needs a `!`, write the command/code to a file with the Write tool under `.tmp/` and run the file. `.tmp/` is prompt-free via the `Edit(.tmp/**)` allow rule in `~/.claude/settings.json`. Do **not** create the file with inline `printf`/`echo >` — that re-escapes the `!`. - Need a literal `!` inline anyway: ANSI-C hex `$'\x21'` (e.g. `B=$'\x21'; cmd "${B}=…"`) yields a real `!` with no literal `!` in the command. ## Tooling - **`ccc` for semantic code search.** Repos containing a `.cocoindex_code/` directory are indexed by [`ccc`](https://github.com/cocoindex-io/cocoindex-code). Reach for it on conceptual questions ("where is X used / which files do Y / what handles Z"), where a keyword grep would miss indirect usage: `ccc search '' --path '**'`. Pass `--path '**'` — without it, results are filtered to the current working directory's subtree. The `ccc` skill has the full reference; `grep`/`rg`/`find` remain fine for exact-string lookups. - **`ccc index` / `ccc init` are read-safe maintenance.** They only write to the gitignored `.cocoindex_code/` directory, never to source. Run them without confirmation prompts — at session start, after refactors, or before a search when the index may be stale. Treat like `grep` for permission purposes, not like a code edit.