BUTLER.md
BUTLER.md is a file you drop at the root of any project. When AI Butler’s coding agent enters that directory, it reads BUTLER.md first and uses it as durable context for everything it does in that workspace.
Think of it as “instructions to your collaborator” — things every new contributor would need to know about this project that aren’t obvious from the code itself.
Where It Lives
Section titled “Where It Lives”AI Butler walks up from the current working directory looking for BUTLER.md (just like git looks for .git). The closest one wins.
/home/me/projects/├── BUTLER.md ← default for all projects└── webapp/ ├── BUTLER.md ← overrides the parent for this project └── src/ └── ...You can also have a user-level BUTLER.md at ~/.config/aibutler/BUTLER.md that applies to every project unless a project-level file overrides it.
What Goes In It
Section titled “What Goes In It”Anything the agent should know that isn’t obvious from reading the code:
- Test commands (
go test -race ./...,npm run test:watch) - Code style rules (
gofumpt,prettier, tab vs spaces) - Architectural conventions (“we use dependency injection”, “handlers go in
internal/http”) - Build and deploy commands
- Gotchas and foot-guns (“never use CGO”, “migrations are one-way”)
- Review expectations (“always add tests for new features”)
- Project-specific terminology
Example
Section titled “Example”This is the backend for Acme's customer portal. Go 1.26, PostgreSQL 16, Redis.
## Build & Test
- `make test` — runs unit tests with race detector- `make e2e` — runs end-to-end tests (requires Docker)- `make lint` — gofumpt + golangci-lint- Always run `make lint && make test` before committing
## Style
- `gofumpt -w .` is mandatory, not optional- Never use CGO — we compile with `CGO_ENABLED=0`- No `panic()` in request handlers — return errors up the stack- Use `slog` for logging, not `log` or `fmt.Println`
## Architecture
- HTTP handlers in `internal/http` — thin, delegate to services- Business logic in `internal/service` — no HTTP dependencies- Data access in `internal/repo` — hides PostgreSQL details- All three layers have interfaces; tests use fakes, not mocks
## Gotchas
- `migrations/` is append-only. Never edit an existing migration.- Redis is a cache, not state — never rely on it being present- The `users.email` column is case-insensitive at the DB level (citext)
## Before You Commit
- Tests pass with `-race`- New code has test coverage- No `TODO` comments without a ticket number- Commit message follows conventional commits (`feat:`, `fix:`, `docs:`, etc.)How the Agent Uses It
Section titled “How the Agent Uses It”When you ask the coding agent to do anything in a project with a BUTLER.md, it:
- Reads the file on session start
- Keeps it in the system prompt for the whole session
- Treats it as higher priority than general best-practice defaults
- References it when answering (“per BUTLER.md, I need to run
make lintfirst”)
If you update BUTLER.md mid-session, ask the agent to re-read it.
What Not to Put In It
Section titled “What Not to Put In It”- Secrets — BUTLER.md is meant to be committed to version control. Use the vault for secrets.
- One-off task descriptions — those belong in the chat message
- Huge API docs — reference them instead, don’t inline
- Things the code already says — don’t re-state function signatures or type definitions
BUTLER.md vs CLAUDE.md
Section titled “BUTLER.md vs CLAUDE.md”If you already have a CLAUDE.md (from using Claude Code), AI Butler reads it too — both files are loaded, BUTLER.md takes precedence where they overlap. This lets the same project work with multiple agents without duplicated effort.
Related
Section titled “Related”- Coding Agent — the agent that consumes BUTLER.md
- Hooks — for enforcement that BUTLER.md only suggests