New agent commands and skills are being created all over the interwebs. Most of the daily emails I subscribe to have become a deluge of new agent workflows promising to supercharge my productivity.
Until recently, I hadn’t spent much time creating my own agent tools, so in a lot of ways I simply hadn’t grasped how powerful these additions would be to my workflow. I’d mostly leaned on the commands that ship with Claude Code and a handful of the extremely helpful skills from Matt Pocock’s skills repo.
If you try only one thing from that repo, make it /grill-with-docs. It runs a relentless interview that challenges your plan against your existing domain model before you write a line of code, sharpens your project’s terminology, and drafts docs like CONTEXT.md and ADRs inline as decisions get made. Pocock himself calls it possibly the coolest technique in the repo, and after using it I’m inclined to agree. Once I started writing and tweaking my own tools, everything clicked.
Here’s what I’ve picked up: what these tools actually are, how commands and skills differ, how to start extending them, and a real command I use to close out PR review comments.
An Agent Tool
An agent tool is a reusable capability you hand to your coding agent: a packaged bit of instruction (and sometimes actual code) that teaches it to do a specific job the way you want it done.
The core idea is simple. Instead of retyping the same multi-step prompt every time (“pull the open PR comments, group them by severity, read the affected files, and give me a plan”), you write it down once, drop it in a directory the agent watches, and from then on it’s just there.
The nice part is that these tools are plain Markdown files. That means they live in your repo right next to your code, they’re version-controlled, they get reviewed in pull requests, and they’re trivial to share with your team. A workflow that used to live in one person’s head (or their Apple Notes) becomes a checked-in artifact everyone benefits from. Claude Code ships with a set of these out of the box, and the community (repos like Matt Pocock’s) is full of more. The two you’ll build most often are commands and skills.
Skill vs. Command
The cleanest way to think about the difference is who decides to run the thing.
A command is something you invoke. You type /address-pr-comments (optionally with an argument) and the agent runs that playbook right now. It’s a parameterized prompt you trigger on demand.
A skill is something the agent invokes. You give it a name and a description of when it’s useful, and the model decides to reach for it when the task in front of it matches. You don’t call it by name; it gets pulled in automatically.
| Command-style | Skill-style | |
|---|---|---|
| Who triggers it | You, explicitly with /name |
The model, when the task matches its description |
| Frontmatter | A description, maybe allowed-tools |
Adds model invocation; can bundle files |
| Shape | A single Markdown prompt | A folder with a SKILL.md plus optional scripts |
| Reach for it when | You want a deliberate, on-demand ritual | You want the capability applied automatically |
One important wrinkle if you’re reading older tutorials: in recent versions of Claude Code, commands and skills have converged. A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both give you a /deploy you can run, and both are just Markdown with YAML frontmatter. The .claude/commands/ path still works, but .claude/skills/ is now the recommended home. In practice, a command is a skill with the extras turned off: a prompt body you trigger yourself. Turn on model invocation, or bundle a script alongside it, and the same file starts behaving like a full skill.
So “skill vs command” is less about two separate systems and more about how much you switch on. Start with a plain command when you want deliberate, on-demand control. Reach for a skill’s extra features when you want the capability to show up on its own, carry supporting files, or run with tighter tool permissions.
Extending Agent Tools
Once you’re past the built-ins, a few mechanics are what turn a “saved prompt” into something genuinely useful:
Scope what it can touch. Notice the frontmatter on the command below. It declares exactly which gh and git invocations are allowed via allowed-tools. That’s a guardrail: a tool meant to read PR data can’t wander off and force-push. It’s worth setting on anything that reaches into your shell.
Pass it arguments. $ARGUMENTS (and positional $1, $2) let one tool handle many cases, whether that’s a PR number today or the current branch’s PR tomorrow, without copy-pasting a new variant each time.
Bundle scripts and real context. This is the jump from prompt to small program. A skill can ship helper scripts in its directory and even inline the output of a shell command at load time, so the agent starts with current, grounded context instead of a static wall of text.
Compose small tools. Tools can hand off to other tools. The command below ends by pointing you at /commit. Small, single-purpose tools that chain into a larger flow beat one sprawling mega-command every time.
Start from someone else’s tool. Because these are all just Markdown, anything you install from a repo is yours to edit. Pull down a skill like Pocock’s /grill-with-docs, open the file, and reshape it to fit how your team actually works: swap in your own domain vocabulary, point it at your ADR folder, cut the questions that don’t apply, and add the ones that do. You aren’t locked into someone else’s opinion; you’re starting from a strong draft and making it yours. Reading a few well-written tools this way is also the fastest route to writing good ones from scratch.
The best first tool to write is the annoying thing you already do by hand. Capture it, check it in, and let it improve through PRs like any other code. Keep personal habits at the user level (~/.claude/) and shared team conventions at the project level so everyone gets them on clone.
Example Command
Here’s one of mine. Working through PR review comments is exactly the kind of repetitive, easy-to-fumble task worth encoding: fetch every comment (inline, conversation, and review-level), triage them by severity, ground the plan in the current code rather than a stale diff, and, crucially, confirm with me before it touches a single file.
--- description: Fetch open PR comments and create a prioritized plan to address them allowed-tools: Bash(gh pr view:*), Bash(gh pr diff:*), Bash(gh api:*), Bash(git branch:*), Bash(git remote:*) argument-hint: [PR number, or leave blank to use current branch's PR] --- # Address PR Comments ## Prerequisites check Before starting, verify the GitHub CLI is available and authenticated: ``` gh auth status ``` If not authenticated, stop and tell the user to run `gh auth login` first. --- ## Step 1: Identify the PR Determine which PR to work with: - If $ARGUMENTS is provided, use it as the PR number - Otherwise, detect the PR from the current branch: ``` gh pr view --json number,title,url,baseRefName,headRefName,state ``` If no PR is found for the current branch, stop and tell the user: "No open PR found for the current branch. Pass a PR number directly: `/address-pr-comments 42`" Capture the PR number, title, base branch, and URL. Show the user which PR you're working with. --- ## Step 2: Fetch the repo owner and name ``` gh repo view --json nameWithOwner --jq '.nameWithOwner' ``` Split into `{owner}` and `{repo}` for use in API calls below. --- ## Step 3: Fetch all review comments (inline, line-level) These are comments attached to specific lines in the diff: ``` gh api repos/{owner}/{repo}/pulls/{pr_number}/comments \ --jq '[.[] | {id, path, line, original_line, body, user: .user.login, diff_hunk}]' ``` --- ## Step 4: Fetch general PR conversation comments These are top-level comments on the PR, not tied to specific lines: ``` gh api repos/{owner}/{repo}/issues/{pr_number}/comments \ --jq '[.[] | {id, body, user: .user.login, created_at}]' ``` --- ## Step 5: Fetch review summaries Get the overall review states (APPROVED, CHANGES_REQUESTED, COMMENTED): ``` gh pr view {pr_number} --json reviews \ --jq '.reviews[] | {author: .author.login, state, body}' ``` --- ## Step 6: Fetch the PR diff for context ``` gh pr diff {pr_number} ``` Use this to understand the full context of what was changed and where comments land. --- ## Step 7: Read the relevant files For each inline comment, read the actual current file content around the referenced line: ``` Read the file at comment.path, focusing on ±20 lines around comment.line ``` This ensures the plan is grounded in the current state of the code, not just the diff snapshot. --- ## Step 8: Analyze all comments For each comment (inline and general): 1. Understand what the reviewer is asking for 2. Identify whether it is actionable, a question, or already resolved 3. Assess severity: blocker, meaningful improvement, or optional nit 4. Note the file and line if applicable Skip comments that are: - Compliments or acknowledgments ("looks good", "nice work") - Already marked as resolved - Questions that don't require a code change --- ## Step 9: Produce a structured remediation plan Present the plan clearly before touching any code: --- ### PR: {title} (#{pr_number}) {url} **Reviewers:** list all reviewers and their review state **Total actionable comments:** N --- ### 🔴 Must Fix > Blockers, bugs, security issues, or explicit "request changes" items - [ ] `{file}:{line}` — **{reviewer}**: {what they asked for} → {what you'll do} - [ ] ... --- ### 🟡 Should Fix > Code quality, logic improvements, missing edge cases, style guide violations - [ ] `{file}:{line}` — **{reviewer}**: {what they asked for} → {what you'll do} - [ ] ... --- ### 🟢 Consider > Optional suggestions, nitpicks, preferences — low priority - [ ] `{file}:{line}` — **{reviewer}**: {what they asked for} → {what you'll do} - [ ] ... --- ### ❓ Questions / Needs Clarification > Comments that need a human response before acting - `{file}:{line}` — **{reviewer}**: {the question} --- ## Step 10: Ask before acting After presenting the plan, ask: "Ready to start implementing. A few questions: 1. Should I address **Must Fix** items only, or **Must Fix + Should Fix**? 2. Should I commit after each item or batch all changes into one commit? 3. Any items above you want to skip or handle manually?" Wait for the user's response. Do not edit any files until confirmed. --- ## Step 11: Implement (after confirmation) Work through the confirmed items in order — Must Fix first, then Should Fix. For each item: 1. Make the change 2. Briefly confirm what was done: "`auth.py:42` — removed hardcoded timeout, now uses `settings.REQUEST_TIMEOUT`" After all changes: ``` git diff --stat ``` Show a summary of all files changed. --- ## Step 12: Suggest next steps After implementation, remind the user: "Changes are made but not committed. When you're ready: - Review the diff: `git diff` - Commit: `/commit` (or your preferred commit command) - Push and reply to reviewers on GitHub to close the loop"
Notice how much of the value is in the boring parts: the guardrails, the “ask before acting” gate, and the handoff to /commit at the end. None of it is clever on its own. It just encodes the careful version of a task I’d otherwise rush.
Wrapping Up
The real unlock here isn’t any single command. It’s the habit. Once you start noticing the workflows you repeat and spend ten minutes writing them down, your agent stops being a generic assistant and starts working the way you and your team actually work. Steal the command above, tweak it, and see what else in your day is begging to be turned into a tool.
Further Reading
Matt Pocock’s skills repo: the source of /grill-with-docs and a pile of other engineering skills worth stealing.
Claude Code documentation: the official reference for commands, skills, and the rest of the extension stack.