DEV Community

VincentChabran
VincentChabran

Posted on • Edited on

The Claude Code setup I install in every repo: slash commands, a review subagent, and hooks

Claude Code is powerful the moment you install it. But the thing that makes it feel like a real teammate isn't the model — it's the configuration you build up around it: custom slash commands, specialist subagents, and hooks that run at the right moments.

The problem is that a fresh install is a blank .claude/ folder. You get all that value only after you read the docs and write the config yourself.

So here's the config I now copy into every repo. Everything below is a plain file you can paste, read, and change. I'll show you real commands, a subagent, and a hook — with the actual code and why each part is there — so you can rebuild this yourself in an afternoon.

Unofficial, community-made. Not affiliated with or endorsed by Anthropic. "Claude" and "Claude Code" are trademarks of Anthropic. This is independent config for Claude Code, not a product of Anthropic.

Where this config lives

Two locations, and you can use both:

  • ~/.claude/ in your home directory — applies to every project you open.
  • .claude/ in a repo root — applies to that project, and you can commit it to share with your team.

When a project file and a global file collide, the project one wins. I keep general-purpose commands and subagents in ~/.claude/, and project-specific rules in the repo.

1. A slash command is just a markdown file

The file name is the command name: .claude/commands/review.md becomes /review. The body is the prompt Claude runs. Here's a full, useful one — a pre-commit code review:

---
description: "Review the current changes for bugs, risks and quality before you commit"
argument-hint: [optional path or focus]
allowed-tools: Bash(git status:*), Bash(git diff:*), Bash(git log:*)
---

## Context

- Changed files: !`git status --short`
- Full diff: !`git diff HEAD`

## Task

Act as a careful senior reviewer of the diff above (focus on "$ARGUMENTS" if provided).

Report findings grouped by severity — **Blocking**, **Should-fix**, **Nit** — and for
each give the `file:line`, what is wrong, and a concrete fix. Look specifically for:

- **Correctness**: off-by-one, null/undefined, wrong operators, missed edge cases.
- **Security**: injection, unsafe input handling, secrets committed, missing auth checks.
- **Concurrency & resources**: races, leaks, unclosed handles, missing timeouts.
- **Contracts**: API changes that break callers or aren't reflected in tests/docs.

If the diff is clean, say so plainly instead of inventing problems. End with a one-line
verdict: safe to commit, or not yet.
Enter fullscreen mode Exit fullscreen mode

Three things are doing the work here:

  • ! runs a shell command and injects its output into the prompt. !`git diff HEAD` means Claude reviews your actual current diff, not a description of it. This is the single most useful trick in the whole system.
  • allowed-tools pre-approves exactly those git commands, so /review doesn't stop to ask permission every time it reads the diff. (If Claude Code still prompts you all the time, I wrote a deep-dive on the permission model and how to fix it — including a trap that makes a command prompt on every run even when everything looks allowed.)
  • $ARGUMENTS is whatever you type after the command. /review the auth changes focuses the review; /review alone reviews everything.

Now /review gives you a consistent, senior-style pass over your changes every time, instead of a fuzzy "can you check this?"

2. Bake your repo's conventions into /commit

Same idea, pointed at commits. The trick here is feeding Claude your recent history so the new message matches the style you already use:

---
description: Create a well-formed git commit from the current changes
argument-hint: [optional message or intent]
allowed-tools: Bash(git status:*), Bash(git diff:*), Bash(git add:*), Bash(git commit:*), Bash(git log:*)
---

## Context

- Current status: !`git status --short`
- Staged diff: !`git diff --cached`
- Recent commits (match this style): !`git log --oneline -10`

## Task

Create one focused git commit for the changes above.

1. If nothing is staged, stage the files that clearly belong together — never unrelated
   files, build artifacts, or anything that looks like a secret.
2. Write a Conventional Commits message (`type(scope): summary`), imperative mood,
   ≤ 72 chars, matching the tone of the recent commits shown above.
3. Commit with `git commit`. Do **not** push. No co-author trailers or tool ads.

If the staged changes cover several unrelated concerns, say so and propose splitting them.
Enter fullscreen mode Exit fullscreen mode

Because !`git log --oneline -10` injects your last ten commits, Claude writes in your house style — not a generic chore: update files. And "do not push" keeps a human in the loop for the one step that leaves your machine.

3. Subagents: specialists with their own context window

A subagent is a markdown file in .claude/agents/ with a bit of frontmatter and a system prompt. Claude can hand a task to it automatically, or you can call it by name. The win: the subagent works in a separate context window, so a long review or audit doesn't clutter your main conversation.

Here's the code-reviewer I use:

---
name: code-reviewer
description: Expert code reviewer. Use PROACTIVELY right after writing or changing code,
  and before committing, to catch correctness, security and design issues.
tools: Read, Grep, Glob, Bash
model: inherit
---

You are a senior software engineer doing a focused, high-signal code review.
Your job is to catch what matters and say it plainly.

## What you look for, in priority order

1. **Correctness** — logic errors, off-by-one, null/undefined, unhandled error paths.
2. **Security** — untrusted input reaching queries/commands/filesystem, injection,
   missing auth, secrets committed.
3. **Contracts** — API changes that break callers or aren't reflected in tests/docs.
4. **Resource & concurrency** — leaks, races, missing timeouts.
5. **Design & readability** — duplication, dead code, unclear names. Lower priority.

## Rules

- Do not invent problems to seem thorough. If the code is solid, say so and stop.
- End with a one-line verdict: **safe to merge**, **safe after should-fixes**, or **not yet**.
Enter fullscreen mode Exit fullscreen mode

Two details matter:

  • The description is how Claude decides when to delegate. Writing it as "use PROACTIVELY right after writing code" is what makes the subagent trigger on its own. Vague descriptions never fire.
  • tools scopes what it can touch. A reviewer only needs to read and search (Read, Grep, Glob, Bash) — it shouldn't be editing your files. Omit tools entirely and it inherits everything.

After this is in place, Claude tends to call the reviewer itself after a change. You can always force it: "have the code-reviewer look at the auth module."

4. Hooks: automate what you'd otherwise forget

Hooks run your shell commands at defined moments in a session. They live in settings.json. The one I'd never work without formats every file the instant Claude edits it:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "f=$(jq -r '.tool_input.file_path // empty'); [ -z \"$f\" ] && exit 0; case \"$f\" in *.js|*.jsx|*.ts|*.tsx|*.json|*.css|*.scss|*.html|*.md|*.yml|*.yaml) command -v prettier >/dev/null 2>&1 && prettier --write \"$f\" >/dev/null 2>&1 ;; *.py) command -v black >/dev/null 2>&1 && black -q \"$f\" >/dev/null 2>&1 ;; *.go) command -v gofmt >/dev/null 2>&1 && gofmt -w \"$f\" >/dev/null 2>&1 ;; *.rs) command -v rustfmt >/dev/null 2>&1 && rustfmt \"$f\" >/dev/null 2>&1 ;; esac; exit 0"
          }
        ]
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

How to read that:

  • PostToolUse + matcher: "Edit|Write|MultiEdit" means "run after Claude edits or writes a file." The matcher is a regex on the tool name.
  • Claude Code sends the hook a JSON payload on stdin. Here jq pulls out .tool_input.file_path — the file that was just touched.
  • It picks a formatter by extension and no-ops silently if that formatter isn't installed, so it never breaks a session on a machine that doesn't have black.
  • Exit codes are the contract: 0 = fine, continue. 2 = block the action and hand your message back to Claude as the reason. (A PreToolUse hook that exits 2 on .env paths is a nice guard against Claude ever editing your secrets.)

jq is the only dependency (brew install jq / sudo apt install jq).

Install it in two minutes

Grab the files, drop them in, restart:

mkdir -p ~/.claude/commands ~/.claude/agents
cp commands/*.md ~/.claude/commands/
cp agents/*.md   ~/.claude/agents/
# then merge the hooks block into ~/.claude/settings.json
Enter fullscreen mode Exit fullscreen mode

Restart Claude Code, type /, and the commands are there. Run /agents to see the subagent, /hooks to confirm the hook loaded.

One habit that makes all of this better

Notice a theme in the prompts above: they're written to be honest. The review command is told not to invent problems. A companion /pr command writes "not yet tested" instead of pretending. That matters — the fastest way to lose trust in an AI teammate is catching it claim a test passed when it never ran. Bake that into your prompts and the output stays trustworthy.

Get the files

I put the four commands, the code-reviewer subagent, the auto-format hook, and a CLAUDE.md template in a free, MIT-licensed repo so you can copy them straight in:

Claude Code Starter Kit on GitHub (MIT — use it, change it, ship it)

If you end up wanting the full set — 12 commands, 6 subagents, 5 hooks, a git-aware status line, and a full CLAUDE.md template — there's a paid Power Pack that bundles it with a step-by-step guide. But the repo above is enough to get real value today.

Happy building.

Top comments (0)