2. Inside the files — commands, skills, guides
Sections
Reading settings
No voice for this language in this browser.
More voices
Code and English terms
Off: the page’s voice reads everything, with no pause between two voices.
No voice for this language in this browser.
More voices
More voices: Microsoft Edge has natural online voices, and Windows (Settings › Time & language › Speech), macOS and Android install others.
Code: code/slashforge/check.sh and scripts/installer-functions.mjs, which calls the installer’s own functions. The outputs are in expected/.
The installer exports the functions it is built from, and loading it doesn’t run it — its entry point is guarded by require.main === module, Node’s equivalent of a Main that only runs when the assembly is the entry assembly. So instead of describing what it does, this lesson calls it.
A path becomes a name
Section titled “A path becomes a name”# A file path under commands/ becomes the name you typeslashforge/setup.md /slashforge:setupslashforge/code.md /slashforge:codeslashforge/investigate.md /slashforge:investigateslashforge/review-pr.md /slashforge:review-prslashforge/brainstorm.md /slashforge:brainstormslashforge/plan.md /slashforge:planslashforge/debug.md /slashforge:debugslashforge/tdd.md /slashforge:tddslashforge/verify.md /slashforge:verifyslashforge/review-feedback.md /slashforge:review-feedbackslashforge/request-review.md /slashforge:request-reviewslashforge/worktree.md /slashforge:worktreeslashforge/parallel.md /slashforge:parallelThe installer’s commandName applies the rule Claude Code documents for how a skill gets its command name: for a file in a subdirectory of commands/, “subdirectory path relative to commands/ with each / replaced by :, then the file name without extension”. It is routing by folder, the way an ASP.NET area or a Java package turns a directory into a prefix. Nothing inside the file takes part. The prefix is also the whole collision strategy: a /code command of your own and /slashforge:code can live side by side.
The frontmatter has two readers
Section titled “The frontmatter has two readers”Each file starts with a block of frontmatter between --- lines. Here is code.md:
---name: /slashforge:codedescription: End-to-end development workflow — gather requirements, plan, confirm, branch, implement, verify, review, push, PR. Pass `-quick` for lean mode on small changes (skips brainstorming, minimal plan, inline self-review instead of the agent review). Uses SlashForge's own skills at each phase — no plugins required.---Two programs read this block, for different reasons. The installer reads it to refuse a broken template, and requires name and description. Claude Code reads it to configure the command — and for a file in commands/, its documentation says the file “supports the same frontmatter except name and paths”. The one field the installer insists on is one Claude Code doesn’t use for this kind of file. name: /slashforge:code is a label for humans and for the installer’s check; the command’s name comes from the path, as above. Rename the file and the command changes name; edit the name line and nothing happens.
The two readers don’t parse the same way either. Claude Code reads YAML. The installer reads line by line: every non-blank line between the fences must look like key: value, with a key made of letters, digits, _ and -. Calling parseFrontmatter on a few samples:
# What the frontmatter check refusesno opening fence: demo.md: missing opening '---' frontmatter fenceno closing fence: demo.md: missing closing '---' frontmatter fenceno description: demo.md: frontmatter missing required field 'description'a key with a space: demo.md: invalid frontmatter at line 3: "long description: d"a closing fence with a trailing space: demo.md: missing closing '---' frontmatter fencea folded YAML description: demo.md: invalid frontmatter at line 4: " two lines"valid: ok {"name":"/demo","description":"d"}The folded description is valid YAML, and Claude Code would read it as one line of text. The installer refuses it. Neither is wrong about its own job — the installer only has to accept the twenty-nine templates it ships, and they all use one-line values — but a check that is stricter than the runtime it guards is worth knowing about before you add a template of your own and wonder why a file Claude Code accepts won’t install.
Refused before anything is written
Section titled “Refused before anything is written”check.sh copies the package, deletes the description: line of one skill, and runs that copy’s installer into another empty home directory:
Template validation failed: ✗ slashforge/verify.md: frontmatter missing required field 'description'Error: Refusing to install with invalid templates.exit 1and then lists the files in that home directory: none. The install function validates all four lists before it creates a single folder, and a comment gives the reason: “a half-installed kit is worse than none”. It is the pattern of a batch validated in full before SaveChanges, rather than saved row by row until one fails.
{{INSTALL_PATH}}: absolute in one mode, relative in the other
Section titled “{{INSTALL_PATH}}: absolute in one mode, relative in the other”A command has to tell the model where the guides are. The templates write {{INSTALL_PATH}}, and the installer replaces it — together with {{KIT_VERSION}} and {{KIT_PACKAGE}} — when it writes the file. What it replaces it with depends on the mode:
# The two install modesglobal guides /home/ada/.claude/setup/slashforgeglobal commands /home/ada/.claude/commandsglobal {{INSTALL_PATH}} = /home/ada/.claude/setup/slashforgeproject guides /src/app/.claude/setup/slashforgeproject commands /src/app/.claude/commandsproject {{INSTALL_PATH}} = .claude/setup/slashforgeIn a global install the path is absolute, and always written with /, Windows included. In a project install it is relative to the repository. One line of code.md, as shipped and after each install:
# template- **The argument contains `-quick`** → **LEAN MODE.** Read `{{INSTALL_PATH}}/forge-workflow-quick.md` in full, in addition to the workflow files below, and apply its overrides on top of everything in this file. Tell the user: *"Lean mode — skipping brainstorming, minimal plan, inline self-review."*# global- **The argument contains `-quick`** → **LEAN MODE.** Read `~/.claude/setup/slashforge/forge-workflow-quick.md` in full, in addition to the workflow files below, and apply its overrides on top of everything in this file. Tell the user: *"Lean mode — skipping brainstorming, minimal plan, inline self-review."*# project- **The argument contains `-quick`** → **LEAN MODE.** Read `.claude/setup/slashforge/forge-workflow-quick.md` in full, in addition to the workflow files below, and apply its overrides on top of everything in this file. Tell the user: *"Lean mode — skipping brainstorming, minimal plan, inline self-review."*# placeholders left in the installed filesglobal 0project 0(check.sh writes the throwaway home as ~; the installed file contains the full absolute path.) That relative path is what makes a project install committable: an absolute path would contain the name of whoever ran the installer. It also means the model has to resolve the path from the repository’s root. Whether it still finds the guides when Claude Code is started in a subfolder is to verify: that depends on the model and on its working directory, not on the installer.
Comparing the two installs file by file shows exactly where the modes differ, with the number of changed lines:
2 ./commands/slashforge/brainstorm.md 3 ./commands/slashforge/code.md 2 ./commands/slashforge/investigate.md 2 ./commands/slashforge/plan.md 2 ./commands/slashforge/review-pr.md 18 ./commands/slashforge/setup.md 3 ./setup/slashforge/forge-workflow-investigation.md 2 ./setup/slashforge/forge-workflow-review-pr.md 2 ./setup/slashforge/meta.jsonEight files name a path, and meta.json records the mode and the time. The other twenty-three are identical. Until 4.4.1 the guides were copied rather than rendered, so a guide could not name another file by its path; the changelog records that fix, and the two guides above are the ones that needed it.
This table is also the proof of what lesson 1 read in the changelog: the dry run still says copy forge-workflow-review-pr.md, and a copied file could not differ between the two modes.
Short commands, long guides
Section titled “Short commands, long guides”The four entry points are small. Most of what they do is in the guides they send the model to read:
110 slashforge/setup.md 70 slashforge/code.md 165 forge-workflow.md 46 forge-workflow-agents.md 94 forge-workflow-quick.md 51 slashforge/investigate.md 154 forge-workflow-investigation.md 67 slashforge/review-pr.md 302 forge-workflow-review-pr.mdcode.md holds the mode selection and the entry question, then says:
## Workflow files
Read the following in full — together they are your complete workflow guide:
- {{INSTALL_PATH}}/forge-workflow.md- {{INSTALL_PATH}}/forge-workflow-agents.md
You MUST follow every phase in order. Do not skip phases. Do not combine phases.The changelog calls this shape a dispatcher plus a workflow file. review-pr.md was 301 lines until 4.4.1 moved its phases to forge-workflow-review-pr.md, and investigate.md 143 lines until 4.4.2 did the same, “so I3 existed twice, in two levels of detail, and the two could drift”. It is the same refactoring as moving logic out of a controller into a service: the entry point stays small enough to read at a glance, and each rule is written once.
There is a cost the table doesn’t show. A command file is loaded when you type it; a guide is loaded when the model decides to read it, as a tool call, and it counts against the conversation like any file it reads. /slashforge:code asks for 211 lines of guides before its first question.
Skills that are command files
Section titled “Skills that are command files”The nine skills are files of the same kind, in the same folder. verify.md begins:
---name: /slashforge:verifydescription: Evidence before claims. Use before stating that anything is done, fixed, passing, or ready — and before committing, opening a PR, or handing off. Requires running the verification command and reading its output first.---
<!--Adapted from the `verification-before-completion` skill in superpowers.Copyright (c) 2025 Jesse Vincent. Licensed under the MIT License.They are adapted from superpowers, and each carries the MIT notice in an HTML comment, because the files are installed far from the repository that holds the licence. Claude Code has two formats for this: a skill proper is a folder with a SKILL.md and room for supporting files, and a file in commands/ is “the older format” that “still works”. SlashForge uses the older one for all thirteen files, which is what lets one folder give them one prefix. The workflow doesn’t wait for the model to pick a skill: the guides name the one to use at each phase — slashforge:plan in Phase 2, slashforge:verify in Phase 6, and so on.
Key points
Section titled “Key points”- A file’s path under
commands/is its name; thenamefield of a command file is ignored by Claude Code and required by SlashForge’s installer. - The installer’s frontmatter check is a line parser, stricter than the YAML Claude Code reads: a folded
description: >is refused. - Every template is validated before the first file is written, so a broken package installs nothing.
{{INSTALL_PATH}}is absolute in a global install and relative in a project install; eight files use it, which is why they are the only ones that differ between the two modes.- The four commands are dispatchers of 51 to 110 lines; the workflow itself is in guides of up to 302 lines that the model reads on demand.
Exercises
Section titled “Exercises”- You rename the installed
commands/slashforge/verify.mdtocheck.mdand leave its frontmatter alone. What do you type now to run it, and what happens the next time you run the installer? - The installer checks four lists before writing. Suppose it validated each file just before writing it instead. What would the empty-
descriptionexperiment above leave in the home directory? - In
l02_global_vs_project,setup.mddiffers in 18 lines andcode.mdin 3. Without opening the files, what does that tell you about the two commands?
Solution
/slashforge:check: the name comes from the file’s path, and Claude Code ignoresnamein a command file, so the oldname: /slashforge:verifyline changes nothing. The next install writesverify.mdagain, because the installer works from its own list, not from what is on disk — and you then have two commands with the same content,/slashforge:checkand/slashforge:verify. The guides still send the model toslashforge:verify, so your renamed copy is the one nothing uses.- The files written before
verify.mdin the installer’s order: the sixteen guides, the two assets and the commands and skills before it in[...COMMAND_FILES, ...SKILL_FILES]—setup,code,investigate,review-pr,brainstorm,plan,debug,tdd— withoutmeta.json, which is written last: 26 files. A kit whose Phase 6 skill is missing, and thatstatuswould describe as “unknown (legacy install — no meta.json)”, since the guides folder exists butmeta.jsondoesn’t. - That
setup.mdnames the guides by path many more times: it is the command that sends the model to most of them — rules, skills, agents, commands, hooks, memory — one line each, whilecode.mdnames three. The line counts are a map of which command depends on which guides, drawn by adiff.