Repository navigation
Convert the user-wide slash commands to skills - #167
Draft
mattmenefee wants to merge 8 commits into
Draft
mattmenefee wants to merge 8 commits into
mattmenefee wants to merge 8 commits into
Conversation
9 of 10 tasks
mattmenefee
force-pushed
the
convert-commands-to-skills
branch
2 times, most recently
from
October 24, 2026 16:12
d3055f2 to
5b10b3e
Compare
7 tasks done
mattmenefee
force-pushed
the
convert-commands-to-skills
branch
5 times, most recently
from
October 24, 2026 18:23
fd09448 to
d6ccab2
Compare
mattmenefee
marked this pull request as draft
October 24, 2026 18:25
mattmenefee
force-pushed
the
convert-commands-to-skills
branch
6 times, most recently
from
October 24, 2026 21:24
a7f617f to
dfc2347
Compare
The five user-wide commands lived as bare Markdown files in
~/.claude/commands with no frontmatter, so Claude Code took each one's
listing description from its first heading ("Commit Changes") and had
no way to say when the model should reach for it or keep a command
user-only.
Move each into its own skill directory as SKILL.md, keeping its history
with the rename, and give it a name, a description of when to use it
and, where it takes arguments, an argument hint. /update-deps creates a
branch and opens a pull request, so it carries disable-model-invocation
like /ship-it; /commit, /handoff and /doc-review stay model-invocable
because the user-wide CLAUDE.md asks the model to run them itself.
~/.claude/skills is a real directory that also holds skills installed
from elsewhere, so .homesick_subdir now lists .claude/skills and
homesick links each skill directory into it rather than the directory
as a whole. /doc-review's rule extract now reads its own SKILL.md, and
the references in /ship-it, scrub.sh, .markdownlintignore and the
user-wide CLAUDE.md follow the new paths and name skills alongside
commands.
After pulling, run `yes n | homesick link dotfiles` to link the skills;
the old ~/.claude/commands link is left dangling and can be removed.
As a skill, /doc-review was one 129 KB SKILL.md. The documentation expert agent listed it under `skills:`, which injects a skill's full content into the agent at startup, so every reviewer, the collator and each recording agent began with the whole orchestrator procedure loaded. After compaction Claude Code keeps only the first 5,000 tokens of an invoked skill, so most of the procedure was also lost to the session running it. SKILL.md now holds the orchestrator's procedure and names the files beside it through the skill directory: reviewer-rules.md (the review criteria and report rules, for every reviewer and the collator), review-file.md (the review file rules, for the collator), posting.md (the scrub, the Sensitive Information withholding and the comment format) and a worked walkthrough example. Prompts give agents those paths in place of a sed extract of SKILL.md, and documentation-expert no longer preloads the skill. The scrub and the gated post become scripts: scrub-lib.sh holds the one pattern set, scrub.sh runs the scan the user sees and post.sh runs every gate itself before posting, taking the status and stats lines as arguments, so no post step exists to copy without its checks. header.sh resolves each document's branch and commit. test-post.sh replays the end-to-end cases the blocks were tested against, with a stub gh. The prose in the moved files is refilled to 100 columns, and ship-it's scrub.sh header points at the new home of the patterns it derives from.
/handoff and /resume-handoff each carried a long state-gathering block for the agent to copy, fill in and run, and /resume-handoff's check that a rewrite lost nothing worked around the skill argument substitution with awk's `$(0)` and a variable set by its loop. Each skill now runs scripts from its own directory instead: gather-state.sh prints the base and where it came from, the tip, the working tree, the pull request and the commit ranges under labeled headings, taking the branch, the Updated date and the files the handoff names as arguments where /resume-handoff needs them, and check-loss.sh compares a rewritten handoff with its backup and keeps the backup when a heading or a preserved line went missing. The reasoning about bases, tips and silenced gh calls stays in the skills, and their prose is refilled to 100 columns.
/update-deps was one 85 KB SKILL.md, most of it steps that apply only in some repositories: Terraform, JavaScript, the RuboCop and haml-lint bumps. Loaded whole on every run, it also lost everything past its first 5,000 tokens whenever the session compacted. SKILL.md keeps the overview, the steps every run takes and a short stub at each moved step that says when to read its file from the skill directory: javascript.md, terraform.md (Steps 5 and 6 and the notes on why their commands are shaped as they are), pins.md, linters.md, version-locked.md and changelogs.md. Each moved section keeps its text, its headings rise one level to sit under the file's title, and every in-page link now names the file that holds its target. The prose is refilled to 100 columns.
Several paragraphs in these files broke well short of the 100-column limit, some after edits on this branch shortened a line. Refill them to the full width. Only line breaks change: each file's words and its rendered Markdown are identical before and after.
The secrets term for a credential in a table row allowed only spaces between the cell's pipe and the key name, so a row whose key cell was written `SECRET_KEY_BASE` in backticks or **Password** in bold passed both /doc-review's scrub and /ship-it's as clean, while the same value as an assignment was blocked. A review in another project found the gap with synthetic rows. Both copies of the term now accept backticks and asterisks around the name. A header row naming a key also blocks, as it did before, and is cleared like any other line. A key cell of several words still passes, since matching words would also catch summary rows whose description mentions a credential; posting.md now says so and leaves that form to the reading pass. Both test suites gain the backticked and bold cases, which fail against the old term, and test-post.sh checks that a summary row naming a credential still posts.
/doc-review's SKILL.md and review-file.md run scripts/header.sh by path, but the script was tracked as 100644, so that call failed with "permission denied" (exit 126) and only `bash header.sh` worked. Mark it 100755 like the skill's other runnable scripts. scrub-lib.sh stays 100644 because it is sourced, not run.
mattmenefee
force-pushed
the
convert-commands-to-skills
branch
from
October 24, 2026 21:45
dfc2347 to
50574c0
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
commit,doc-review,handoff,resume-handoff,update-deps) fromhome/.claude/commands/<name>.mdtohome/.claude/skills/<name>/SKILL.mdwithgit mv, and give each frontmatter:name, adescriptionthat says when to use it and anargument-hintwhere it takes argumentsupdate-depscarriesdisable-model-invocation: true, like/ship-it, because it opens a pull request;commit,handoffanddoc-reviewstay model-invocable because the user-wide CLAUDE.md asks the model to run them.homesick_subdirlists.claude/skills, so homesick links each skill directory into the existing~/.claude/skillsrather than replacing itSKILL.mdstays near the 500-line guideline: after compaction Claude Code keeps only the first 5,000 tokens of an invoked skill, and supporting files load only when readdoc-review:SKILL.mdis the orchestrator's procedure;reviewer-rules.md,review-file.md,posting.mdand a worked walkthrough example sit beside it, and agent prompts name those files instead of a sed extractupdate-deps:SKILL.mdkeeps the overview, the steps every run takes and a stub per moved step; Terraform, JavaScript, tool and image pins, the linter bumps, version-locked packages and changelog quirks each have a file, with every in-page link pointing at the file that holds its targetdoc-reviewinto thedocumentation-expertagent. Askills:entry injects the skill's full content into every dispatch, which as a skill would have meant the whole orchestrator procedure in each reviewer${CLAUDE_SKILL_DIR}:doc-review/scripts:scrub-lib.sh(the one pattern set),scrub.sh(the scan the user sees),post.sh(runs every gate itself, then posts; status and stats lines are arguments),header.shandtest-post.shhandoff/scripts/gather-state.sh,resume-handoff/scripts/gather-state.shandresume-handoff/scripts/check-loss.sh/ship-it, itsscrub.sh,.markdownlintignoreand the user-wide CLAUDE.md follow the new paths, and two CLAUDE.md rules about command files now name skill files too/doc-review's scrub and/ship-it's. Both copies now accept backticks and asterisks there; a key cell of several words still passes, andposting.mdnow says soAfter pulling, run
yes n | homesick link dotfilesto link the skills. The old~/.claude/commandslink is left dangling and can be removed by hand.Test plan
yes n | homesick link dotfileslinked all five skill directories into~/.claude/skillsand left the existing entries in placecommit,doc-review,handoffandresume-handoffappeared in the skill listing with their descriptions, andupdate-depsdid notclaude plugin validate home/.claude/skillspassesdoc-review/scripts/test-post.sh28/28: the 16 end-to-end cases the inline blocks were tested against (all matched the blocks' results before extraction), the key-cell cases, and argument andscrub.shchecks; disabling the withhold gate in a copy fails exactly the two withhold cases, and the old key-cell term fails exactly the two new key-cell casestest-scrub.sh90/90; its two new key-cell cases fail against the old termcheck-loss.shkeeps the backup when a preserved line or a heading is dropped and removes it otherwise; bothgather-state.shscripts run against this branch--external-sources.markdown-lint.ymlclean on every changed Markdown filed1d0f27)/doc-reviewrun reads the rule files and posts throughpost.sh;/update-depsstill starts when typed