Skip to content

Instantly share code, notes, and snippets.

@codeninja
Last active June 8, 2026 15:53
Show Gist options
  • Select an option

  • Save codeninja/0d261024d8a991fb12e21b2c853c18b7 to your computer and use it in GitHub Desktop.

Select an option

Save codeninja/0d261024d8a991fb12e21b2c853c18b7 to your computer and use it in GitHub Desktop.
CLAUDE.md
# CLAUDE.md
This is a decision guide, not a runbook — how to make choices when writing code here. Commands, setup, architecture, and deployment live in the README. On *running* something, the README wins; on *deciding* something, this file wins.
Full conventions: https://gist.github.com/codeninja/75f94d35911df96b3c931a8f76242332
---
## Philosophy
You are an LLM assisting the Principal Engineer — nothing is impossible or too much work. In systems we don't control, understand them and make the minimal change. In greenfield, set a strong foundation from the start.
Aim for clean, modular, reusable code. Patterns and abstractions are tools, not goals — avoid needless complexity; favor patterns that automate away boilerplate and human error.
- **Explicit > implicit** — no magic, no hidden state, no author-only conventions.
- **Composition > inheritance** — small composable pieces over deep hierarchies.
- **Constraints > convention** — enforce correctness with types, schemas, and tooling, not docs.
- **Deterministic behavior** — same inputs, same outputs; minimize runtime surprises.
- **Tests are non-negotiable** — untested is broken. Every feature ships with tests; target ≥85% coverage.
- **Code is the source of truth** — behavior lives in code and tests, never in comments or docs that drift.
---
## Comments: self-documenting code, strictly enforced
Code explains itself through naming, structure, and types. Comments are a last resort:
1. **Max 2 lines.** Need more? Restructure — extract a named function, rename a variable, split the logic.
2. **Only non-obvious interactions**, and only about the code directly beneath. "What" comments are forbidden.
3. **No business logic.** Rules and policies belong in code and tests, where they're executable. A comment of a rule lies silently when the rule changes.
4. **No third-party knowledge.** Don't document how a library/API behaves — it drifts and misleads. If an external quirk forces odd code, link the upstream issue instead of paraphrasing.
5. **Don't touch existing comments** when editing nearby code unless the code they describe changed. Never rewrite for tone or style.
6. **Delete comments that restate the code** when you're already modifying it — the only comment edit needing no justification.
Docstrings on public APIs are fine: signature, purpose, contract only. No essays, tutorials, or change history.
**The test:** before writing a comment, ask "can renaming or restructuring make this unnecessary?" If yes, do that.
---
## Writing code
- **Small, focused modules with clear ownership.** No god-objects, no grab-bag `utils`.
- **Business logic lives in services/domain code**, not route handlers, UI components, or scripts.
- **Dependency injection over global state.** Config is explicit and validated at startup.
- **Import from actual modules**, not `__init__.py` re-exports.
- **Prefer auto-discovery over manual registration** (e.g., routers) — fewer parallel-agent merge conflicts.
- **Match the surrounding code** — its idioms, naming, and density. Don't introduce a new pattern when one exists.
- **No speculative flexibility.** Build what the task needs; abstractions earn their place with ≥2 real consumers.
- **Handle errors where they can be acted on.** Don't swallow exceptions or catch-log-continue without reason.
### Default technology choices
When starting new and the codebase doesn't dictate otherwise:
- Python: `uv` (never pip/poetry), `ruff` lint+format, `pytest`, Pydantic, SQLAlchemy 2.x async.
- JS/TS: `bun` (never npm/yarn/pnpm), Vite, Vitest + Testing Library + MSW.
- Python UI defaults to NiceGUI; React only for standalone/public SPAs.
- UUID primary keys, `created_at`/`updated_at` on every model, JSONB for flexible data.
- Conventional Commits. Merge commits, not squash.
---
## Git workflow: worktrees, commits, PRs
All work happens in git worktrees — never directly on `main` or the working checkout.
- **Base every worktree off `main`** (or the branch the user designates).
- **One worktree per unit of work; a fresh worktree per background subagent.** Subagents never share a worktree or write to the primary checkout.
- **Worktrees live in `.claude/worktrees/`** — ensure it's gitignored before the first one.
```bash
git worktree add .claude/worktrees/<branch-slug> -b feat/<short-slug> main
```
- **Commit early and atomically; open a PR before work is done.** Worktrees get cleaned up, so uncommitted/unpushed work is lost. Sequence: implement → test → commit → push → PR. Never stop at "implement."
- **All tests pass before commit.** Never commit a red suite, never "fix" it by deleting or skipping tests.
- Remove a worktree only after its branch is pushed and the PR exists.
---
## Testing
- New behavior gets new tests in the same PR — not "later."
- Test behavior and contracts, not implementation details.
- Cover unhappy paths: empty input, missing auth, invalid data, error propagation.
- A failing test is information. Report it; never weaken the assertion to make it pass.
---
## Anti-patterns
| ❌ Never | ✅ Instead |
|---|---|
| pip / poetry / npm / yarn / pnpm | `uv` (Python), `bun` (JS) |
| Comments explaining business rules | Encode rules in code and tests |
| Comment blocks longer than 2 lines | Restructure until the comment is unnecessary |
| Rewriting comments while editing nearby code | Leave them unless their code changed |
| Manual registration of auto-discoverable things | Auto-discovery |
| Fat `__init__.py` re-exports | Import from the actual module |
| Working on main / sharing worktrees | Fresh worktree per task and per subagent |
| Uncommitted work left in a worktree | Commit, push, and PR before stopping |
| Real secrets in examples or commits | Placeholders in `.env.example`; `.env` gitignored |
| "I'll add tests later" | Tests in the same PR |
| Magical abstractions, implicit global state | Explicit, traceable, injected dependencies |
| Squash merges | Merge commits |
---
## When in doubt
1. Read the surrounding code first — the existing pattern beats this document's defaults.
2. Raise a question to the user when the implementation path is ambiguous.
3. If a decision isn't covered here and isn't derivable from the code, ask — don't enshrine a guess.
---
## Debugging
Don't guess at fixes. Deconstruct the root cause through verifiable observations and tests; understand the "why" before attempting a fix.
When tempted to patch or work around a problem, resist. Explore solutions in a fan-out worktree with experiments — test multiple approaches without risking the main codebase. Once you find a fix that addresses the root cause, merge or reimplement it with confidence.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment