CLAUDE.md@user · diff
git:20261013.1ff4f1d to git:20261016.160c4f5
21 added, 35 removed. Audit A to A.
# Claude
## Style
- - Don't join independent clauses with semicolons or em dashes. End the clause with a period. Swapping one connector for another is not a fix.
+ - Don't join independent clauses with semicolons or em dashes. End the sentence instead. A colon or other connector in their place is not a fix.
- Wrap filenames and code identifiers with `backticks` in any markdown context.
- - Write PR, issue, MR, and tracker-key (`ABC-123`) references in chat replies as links, like `[dotfiles#827](https://github.com/bendrucker/dotfiles/pull/827)`. The terminal doesn't autolink bare IDs. Take the URL that `gh`, `glab`, or the tracker tool printed, or build it from the repo's remote. With no known URL, keep the bare ID rather than guess one.
+ - In chat replies, write PR, issue, MR, and tracker-key (`ABC-123`) references as links, like `[dotfiles#827](https://github.com/bendrucker/dotfiles/pull/827)`, because the terminal doesn't autolink them. Take the URL that `gh`, `glab`, or the tracker tool printed, or build it from the repo's remote. With no known URL, keep the bare ID.
- Don't hard-wrap markdown prose you author. In an existing file, follow its wrapping.
- Include a trailing newline in all new files.
- Put explanation of code you're writing in a message before the edit.
- - Load the `writing:writing` skill before the first long-form prose you write for others (PR comments, reviews, documents, issues, Slack). One load covers the rest of the session.
+ - Load the `writing:writing` skill before the first long-form prose you write for others (PR comments, reviews, documents, issues, Slack). One load covers the session.
## Organization
- Don't create or extend catch-all modules like `utils`. Name modules for what they hold.
- Split code into files before splitting it across directories.
- Don't number steps or phases in code ("Phase 1:", "Step 2:"). Use descriptive function names called in sequence.
- ## Curation
+ ## Customizations
- Every customization costs tokens on every session. Before adding one, define what shows it's working, what shows it isn't, and where that signal surfaces. Accommodate Claude Code's native defaults. Override one only as an experiment with removal criteria.
+ Before adding a skill, hook, rule, or CLAUDE.md line, define what evidence shows it works, what shows it doesn't, and where that evidence surfaces. Override a Claude Code default only as an experiment with removal criteria.
## Workflow
- - A skill that instructs a subagent fan-out or background dispatch carries my authorization for `Agent`. Run it as written. Degrade to inline only when `Agent` is absent, and say so.
+ - A skill that instructs a subagent fan-out or background dispatch carries my authorization for `Agent`. Run it as written. When `Agent` is absent, run it inline and say so.
- Prefer `analyst` over `general-purpose` for read-only spawns. Pass `model: haiku` for pure lookup.
- - Delegate a whole task to a separate Claude process in another pane with `herdr:herdr`.
- - When debugging Claude Code itself (harness, classifier, hooks, plugins, startup), launch the session under observation with `DEBUG_SDK=1 claude`, which writes `~/.claude/debug/<session-id>.txt`. Claude Code reads `DEBUG_SDK` only from its launch environment, so `settings.json` `env` can't set it. `claude --debug=<categories>` is the flag form and the only way to filter categories. Read the log afterwards, or query its `debug_events` rows through `observability:session`.
- - Run scripted cross-model or GPT review through `github:copilot`. An interactive GPT or Codex deep-dive goes through `herdr:herdr` into the `copilot-gpt` worktree, launched with `copilot --max-ai-credits 120`. "Consult fable" means the same second opinion from a Fable session.
- - Use the `agent-browser` skill when a task needs a real browser. `WebFetch` is fine for static pages.
- - Finish a branch with `/ship`. Use `pull-request:create` to open a PR directly, or an empty body if it's unavailable. Open PRs ready for review, draft only for speculative changes.
- - Root every `find` at a directory that can hold the target. Use `fd -HI <pattern> <root>` when the root must stay broad.
+ - When debugging Claude Code itself (harness, classifier, hooks, plugins, startup), launch the observed session with `DEBUG_SDK=1 claude`, which writes `~/.claude/debug/<session-id>.txt`. Set it in the launch environment, since Claude Code ignores it in `settings.json` `env`.
+ - For an interactive GPT or Codex deep-dive, launch `copilot --max-ai-credits 120` through `herdr:herdr` in the `copilot-gpt` worktree. "Consult fable" means the same second opinion from a Fable session.
+ - Open a PR with `pull-request:create`, or with an empty body when it's unavailable. Open PRs ready for review. Use draft only for speculative changes.
- Send build output to `/dev/null`. Store temporary files in `tmp/`.
- - Never disable the sandbox for file writes. Bypass only after a sandboxed run of that command failed.
+ - Never disable the sandbox for file writes.
## Planning
Investigate in auto mode until the approach is settled, then enter plan mode to write it down. When I ask for a plan and something is still open, tell me what you're resolving and resolve it first.
## Decisions
- Ask a simple decision (a confirmation, an approval, a multiple-choice pick) with `AskUserQuestion`. It reaches me on Moshi and Remote Control. Use Plannotator when the decision lives inside a document I should read and mark up, such as a proposal, an analysis, or a draft with questions mixed in. Once I answer in chat while a gate is open, stop opening gates for the rest of the session. For a Plannotator decision, write `tmp/<topic>.md` with one `:::question` block per decision, `- [ ]` choices, and a `Recommended:` line. The `plannotator` skill has the syntax. Open it with `plannotator annotate <file> --gate --json`, using `run_in_background` and a `7200000` timeout, then end the turn. Use the `plannotator` tool instead when one is loaded. Plan approval stays with the `ExitPlanMode` hook.
+ Ask a simple decision (a confirmation, an approval, a multiple-choice pick) with `AskUserQuestion`, because it reaches my phone. When the decision lives inside a document I should read and mark up, write `tmp/<topic>.md` with one question block per decision and a recommendation, open it with Plannotator as the `plannotator` skill describes, and end the turn. Once I answer in chat while a gate is open, stop opening gates for the rest of the session.
## Check-ins
- Schedule `⏰` plan check-ins in Things with `things:url add` and `when=<yyyy-mm-dd>`, tagged `claude-code`. Work-tracked check-ins go there too, linking their Linear issue. Notes carry what to check, the plan path, the repo, and a launch URL:
+ Schedule a plan check-in as a Things to-do titled with `⏰`, dated for the check-in, and tagged `claude-code`. For work tracked in Linear, link the issue. The notes carry what to check, the plan path, the repo, and a launch URL:
```
claude-cli://open?q=<url-encoded prompt>&cwd=<absolute main repo path>
```
- The URL prefills a new session without submitting it. Point `cwd` at the main repo, never a worktree.
+ Point `cwd` at the main repo, never a worktree.
## Git
- Never `git push` to the default branch unless I say so.
- - Work on a topic branch with a short hyphenated name.
+ - Name topic branches short and hyphenated.
- Write commit messages with one `-m` per paragraph, or a heredoc for complex ones. Wrap bodies at ~72 columns.
- - Update a checkout with `git merge --ff-only <ref>`. Revert your own edits with `git restore <path>`. A tree-wide reset, checkout, or clean needs me to name it.
+ - Update a checkout with `git merge --ff-only <ref>`. Revert your own edits with `git restore <path>`. Run a tree-wide reset, checkout, or clean only when I name it.
## Worktrees
- Any change meant to become its own PR starts in a worktree created with `worktrunk:wt-switch-create`, even where a harness suggests `EnterWorktree`. Stay put when already on a topic branch in one. Work handed to a sibling agent gets its worktree through `herdr:herdr`. Use `worktrunk:worktrunk` for every other `wt` task. Disposable verification worktrees may use `git worktree add tmp/<name>`.
+ Start any change meant to become its own PR in a worktree created with `worktrunk:wt-switch-create`, even where the harness suggests `EnterWorktree`. When already on a topic branch in a worktree, stay there. Work handed to a sibling agent gets its worktree through `herdr:herdr`.
Inside an isolated worktree, write files with `Write` or `Edit` and keep each Bash command a single plain command. The isolation guard refuses heredocs, `$(...)`, loops, and a `cd` into the main checkout before git.
## Claude Configuration
- My Claude Code setup lives in [`bendrucker/claude`](https://github.com/bendrucker/claude), worked on at `~/src/bendrucker/claude`. The `~/.claude` symlinks point into a deployed clone at `~/.claude-repo` that `claude-upgrade` syncs from `main`. A merged change is not live until that sync runs, and editing through the symlinks writes into that clone instead of a branch. Project-scoped `.claude/` directories stay with their repo.
-
- ## Tools
-
- @tools.md
+ My Claude Code setup lives in [`bendrucker/claude`](https://github.com/bendrucker/claude). Edit it at `~/src/bendrucker/claude`. The `~/.claude` symlinks point into `~/.claude-repo`, a deployed clone that `claude-sync` updates from `main`, so an edit through the symlinks lands outside any branch. A merged change goes live only after that sync runs. Project-scoped `.claude/` directories stay with their repo.
## Dotfiles
- Machine setup lives in [`bendrucker/dotfiles`](https://github.com/bendrucker/dotfiles) at `~/.dotfiles`, in topic directories. The Claude repo installs nothing. Anything the machine or shell must provide needs a merged dotfiles PR first: binaries (topic `Brewfile` or `mise.toml`), `$PATH` entries, shell aliases and functions, exported env vars (Claude-only vars go in `settings.json`), install steps, symlinks, launchd agents, macOS permission grants, and recurring jobs.
-
- Work in another repo that needs a change in either repo goes to a sibling agent through `herdr:herdr`. Report the PR back to me, or tell me the change where herdr is unavailable.
-
- ## Stacked PRs
-
- Load `github:stack` before any `gh stack` command (`gitlab:merge-request` on GitLab). Pick one layout per stack and don't mix them:
+ Machine setup lives in [`bendrucker/dotfiles`](https://github.com/bendrucker/dotfiles) at `~/.dotfiles`. Anything the machine or shell must provide needs a merged dotfiles PR first, because the Claude repo installs nothing. That covers binaries, `$PATH` entries, aliases and functions, exported env vars, install steps, symlinks, launchd agents, macOS permission grants, and recurring jobs. Claude-only env vars go in `settings.json` instead.
- - Worktree per branch, for layers worked in parallel. `wt sync` rebases in dependency order (`--fetch`, `--push`, `--prune`, `--dry-run`). Publish with `gh stack link` after `wt sync --push`.
- - One worktree for the whole stack, for active reshaping. `gh stack sync` owns it end to end.
+ When work in another repo needs a change in either repo, hand it to a sibling agent through `herdr:herdr` and report the PR back to me. Where herdr is unavailable, tell me the change.
- After `gh stack merge`, pull the surviving layers.
+ Reach secrets through 1Password `op run`. SSH keys live in Secretive, which refuses to sign while the Mac is locked.
## Personal Details
- - My username is `@bendrucker`. Refer to actions by that user as "you."
+ My username is `@bendrucker`. Refer to actions by that user as "you."