DEV Community

Cover image for Claude Code, Beyond the Prompt — Part 3: Turn Your Repeated Prompts Into Slash Commands (and Skills)
Gde
Gde

Posted on

Claude Code, Beyond the Prompt — Part 3: Turn Your Repeated Prompts Into Slash Commands (and Skills)

Part 3 of Claude Code, Beyond the Prompt — patterns from running a live automated trading system on Claude Code. Part 2: the session ritual.


If you did Part 2, you've now typed some version of "run the tests, check for type errors, then summarize what broke" about five times. And before that, the same review checklist. And before that, the same "look at this branch and tell me what's risky."

You're hand-copying your own workflows, session after session. It's the exact re-explanation tax we killed for project context in Part 1 — except now you're paying it for procedures.

Time to stop. This one's quick, and it's the last purely-zero-infrastructure win before we start building real tooling.

A slash command is just a markdown file

Here's the whole mechanism: drop a markdown file in .claude/commands/ in your project. The filename becomes the command. The file's contents become the prompt that runs when you type it.

Create .claude/commands/review.md:

Review the changes on the current branch for:
- correctness bugs and unhandled edge cases
- security issues (injection, leaked secrets, auth gaps)
- anything that doesn't match our conventions in CLAUDE.md

For each finding: file, line, one-sentence problem, suggested fix.
Rank by severity. If nothing's wrong, say so — don't invent findings.
Enter fullscreen mode Exit fullscreen mode

Now type /review. That entire checklist runs — the same way, every time, no matter how tired or rushed you are when you invoke it.

That's it. That's the feature.

Commands can take arguments

Make .claude/commands/fix-issue.md:

Look at GitHub issue #$ARGUMENTS. Reproduce it, find the root cause,
write a failing test, then fix it. Show me the diff before you commit.
Enter fullscreen mode Exit fullscreen mode

Type /fix-issue 412 and $ARGUMENTS becomes 412. One command, infinite issues. (You can also use $1, $2 for positional arguments when you need more than one.)

Why this is more than a shortcut

Saving keystrokes is the least interesting part. The real wins:

  • Consistency. The workflow runs the same way every time — not however you happened to phrase it at 2 a.m. The review.md above always checks security, even when you forgot security was a thing you cared about today.
  • Encoded judgment. A command isn't just steps; it's how you want the thing done. "Rank by severity. Don't invent findings." That's taste, captured once.
  • Shareability. .claude/commands/ is committed to your repo. Every teammate — and every future you — gets the same commands for free. Your workflows become part of the project, like tests.

And just like Part 1's memory files, there are two scopes: .claude/commands/ (project-level, committed, shared) and ~/.claude/commands/ (personal, available across all your projects). Same split, same logic.

Skills: when a command outgrows a single prompt

Sometimes a workflow is bigger than one prompt. It has multiple steps, decision points, its own reference material, maybe sub-files. Cramming that into a slash command turns it into an unreadable wall of text.

That's what skills are for. A skill is a folder with a description and a set of instructions that Claude loads on demand, when a task matches its description. The critical differences from a slash command:

  • Who triggers it. A slash command is something you invoke by name. A skill is something Claude reaches for when it recognizes the situation fits — though you can invoke skills explicitly too.
  • How it loads. Only the skill's short description sits in context all the time. The full body loads only when it's actually relevant. That progressive disclosure keeps your context lean even when you have dozens of skills installed — which matters more than you'd think for cost and speed (that's Part 7).

Rule of thumb: re-typing a prompt → slash command. A capability with its own docs, multi-step logic, or a decision tree that Claude should pull in automatically → skill.

How I scaled it

The workflows I run most often are commands and skills now, not things I re-explain.

The one that earns its keep daily is an audit pipeline: a single command that runs several review passes over my changed files in parallel, dedupes the findings into one ranked list, proposes fixes, and re-verifies them. Before I packaged it, I was manually orchestrating that every time — and doing it slightly differently, and forgetting a step, every time. Now it's one invocation, and it runs identically whether I'm sharp or fried.

The deeper payoff is subtle: a command carries the method, so a fresh session inherits it for free. Every hard lesson about how to do a complex task — the order, the guardrails, the "don't skip this check" — lives in the command instead of in my head. I stopped re-teaching Claude how we do things here.

The lesson: encode guardrails, not just steps

This is the part worth stealing.

A naive /deploy command runs some deploy commands. A good /deploy command refuses to deploy uncommitted code, verifies the deployed file's checksum matches what's actually in the repo, and confirms the service came back healthy before declaring success. It encodes the discipline — which means you physically can't skip the safety step at 2 a.m. when you're tired and "pretty sure it's fine."

Your commands are where your scar tissue lives. Every incident that taught you a rule should end with that rule baked into the command, so you never re-learn it the hard way. That's the difference between a shortcut and a system.

One more, from the same school of thought as the memory files: keep a command focused. One command, one job. A /do-everything command is as bad as a 500-line function — impossible to trust, impossible to reuse. Small, sharp, composable.

What you get out of it

No "full automation" fantasy — you're still driving. What you get is real and boring in the best way: complex tasks run consistently, your judgment is captured once instead of re-typed forever, and your best practices ride along in the repo where the whole team (and future you) inherits them automatically.

You stop paying the re-explanation tax on procedures, the same way Part 1 killed it for context.

Next

Commands and skills let Claude run your workflows — but those workflows still run through the tools Claude already has. The next leap is bigger: giving Claude entirely new tools of its own, with a narrow, audited interface onto your systems. Part 4: your first MCP server — how I turned raw SSH access into ~30 sandboxed, logged tools, and how you can build a tiny one this weekend.


Part 3 of a series on running real systems on Claude Code. The deeper agent-memory research lives in the open-source RE-call. Follow for Part 4.

Top comments (2)

Collapse
 
sarracin0 profile image
Raffaele Zarrelli

The distinction I would add: a slash command captures a repeatable procedure, it does not capture a one off judgment call. The deploy example is a good case, refusing to deploy uncommitted code is a rule you bake in once and reuse forever, but "we chose Postgres over Mongo because of X" is a decision, not a procedure, it happened once, and it needs a status (still true, or superseded once something changes) that a future skill invocation can check before re litigating it. That is the layer I ended up building in cowork-os on top of exactly this kind of file based setup: decision records with status sitting next to the command and memory files, so a skill loads not just how we do X but why we picked X over Y and whether that is still current.

Question on the skills part specifically: when a skill's own instructions turn out to be wrong (the guardrail was right at the time, then the underlying system changed), how do you catch that drift? At the next time the skill triggers and someone notices by hand, or is there a review step, something like the MEMORY.md staleness check from Part 1?

Collapse
 
gde03 profile image
Gde

Honestly: at next trigger, by hand. There's no automated review step — and the MEMORY.md staleness check doesn't transfer. That one works because it watches data, which has a heartbeat: last-write against expected cadence, alert on the gap. A skill's instructions emit nothing to watch. The git timestamp on the skill file tells you when the code changed, not when its assumptions went false. You can't timestamp "the system this guardrail was written for still exists."

The only real defense is upstream: write the guardrail to re-derive its truth each run instead of storing it. My /deploy checksums against git and health-probes the live service every time, so it can't drift — there's nothing stale to go stale. The ones that rot are the ones that hardcoded a fact — a host, a path — and those I only catch when the output looks wrong. Which is exactly the failure mode you're pointing at.