# Claude Code — a personal setup for a repo of your own

Companion artifact to the project "Set up Claude Code as a coding agent
you can trust" at https://lyceumagents.com/projects/claude-code-guide/

Four files and a checklist. Reference documentation:
https://code.claude.com/docs — the mechanisms below are the ones its
"Extend Claude Code" and "How Claude remembers your project" pages
describe, applied to one repository.

---

## 1. CLAUDE.md — the rules file (target: under 200 lines)

```markdown
# <project name>

<One paragraph: what this is, the stack, the rule that must never break.>

## Workflow — every change
1. Read `docs/` for the subsystem you touch BEFORE designing.
2. `<build command>` AFTER building. It is the test suite.
3. Update the doc for the subsystem in the SAME commit.
4. `<verify command>` LAST, before commit.

## Quick facts (always true, or it does not belong here)
- `<build command>` is the test suite.
- Adding <content type> = one file at `<path>`. Nothing else.
- Never edit `.env`; ask me to.
- Never <the one thing that breaks everything>.

See @README.md for the layout.
```

Rules of thumb from the docs, verbatim in spirit:
- Add to it when the agent gets a convention wrong twice, or when you
  type the same correction you typed last session.
- If a line is a multi-step procedure, or matters for one part of the
  codebase only, it belongs in a skill or a `.claude/rules/` file with a
  `paths:` list, not here.
- `/init` writes a first draft; `/context` shows what actually loaded;
  `/memory` opens the files.

## 2. .claude/rules/<topic>.md — a path-scoped rule

```markdown
---
paths:
  - "src/api/**/*.ts"
---

# API handlers

- Every handler validates its input with the shared schema first.
- Errors return the standard shape in `src/api/errors.ts`; never a bare string.
```

Loads only when the agent opens a matching file.

## 3. .claude/skills/<name>/SKILL.md — a procedure with a trigger

```markdown
---
name: verify-change
description: Verify a code change for real AFTER editing — run the build,
  the tests, and the app, and report the exit codes and failing test
  names. Use before claiming any change works, and before every commit.
---

# Verify a change

1. Run `<build command>`; record the exit code.
2. Run `<test command>`; record every failing test by name.
3. Start the app and exercise the changed path; record what you saw.
4. Report all three as facts. "It looks correct" is not one of them.
```

- Name = a verb. Description = the trigger, in the words a task would
  contain.
- A skill with side effects (deploy, release) adds
  `disable-model-invocation: true` so only you can start it.

## 4. The guard hook — enforcement, not a request

`.claude/settings.json`:

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "bash .claude/hooks/guard-env.sh" }
        ]
      }
    ]
  }
}
```

`.claude/hooks/guard-env.sh` (needs `jq`):

```bash
#!/usr/bin/env bash
# Refuse edits to .env files. Exit 2 blocks the tool call and hands the
# message on stderr back to the agent.
path=$(jq -r '.tool_input.file_path // empty')
case "$path" in
  *.env|*/.env|*.env.*) echo "blocked: $path is edited by hand only" >&2; exit 2 ;;
esac
exit 0
```

Test it: ask the agent to "add my API key to .env" and read the refusal.

## 5. .mcp.json — a server the agent discovers at start

```json
{
  "mcpServers": {
    "catalog": { "type": "sse", "url": "http://localhost:8931/sse" }
  }
}
```

`/mcp` shows connection status. Pair a server with a skill that documents
how to use it well: the server is the connection, the skill is the
knowledge.

## 6. The definition-of-done checklist — add this block to CLAUDE.md

```markdown
## definition of done — every change, no exceptions
1. the verification command named below, run for real, not read
2. the doc for the subsystem touched now describes the new behavior
3. a decisions-log entry, only if this change chose between real alternatives
4. all three land in the same commit
```

A rule stated once in CLAUDE.md is still a request. Chain it as skills so a
long session cannot skip it: one that syncs the docs, one that reviews the
diff, both invoked "immediately before commit." See section 3 for the
skill shape; section 8 below has both templates filled in.

## 7. Three maintenance skills — run on a schedule, not a task's words

A feature skill fires when a task's wording matches its description. These
three fire on a date instead, because nobody asks for them until something
has already gone wrong. Claude Code keeps no clock, so the trigger lives
outside it — a recurring calendar block, a release checklist — and what you
do at that moment is invoke the skill by name.

```markdown
---
name: security-final-check
description: Run a security review as the FINAL step before committing
  any change — after code is written, after docs are synced, immediately
  before commit. Covers injection surfaces, secrets, supply chain, and
  any place the repo trusts data it did not generate itself.
---

# Security Final Check

Review the full pending diff (`git diff` + `git status` for new files),
not what you remember changing.

1. Injection: anywhere untrusted text (a fetched page, an MCP tool
   result, a user upload) is rendered, executed, or interpolated into a
   command.
2. Secrets: keys, tokens, credentials — in code, in config, in a file
   about to be committed.
3. Supply chain: a new dependency, a version bump, a script that runs at
   install time.
4. Report a PASS/FAIL verdict, not a list of maybes.
```

```markdown
---
name: architecture-cleanup
description: Audit the codebase against its own dependency map for drift
  — dead code, stale docs, disagreeing conventions. Run on a schedule
  (monthly, or before a release), not from memory of what changed.
---

# Architecture Clean-up

1. Read the repo's own dependency map (an index doc, a README section,
   whatever names what depends on what).
2. Report, do not fix: a doc that claims a mechanism the code no longer
   has; a file nothing in the map imports; a convention two files
   disagree on.
3. Leave the judgment call to a human. The skill's job is surfacing the
   report on a date, not deciding what to do with it.
```

```markdown
---
name: docs-refresh
description: Sweep the WHOLE documentation tree for drift, not just the
  files a recent commit touched. Run on a schedule — drift accumulates
  fastest in the corners nobody has opened in months.
---

# Documentation Refresh

1. Walk every doc, not the diff.
2. For each: does this still describe the code as it runs today?
3. Fix what has drifted; log anything ambiguous for a human decision
   rather than guessing.
```

## 8. Capture a run as a skill — good or concerning, the same mechanism

A session's window empties the moment it ends. A run worth repeating and
a run worth never seeing again are both facts that disappear unless a
repository file carries them forward.

**The good case.** Name the skill for the action. Write the description
in the exact words you used when you noticed the run was good — the
routing match is against your own vocabulary, not a tidier paraphrase of
it. Put what the agent actually did, generalized one level, in the body.

**The concerning case.** Start with a skill whose body states the
constraint explicitly. If asking has not been enough — the same mistake
recurs after the skill exists — escalate to a hook (section 4 above): a
script that blocks the tool call outside the model, rather than a line
the agent can still choose to skip on a tired turn.

## 9. The first-week checklist

- [ ] `claude --version` prints; `claude` signs in; `/context` lists CLAUDE.md
- [ ] CLAUDE.md under 200 lines; everything procedural moved out
- [ ] the definition-of-done block (section 6) is in CLAUDE.md
- [ ] one feature skill, tested by asking in plain words and watching it fire
- [ ] one hook, tested by trying to make the agent break the rule
- [ ] one maintenance skill (section 7) run once, by hand, against the repo
- [ ] the verification command named in CLAUDE.md
- [ ] next feature: plan mode (Shift+Tab) → approve the plan → edit → run →
      "what did you run to verify that?" → commit code, docs, and any
      decisions-log entry together
- [ ] count the turns from plan to verified change; repeat the feature a
      week later and count again
