I've been using Claude Code CLI as my daily driver for about six months. At first I was using it like a slightly smarter autocomplete — ask it to write a function, paste in an error. Fine. Useful. But not life-changing.
The thing that actually changed my workflow was slash commands.
If you haven't used them, slash commands in Claude Code are custom .md files that live in .claude/commands/ in your project (or ~/.claude/commands/ for global ones). When you type /command-name in a Claude Code session, it executes the prompt inside that file — with full access to your project context, file system, and shell.
This post walks through exactly how to set them up and shares 15 production-ready commands you can start using today. No vague descriptions — every command includes the full .md file content you can copy directly.
How slash commands work
Create a file at .claude/commands/your-command-name.md. The contents of that file are the prompt Claude runs when you type /your-command-name.
That's it. The command has full context of your current project — it can read files, run shell commands, see your git history, check your package.json. Everything Claude Code normally has access to.
For a global command available in every project, put it in ~/.claude/commands/ instead.
.claude/
commands/
git-commit.md → /git-commit
test-write.md → /test-write
debug-trace.md → /debug-trace
The power comes from writing prompts that are actually specific and instructional — not "help me write a commit message" but "run git diff --cached, analyze the staged changes, and output a conventional commit message following this exact format."
Let's get into the commands.
Git commands
/git-commit
File: .claude/commands/git-commit.md
Look at the currently staged changes with `git diff --cached`. Write a conventional commit message following the format: `type(scope): description`. Types: feat, fix, docs, style, refactor, test, chore. Keep the subject line under 72 characters. Add a body if the change is non-obvious. Output only the commit message, nothing else.
Why this matters: You stop writing commit messages. Claude reads your actual staged diff and writes a message that's specific to what you changed. No more "fix stuff" commits.
/git-pr
File: .claude/commands/git-pr.md
Run `git log main..HEAD --oneline` and `git diff main...HEAD --stat`. Write a pull request description with: ## Summary (3 bullet points max), ## Changes (file-level breakdown), ## Test Plan (checklist of what to verify), ## Screenshots (placeholder if UI changed). Be specific — name the actual files and functions changed.
Why this matters: PR descriptions that actually describe the change. Takes 30 seconds instead of 10 minutes. The diff context makes it specific to your actual code, not a generic template.
/git-changelog
File: .claude/commands/git-changelog.md
Run `git describe --tags --abbrev=0` to find the last tag, then `git log {last_tag}..HEAD --oneline --no-merges`. Group commits into: ### Added, ### Changed, ### Fixed, ### Removed. Format as Keep a Changelog (keepachangelog.com). Use today's date. Output only the changelog entry block.
/git-blame-why
File: .claude/commands/git-blame-why.md
For the file and line number I specify, run `git log -L {line},{line}:{file} --follow -p` to get the full history of that line. Explain: what the line does now, what it used to do, why it changed, and whether the current implementation looks intentional or like a temporary fix. Reference the actual commit messages.
Why this matters: Every codebase has lines that look wrong. Before you "fix" something, this command tells you if it was changed for a reason — and what that reason was. Saved me from breaking a business rule I didn't know existed.
/git-branch-cleanup
File: .claude/commands/git-branch-cleanup.md
Run `git branch --merged main` to find merged branches, and `git for-each-ref --sort=committerdate refs/heads/ --format='%(refname:short) %(committerdate:relative)'` to find stale ones. List branches safe to delete grouped by: Merged into main, Stale (no commits in 30+ days). Output a single `git branch -d branch1 branch2...` command to delete all of them at once.
Testing commands
/test-write
File: .claude/commands/test-write.md
Write tests for the file/function I point you to. Use the testing framework already in the project (check package.json). Cover: happy path, edge cases, error conditions, boundary values. Write tests that would have caught real bugs — not just tests that confirm the obvious. Use descriptive test names that read like sentences. Don't mock things that don't need mocking.
Why this matters: The key instruction is "tests that would have caught real bugs." Without that, AI-generated tests tend to be tautological — they just verify the happy path you already wrote.
/test-gaps
File: .claude/commands/test-gaps.md
Review the test files in this project. For each tested module, identify: untested functions, untested branches (if/else paths not covered), missing error case tests, missing edge cases. Output a prioritized list — most critical gaps first. For the top 3 gaps, write the actual missing test.
/test-mock
File: .claude/commands/test-mock.md
Look at the types, interfaces, and data shapes in the file I specify. Generate factory functions that create realistic test data for each type. Use faker-style realistic values (real-looking names, emails, IDs) not placeholder strings like "test" or "foo". Export each factory. Make them composable — partial overrides should work.
Why this matters: Most test factories are garbage — name: "test", email: "test@test.com". This one explicitly instructs realistic values and composable overrides, which is how you build test data you can actually trust.
/test-mutation
File: .claude/commands/test-mutation.md
Analyze the function and its tests. Mentally apply these mutations and check if the tests would catch them: flip a comparison operator (> to >=), return null instead of the expected value, skip a conditional branch, change an off-by-one. List each mutation that the current tests would miss. This tells us exactly where the test suite has blind spots.
Why this matters: Coverage metrics lie. 90% coverage can still miss the mutation that flips > to >= in your billing logic. This command tells you where your tests have blind spots without needing a mutation testing tool installed.
Debugging commands
/debug-trace
File: .claude/commands/debug-trace.md
I'll paste a stack trace. Find the root cause — not the symptom. Trace back through the call stack to the point where something first went wrong, not just where it crashed. Explain: what the error means, why it happened (the real reason, not "null is not an object"), what state the application was in when it occurred, and the one-line fix. If you need to see specific files, ask for them.
Why this matters: The instruction "not the symptom" is load-bearing. Without it, you get an explanation of the error message you already read. With it, you get the reason three stack frames up that caused the null in the first place.
/debug-memory
File: .claude/commands/debug-memory.md
Review the code I point to for memory leaks. Common patterns to find: event listeners not removed on unmount, intervals/timeouts not cleared, large objects held in closures, React state that grows unbounded, subscriptions not unsubscribed. For each leak found: show where memory is allocated, show where it should be freed but isn't, write the fix.
/debug-race
File: .claude/commands/debug-race.md
Review the async code I point to for race conditions. Find: multiple async operations that assume sequential execution, shared state modified by concurrent operations, missing await keywords that cause out-of-order execution, fetch requests that could return in wrong order. For each race condition: describe the scenario where it causes a bug, write the fix (AbortController, mutex, state machines, etc.).
Code review commands
/review-security
File: .claude/commands/review-security.md
Review the code I point to for security vulnerabilities. Check for: SQL injection, XSS (cross-site scripting), CSRF, insecure direct object references, sensitive data in logs or responses, missing authentication/authorization checks, hardcoded secrets or API keys, dependency vulnerabilities (check package.json versions). For each issue found: severity (Critical/High/Medium/Low), description, and the exact fix. Don't report false positives — only flag real issues.
Why this matters: "Don't report false positives" is intentional. Most security audit prompts without that instruction produce a wall of low-confidence warnings that train you to ignore the output. This one asks Claude to be conservative and specific.
/review-performance
File: .claude/commands/review-performance.md
Review the code I point to for performance issues. Find: O(n²) or worse algorithms that could be O(n), unnecessary re-computation inside loops, missing memoization, database queries in loops (N+1), large payloads being transferred when smaller ones would work, synchronous operations blocking the event loop. For each issue: current complexity, better approach, estimated improvement.
/review-accessibility
File: .claude/commands/review-accessibility.md
Review the component/HTML I point to for accessibility issues. Check: missing alt text on images, form inputs without labels, buttons without accessible text, color contrast (flag anything that might fail), keyboard navigation (can you tab through everything?), missing ARIA attributes where needed, focus management, screen reader experience. Output a prioritized list with WCAG criterion references. Include the fix for each.
How I organize these in my projects
I keep a global set in ~/.claude/commands/ — the git, debugging, and review commands that apply to any project. Then each project has its own .claude/commands/ with project-specific things: a /seed-db command that knows the specific schema, a /deploy-staging command with the actual deployment steps for that project.
The separation matters. Global commands should be generic enough to work anywhere. Project commands can be as specific as you want — reference actual file paths, actual test commands, actual service names.
What to do when a command gives mediocre output
Slash commands are prompts. If the output isn't what you want, edit the .md file. The most common improvement: add more specificity about the output format, or add a constraint that prevents the common failure mode.
For /test-write, I added "Write tests that would have caught real bugs" after getting several tests that just verified the function returns something. For /review-security, I added "Don't report false positives" after getting a wall of theoretical warnings.
Treat the commands as living documents. The first version is a starting point.
The full set
This article covers 15 commands across git, testing, debugging, and review. If you want all 75 across those categories plus refactoring, documentation, database, deployment, security, and performance — along with 10 CLAUDE.md templates and 8 hooks configurations — I packaged everything into the Claude Code Power User Kit ($29). Drop-in files, organized by category, ready to use the same day.
But honestly, the 15 commands above will already change how you use Claude Code. Start there.
Quick reference
| Command | When to use it |
|---|---|
/git-commit |
Before every commit — let Claude read the diff |
/git-pr |
Branch is ready for review |
/git-blame-why |
Before "fixing" code that looks wrong |
/test-write |
New function with no tests |
/test-gaps |
Pre-release audit |
/test-mutation |
Want to know where tests are weak |
/debug-trace |
Have a stack trace to diagnose |
/debug-memory |
Suspected memory leak |
/debug-race |
Async code with intermittent failures |
/review-security |
Pre-deploy security check |
/review-performance |
Noticing slowness, want a targeted audit |
/review-accessibility |
Before shipping any UI changes |
The pattern across all of these: specific instructions produce specific output. The more precisely you tell Claude what to look for and what format to use, the more consistently useful the result.
If you're already using Claude Code and haven't tried custom slash commands, this is the lever worth pulling.













