6. Making it yours — rules, verification, a team install
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, whose output l06_verify_glob is checked by CI on Linux, Windows and macOS, and lab/run.sh for the one model run, e5b in the journal.
Your conventions go in three places
Section titled “Your conventions go in three places”Setup (lesson 3) writes a first version of each. After that they are yours to edit:
| File | Loaded | For |
|---|---|---|
CLAUDE.md |
every session | what the project is, and the commands: build, test, lint |
.claude/rules/*.md |
at session start, or only when a matching file is read if the rule has paths: |
conventions for one area of the code |
.claude/skills/<name>/SKILL.md |
when invoked, or when Claude judges it relevant | a recipe: “add an endpoint here” |
The middle row is the one to learn. A rule with paths: in its frontmatter costs nothing until Claude reads a file that matches, which is how a large repository keeps its instructions short. The .claude directory documentation adds the caveat that applies to all three: “Like CLAUDE.md, rules are guidance Claude reads, not configuration Claude Code enforces. For guaranteed behavior use hooks or permissions.”
The first row matters to SlashForge in particular. Phase 6 of /slashforge:code begins by checking that “lint, test, and build commands are defined in CLAUDE.md. If any are missing, ask the user for them before continuing.” That is your verification contract: whatever CLAUDE.md names is what the workflow runs before it claims success. /init wrote a Commands section in lesson 3; setup asks about them.
Kit files and your files
Section titled “Kit files and your files”Run setup again after a new SlashForge release, and it has to decide which files it may overwrite. forge-instructions.md makes every file it generates carry a marker, generated_by: slashforge@4.4.3 in the frontmatter, or an HTML comment on the first line of CLAUDE.md, and applies three cases on a re-run:
- the marker matches the current kit version: the file may be refreshed;
- the marker is from an older version: “Propose a refresh; ask the user before overwriting”;
- the marker is “missing or edited”: the file is “user-owned. Edit to fill gaps only; do not overwrite”.
It is the // <auto-generated> header of a .NET designer file, with the partial class as the escape hatch. Here the escape hatch is to edit the marker, or delete it, and the file becomes yours. The model is the one applying these rules on the re-run, so they are instructions, not a mechanism; the course didn’t re-run setup to test them.
Two rulebooks
Section titled “Two rulebooks”The kit gives the model two guides about skills, and they disagree.
forge-instructions.md |
forge-skills.md |
|
|---|---|---|
| Where a skill goes | .claude/skills/*.md |
“each skill is a directory containing a SKILL.md entrypoint, not a flat .md file” |
| How long it may be | “Every .md file — including this one — must stay under 200 lines”, among the “Golden Rules (always enforced)” |
“Keep SKILL.md under 500 lines” |
Claude Code sides with the second on the first row: its skills documentation lists every location as .claude/skills/<skill-name>/SKILL.md. A flat file in skills/ is not in that table. On the second row, both limits are the kit’s own; Claude Code’s documentation uses 200 lines as a target for CLAUDE.md.
A verify step that can’t see skills
Section titled “A verify step that can’t see skills”Setup ends with a verify step, in forge-instructions.md:
# No file exceeds 200 lineswc -l CLAUDE.md .claude/**/*.mdIn bash, ** only means “any depth” when the globstar option is on, and it is off by default. Without it, .claude/**/*.md is .claude/*/*.md: one folder deep. check.sh builds a repository the way forge-skills.md asks — one rule, one skill in its own folder, 300 lines long — and runs the command:
# the files, as find sees them6 .claude/rules/api.md300 .claude/skills/add-endpoint/SKILL.md1 CLAUDE.md# the files the verify step counts: wc -l CLAUDE.md .claude/**/*.md, in bash without globstar1 CLAUDE.md6 .claude/rules/api.mdThe skill is two folders deep, so the check never sees it, and a 300-line skill passes a 200-line rule. macOS’s /bin/bash 3.2 has no globstar at all. zsh is different: there **/ is recursive by default, so the same line works in a zsh shell — the check passes or fails depending on which shell runs it. A check that can’t fail on the case it exists for is worse than no check, because it gets reported as done. find CLAUDE.md .claude -name '*.md' | xargs wc -l sees every file.
A team install, and which copy runs
Section titled “A team install, and which copy runs”--project (lesson 1) writes the kit into the repository’s .claude/, with relative paths, so a team can commit it: everyone who clones gets /slashforge:code at the same version. Unless someone also installed SlashForge globally, in ~/.claude/.
Claude Code’s rule for two skills or commands with the same name is “Enterprise over personal, and personal over project.” The lab tested it with the smallest possible command, /lab:which, present twice: in the lab’s personal commands/lab/which.md, answering GLOBAL, and in the repository’s .claude/commands/lab/which.md, answering PROJECT. The hypothesis, written before the run from that sentence, was GLOBAL.
subtype: successturns: 1cost: 0.0896938 USD (as computed by Claude Code)RESULT: "GLOBAL"The personal copy runs. For a team, that means the committed version is the one that runs only for people who didn’t install the kit themselves: a teammate with an older global install runs their /slashforge:code, with their version’s gates and guides, without any warning. slashforge status and slashforge status --project report the two installs separately, so the check is cheap. Agree on one mode per team, and if it’s the project mode, uninstall the global one.
A note on cost from the same run: the first attempt, with a ceiling of 0.10 USD, was stopped with error_max_budget_usd at 0.103 USD — for an eight-token answer. The ceiling works under a subscription login, but it is checked after each call, so a run can end slightly above it; and with this model, a session costs about 0.09 USD before it does anything, mostly the prompt cache being written.
Key points
Section titled “Key points”CLAUDE.mdholds the commands SlashForge’s Phase 6 runs; rules withpaths:load only for matching files; skills are folders with aSKILL.md.- Setup’s generated files carry a
generated_bymarker; a file whose marker is missing or edited is treated as yours on a re-run. - The kit’s two guides disagree about where skills go and how long they may be; Claude Code’s documentation requires the folder form.
- The verify step’s
wc -l .claude/**/*.mddoesn’t look inside skill folders in bash’s default mode: a 300-line skill passes. - When a command exists in
~/.claudeand in the project, the personal copy runs. A team install only holds for teammates without a global one.
Exercises
Section titled “Exercises”- Rewrite the verify step so that it fails, with a non-zero exit code, when any file under
.claude/orCLAUDE.mdexceeds 200 lines, in a way that works in bash 3.2. - You want
/slashforge:codeto run your team’snpm run lint:strictin Phase 6. Where do you put it, and what happens if you don’t? - A teammate says the committed kit is “not working” and describes gates that 4.4.3 doesn’t have. What do you ask them to run?
Solution
-
For example:
Terminal window find CLAUDE.md .claude -name '*.md' -exec wc -l {} + \| awk '$2 != "total" && $1 > 200 { print; bad = 1 } END { exit bad }'findwalks every depth without shell options, andawkprints the offending files and sets the exit code. -
In the Commands section of
CLAUDE.md, as the lint command. Phase 6 reads the commands fromCLAUDE.md; if lint, test or build is missing, the workflow stops and asks for it — or, headless, the run ends there. -
npx slashforge statusandnpx slashforge status --project: the first shows a global install and its version. If there is one, it is the one running;npx slashforge uninstallremoves it, and the committed project copy takes over.