dotfiles/agents/AGENTS.md
mwiegand 4a155afb63
refactor(agents): trim global AGENTS.md to invariants, fix cognee command forms
- cognee section 67 → 30 lines: triggers and routing only, how-to lives in
  the plugin skill; recall/remember written as `cognee` subcommands
- memory writes explicitly exempt from project write-confirmation rules;
  precedence for projects with their own findings convention (file first,
  cognee note with link)
- removed-hook JSON dropped (in git history), one-targeted-retry rule added
- ccc gotchas moved to the ccc skill, md paragraph translated and shortened
- AGENTS-claude.md: onyx block no longer duplicates the plugin description

Co-Authored-By: Claude Mythos 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJuj5BdSLtn9R4xHduxYWY
2026-10-09 21:26:28 +02:00

150 lines
9.3 KiB
Markdown

# 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/<slug>.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.
## Team memory (cognee)
cognee is a real memory, not an archive: unlike `MEMORY.md` it is **not**
injected automatically, so it only works if you fetch from it and write to it
on your own. Command forms, flags, dataset sharing and failure modes are in the
`cognee` plugin skill; this section only says *when*.
- **Read: `cognee recall <question>` before the first tool call** when the task
touches infrastructure, a server, a service, a ticket or a tool we run
ourselves; when an error "smells familiar"; when choosing between options
where a decision may already exist; or when the task will plausibly take more
than a handful of tool calls. Plain `recall` reads every readable dataset,
team included. Treat what comes back like a colleague's note: useful, possibly
outdated; verify a named file, flag or host still exists before acting on it.
- **Write: `cognee remember` as the insight appears**, not at session end.
Announce it in one line, never ask first: memory writes are exempt from any
project rule that asks to confirm write actions (those rules target external
systems: Jira, chat, Confluence, hosts). Moments: a bug fixed whose cause was
not visible in the code; a decision with a rejected alternative (save the
*why*); a measurement that contradicts an assumption; a correction, yours or
mine; a tool or API that behaves differently than its docs claim.
- **Routing:** `--team` for everything concerning team IT (Seibert IT-Infra,
ISAC/bw, monitoring, INFRA board, shared services, team processes), plain
`remember` for my preferences and personal context. Never secrets,
credentials or customer-personal data; nothing the repo already records;
nothing that only matters inside this conversation.
- **Projects with their own findings convention** (task folders,
`erkenntnisse/`, `decisions/`): write the file there first, then the cognee
note with the conclusion and a link to the file. The file is the detailed
record; cognee is what the next session or a colleague in another repo finds.
- **Hygiene:** on recurring topics `recall` first and extend the existing note
instead of adding a second one. Write notes that answer a question: concrete
numbers, the error message verbatim, the fix, and the external references
(Confluence, Jira, TeamVault, Google Chat thread URLs
`https://chat.google.com/room/<SPACE-ID>/<THREAD-ID>`). No size limit, so
write self-contained.
## Sandbox
- **Always run commands sandboxed first.** Only use `dangerouslyDisableSandbox: true` after a sandbox-related failure — never preemptively. One targeted retry with the identified cause fixed is fine; retrying in a loop is not.
- **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.
- **Commands that must run unsandboxed belong in `sandbox.excludedCommands`** (e.g. `git *`, the pinned
`bin/srv`-style wrappers), not behind the flag: the exclusion is the owner's decision, the flag is the
model's. Without a hook, the flag is only a convention: an unsandboxed command that matches an allow
rule (`Bash(git *)`, `Bash(pytest *)` …) runs without a prompt in default mode, and auto mode may wave it
through as well. (The former PreToolUse hook that forced a prompt on the flag was removed 2026-10-04;
its JSON is in this file's git history.)
## 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
- **Sourcebot MCP for org repos without a local checkout.** The
`mcp__sourcebot__*` tools (instance sourcebot.it.seibert.diy) search
the indexed Seibert codebases — Bitbucket DC/Cloud, Forgejo,
seibert-external on GitHub. Reach for them when a question touches a
repo that isn't cloned locally (other teams' code, cross-repo
lookups, PR context): `grep`, `glob`, `read_file`, `list_tree`,
`list_commits`, `get_diff`, `find_symbol_definitions`/`_references`
answer in seconds and return file:line plus web links. A local
checkout stays first choice when it exists. Never call
`ask_codebase` on your own — it spawns a nested server-side agent
(minutes per call, shared vLLM); use it only when explicitly asked.
- **`ccc` for semantic code search.** Repos containing a `.cocoindex_code/`
directory are indexed by `ccc`. Reach for it on conceptual questions ("where
is X used / what handles Z"), where a keyword grep would miss indirect usage:
`ccc search '<concept>'` from the project root. It is embeddings only: exact
strings (UUIDs, ticket IDs, error messages) stay with `grep`/`rg`. Details and
gotchas in the `ccc` skill.
- **`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; treat like `grep` for permission purposes.
- **`md` for long Markdown files instead of `head`/`grep -n '^#'`.**
`md outline <file>` prints the heading tree with line numbers and size per
section; decide from that, then `md section <file> "<heading>"` for exactly
that subtree (`--range` yields `offset limit` for the Read tool, `--depth 0`
cuts subsections). It knows code fences and frontmatter, so a `# comment` in
a bash block is not a heading. Below ~500 lines just `Read` the file.