Strategist · Designer · Operator

Launch
with Ben



Claude Code

Claude Code Commands: The Decision Rule From 42 in Use

One markdown file, one description line, a name that becomes the command. The rule for building one, and which of my 42 actually earned their keep.


ls ~/.claude/commands/*.md | wc -l returns 42. Every one of those files is markdown with a slash in front of its name. I wrote every one of them, one repeated instruction at a time, and a few of them I’d forgotten existed until I ran that count to write this post.

That’s the honest state of a Claude Code command setup after real use: not a tidy library, a pile with a handful of load-bearing pieces and a long tail nobody touches. Here’s what a command actually is, the rule I use before writing a new one, and which of mine earned the space they take up.

What a command actually is

Strip the ceremony and a command is one file. Open ~/.claude/commands/retro.md, one of the 42, and the whole configuration at the top is three lines:

---
description: Reflect on project learnings - 2 pain points and 1 win with concrete lessons
---

No name: field, no allowed-tools: list, no version number. A description, then markdown. The filename does the rest: retro.md becomes /retro. That one-line description is also what Claude reads to decide, on its own, whether this file is the right match for whatever you just asked, the same way it weighs it against the other 41.

The bodies vary a lot. think.md runs 114 lines. task.md runs 608. Length isn’t a signal of quality here. It’s how much judgment the job needs written down.

When a repeated instruction earns a file

SignalWrite the commandLeave it as a prompt
You’ve typed the same multi-step instruction more than onceYes
It’s a single ask, done onceYes, just type it
Getting a step wrong or out of order costs something real: a bad deploy, a skipped checkYes
You’d only ever open the file to remember what it saysYes, it isn’t earning its keep

That last row is the one I skip past too easily. A command that exists but never gets invoked isn’t neutral. It’s a file that has to be found, read, and kept current, for zero benefit over just typing the thing.

Named by a dispatched subagent, last 30 days

Of the 42 files in ~/.claude/commands/, only task, think, brainstorm, sop, and triage show up by name when I run ~/.claude/scripts/agent-skill-report.sh. The other 37 never appear in that window, because the script only sees commands Claude reaches for inside a subagent it dispatches through the Task tool.

That undercounts real use badly, and the same script says so. Its main-session column shows 46.8% of 267 sessions in the same 30 days called at least one command directly, which is how most of these 42 actually get used: typed by me, not discovered by an agent working on its own.

Where a command stops being enough

A command asks. Claude reads /retro’s steps and decides how to follow them. It can skip a step, reorder one, or decide the file doesn’t apply this turn.

A hook forces. A PreToolUse or Stop hook is a script the harness runs whether Claude agrees or not, and its exit code can block the action outright.

A command raises the odds Claude does the thing correctly. It doesn’t guarantee it, the same gap that let real CLAUDE.md rules ship straight past a tight command setup until a hard gate caught what they missed. A command file sitting in the folder is not proof it’s being followed, the same trap as trusting a doc you never verified against the running system.

None of this is the skill-or-script call either. That’s a different axis with its own rule: automate judgment with a command, automate a fixed sequence with a script, gate the result with enforcement.

A real one, trimmed to the parts that matter

Here’s ~/.claude/commands/retro.md, cut down from 137 lines to the frontmatter and the structure that carries it. This is what you’d copy to start your own:

---
description: Reflect on project learnings - 2 pain points and 1 win with concrete lessons
---

# /retro

Surface the top 3 learnings from this project or session. Two things that
hurt, one thing that went well. Each with a specific lesson.

## Output Format

Return exactly 3 items in this format:

## 1. [Short title of pain point]

[2-4 sentences: what happened. Name files, errors, tools, decisions.]

**Lesson:** [One sentence that applies beyond this project]

## Rules

- No generic answers. "Communication is key" is useless.
  "Blade interprets @context as a directive, breaking JSON-LD" is useful.
- Reference specifics: the file, the error message, the decision point.
- Keep it short. This is a reference, not a postmortem essay.

Receipt Trimmed from my 137-line retro.md, one of the 42 commands I actually use.

Save that in ~/.claude/commands/ under any filename, and it’s a working command. No build step, no registration process. Just a file in a folder and a description that tells Claude when to reach for it.

The rule

Write a command when you’ve repeated the same multi-step instruction more than once, and getting a step wrong would cost something real. Keep the frontmatter to a single description: line unless you genuinely need more. Don’t expect it to hold under pressure the way a hook does, and don’t confuse “should this be a file” with “should this be a skill or a script,” that’s a separate call.

Forty-two files, five of them visible to a script that watches what gets dispatched, all of them cheaper to write than to keep forever. Write the ones that earn it. Delete the ones that don’t, once you’re honest about which is which.


Related:

Sources

  • Claude Code docs, Extend Claude with skills: how a description in frontmatter is matched against intent, and when a skill’s body loads
  • Claude Code docs, Hooks: the enforcement layer a command cannot provide on its own
Ben Peetermans

Ben Peetermans

I build MVPs and run ad campaigns with AI, and I write these notes from real projects. Twenty years shipping for the web. If you want someone who works with these tools every day to build yours, that is what I do.