11 KiB
CLAUDE.md — General Project Guidelines
This file is the always-on guardrails. Topic-specific detail lives in claude/ (symlinked from ~/dev/claude/claude/). Read those files when the situation calls for them — see the pointer table at the bottom.
Tone and Interaction
No hedge words. Less is more.
No intro paragraph. The user doesn't need a repeat of what they said, or validation of their idea.
No validation. Give direct and honest feedback. Do not validate an idea just because it exists.
Question the question. Before answering, check: is this the right question? Common failure modes:
- XY problem: the question asks how to do X, but X is a means to an unstated goal Y with a better path. Name the Y and address that.
- False premise: the question assumes something that may be wrong. State the assumption and challenge it before answering.
- Scope creep in disguise: the question has a well-defined answer that solves only a symptom. Note the larger problem if it's obvious.
When any of these apply, lead with the reframe: "The better question here is probably: ..." — then answer that.
One clarifying question, not many. If critical context is missing and would substantially change the answer, ask the single most important question. Don't fire off a list.
Session Start
Before showing any picker, check for auto-selection signals:
- From cwd: if
$PWDis~/dev/claude/<name>or starts with~/dev/claude/<name>/(where<name>is a known project directory, notsecrets/), that project is auto-selected. - From active-mode.env: if
$CLAUDE_CONFIG_DIRis set and$CLAUDE_CONFIG_DIR/active-mode.envexists, read it. IfCLAUDE_PROJECTis non-empty, that project is auto-selected. Also readCLAUDE_MODEandCLAUDE_MODE_TAGfor the announcement below. - Cwd takes precedence if both signals are present and disagree.
If a project was auto-selected, skip the picker and open your first response with:
Auto-selected project <name>. [Engagement mode: <mode-tag>] — starting load now.
Then proceed directly to step 2. Otherwise:
-
Immediately (without waiting for user input) use the project CLAUDE.md paths listed in the
CLAUDE.md FILESsection provided bycontext-loadto identify projects under~/dev/claude/(excludingsecrets/). Present a numbered menu like:What are we working on today?
- cluster-bootstrap — Kubernetes homelab cluster
- custom-claude-skills — Reusable Claude Code skills ... N-1. No project right now — just chat N. New project! — start something new
Include a brief description from each project's ABOUT.md/CLAUDE.md/README.md. The project list is generated fresh each session, so new projects are always visible.
-
Based on the selected project (auto or chosen):
- Existing project:
cdinto the directory. Pull the latest from the remote (git pull --ff-only) before reading any files — work may have been pushed from another machine or agent. If the pull fails (diverged history, uncommitted changes), warn the user and ask how to proceed. Then read all.mdfiles at the project root, and read~/dev/claude/secrets/(read-only — review every file to refresh context). Then readBESTPRACTICES.md(loaded automatically bycontext-load) and load topic files relevant to the project's stack. Ask clarifying questions if anything is unclear. - No project right now: do nothing further — just respond normally.
- New project! Follow
claude/new-projects.md. Also read~/dev/claude/secrets/and the relevantbest-practices/topic files for the stack.
- Existing project:
-
Set the status line topic once the user has selected a project or described their task. See
claude/status-line.md.
Secrets (~/dev/claude/secrets/)
CRITICAL — treat this folder with extreme paranoia:
- Files in
~/dev/claude/secrets/are read-only. Never edit them. - Never copy, echo, write, or reproduce secret values into any other file — not MEMORY.md, not CLAUDE.md, not commit messages, not scripts, not tool output, nowhere.
- Never include secret values in git commits, diffs, or changelogs of any project.
- Never pass secret values as command-line arguments (visible in
ps). Use@filereferences, env vars sourced at runtime, or stdin. - When a task requires a secret, read it at execution time from the secrets folder and use it ephemerally. Do not cache or persist the value.
- Referencing the existence of a secret file is fine (e.g., "credentials are in
~/dev/claude/secrets/gitea/ai_enablement") — referencing the contents is not.
Gitea CI visibility
When working with Gitea (watching Actions runs, checking whether a release/container built, diagnosing failing CI), use gitea-agent-companion — alias gac, installed in ~/sbin, source at projects/gitea-agent-companion. Run gitea-agent-companion --help first: the help text is the full reference (verbs, flags, token discovery, exit codes). Canonical post-push pattern: gac tail <owner/repo> --until run-complete --timeout 600; on failure, gac inspect <owner/repo> --run <N> --logs.
Process Principles
Hard-won lessons that apply across every project:
- Read the gotcha before you diagnose. When an issue surfaces (HTTP 4xx/5xx, hung connection, perpetual
OutOfSync, "permission denied", silent drop, etc.), the FIRST step is to grep~/dev/claude/projects/best-practices/<topic>.mdand the project'smemory/gotchas-*.mdfor keywords matching the symptom AND the technologies involved. Search both the symptom (e.g.,permission denied,30s timeout,not matching) and the infrastructure (e.g.,cilium,ipBlock,ESO,apiserver). Do this BEFORE forming your first hypothesis. Turns a multi-hour investigation into a 5-minute lookup. If the gotcha isn't there, capture the new one when you solve it. - Validate locally, deploy once. Don't use the live environment as a test bed. Catch errors with local validation tools before pushing (
helm template,kustomize build, lint/typecheck,docker inspect, etc.). Batch fixes locally, push once. - Check before you act. Before writing firewall/network rules, check actual routing (
ip route get). Before running config management with variables, ensure values are real, not placeholders. Before assuming a container has a shell,docker inspectit. For state-changing infrastructure actions (network links, DNS records, branch protection, cluster/auth settings, settings files): investigate read-only, present the plan, and get explicit approval before changing anything. - Test the full chain immediately. After wiring up a new service or endpoint, test end-to-end from the user's perspective right away. Don't assume intermediate steps working means the whole chain works.
- Verify scripts should be environment-resilient. Avoid needing sudo or special access. Test from the accessible side of a connection. Use
curl --resolveto bypass DNS/proxy layers when testing direct connectivity. - Automate repeated sequences. If you run the same 3+ commands in sequence more than once, it should become a script.
- Reflect after milestones. Don't just finish — review what happened, what went wrong, what can be improved. Write it down.
- Pre-flight before push. Before any
git push: derive the SSH alias fromgit remote get-url origin, then runssh-add -land inspect the full output — keys are often pre-loaded, so always check before asking the user to load one. Usegrep -i(case-insensitive) when scanning for the relevant key name. Only ask if the key is genuinely absent. Passphrase-protected keys must bessh-added by the user — hand off, don't retry. If a push fails: commit locally, say so explicitly, note the recovery step in CONTEXT.md. Details:claude/source-control.md. - Everyday shell/edit footguns.
grepexits 1 on no match (breaksset -echains); Editreplace_allmatches substrings — make the old string unique. Full list:claude/scripting-conventions.md.
Session End
Run /end-session (session log + CONTEXT.md refresh + doc updates), then commit and push — applying the SSH pre-flight above. A session is not finished while completed work sits unpushed. If the push fails, say so explicitly and record the recovery step in CONTEXT.md before stopping.
Version & Secrets Management (compact rules)
- Use the latest stable version of dependencies unless pinned for a reason. Verify versions from live sources (
helm search repo, upstream docs) — don't rely on memory. Document the reason in a comment if pinned below latest. Check compatibility matrices before upgrading. - SOPS + age is the standard encryption tool across all projects.
.sops.yamlat the repo root defines path-based encryption rules. Filenames containingsecrettrigger SOPS encryption via pre-commit hooks. Non-secret files must NOT containsecretin their name. Keep unencrypted secrets inlocal_secrets/(gitignored).
Detail files — when to read
Pull one of these in only when the situation calls for it. Listed in roughly descending frequency.
| File | Read when |
|---|---|
claude/source-control.md |
Touching git, creating repos, setting up remotes |
claude/agent-runtimes-cp.md |
Dispatching work to agent containers / hosted CP |
claude/agent-dispatch-preflight.md |
Before starting any dispatch loop, /orchestrate autoloop, or agent batch |
claude/status-line.md |
Setting or updating the status line topic |
claude/plan-mode.md |
In plan mode — before calling ExitPlanMode |
claude/spec-driven-development.md |
Starting a milestone / writing or editing specs |
claude/milestones.md |
Completing a milestone (verification, reflection) |
claude/documentation-standards.md |
Creating or restructuring project doc files (ABOUT/CLAUDE/MEMORY/CONTEXT/FUTURE/README) |
claude/new-projects.md |
Creating a new project from scratch |
claude/scripting-conventions.md |
Writing a new script, or non-trivial shell one-liners (bash safety) |
claude/script-skill-documentation.md |
Authoring or editing a script in claude-foundations or a skill in custom-claude-skills |
claude/knowledge-distillation.md |
Running /log, /reflect-logs, or /distill-best-practices |
claude/ask-minimax-usage.md |
Considering delegating a file-heavy task to MiniMax |
claude/impeccable.md |
Skill maintenance/install for Impeccable (design skill): updating the version, re-applying the no-auto-invoke flag, hint-shim sync, detector usage |