Skip to content

refactor: drop the command files on Claude Code, move the scc- prefix onto the skill - #46

Merged
protonspy merged 1 commit into
mainfrom
refactor/drop-duplicate-commands
Sep 15, 2026
Merged

protonspy merged 1 commit into
mainfrom
refactor/drop-duplicate-commands

Conversation

@protonspy

Copy link
Copy Markdown
Owner

Follow-on to #45, closing the one item that PR left open.

What was duplicated

Claude Code registers a skill at skills/<name>/SKILL.md as /<name> by itself, and its own documentation now says commands and skills are the same mechanism — "for new workflows, use skills/ instead: same /name invocation" — with nothing a command file can do that a skill cannot.

So commands/scc-wiki.md sitting beside skills/scc-wiki/ was two entries in the picker for one thing, and a second description preloaded into every request whether anybody ran it or not. Eight of them: about 980 characters of saying twice what the skill's own description says once.

paths.Harness.SkillsAreCommands is the capability. opencode still gets command files, because nothing there turns a skill into one. Codex still gets none, because its prompts are user-global.

Why the rename came with it

Deleting the command files alone would have shipped a second collision. With no command file the skill's own name is what the user types, and /init is a slash command Claude Code already ships — which is the failure the review agents had under their unprefixed names in #45, arriving by the same door one version later.

So the prefix moves from the command onto the skill: scc-init, scc-wiki, scc-plan-run and the rest. Every /scc-init already written keeps resolving, in the Dockerfile and in scc launch's hint. TestEverySkillShipsWithItsCommand now holds the property underneath both routes rather than the file that used to implement one of them, and fails on a skill whose name is not namespaced.

What the command bodies were carrying

Not nothing, which is why this is a move rather than a delete. Each one held the default job — what to do when nobody typed an argument. For five of them that is "run scc validate and clear this artifact's findings"; for the wiki it is "look at docs/raw/ first, and if there are no findings say so rather than inventing pages".

That is in the skill bodies now, under ## Nothing asked for, where the run that invokes it pays for it instead of every session. argument-hint moved with it, since SKILL.md takes the same key. The command templates opencode still receives are a dispatch stub generated from the skill's own frontmatter, so there is one source rather than two.

#45 here
preloaded per request 40,178 B 39,074 B

Against 52,388 B before #45.

Verification

Build, gofmt -l, go vet, golangci-lint run (0 issues) and the full suite are green. -race needs cgo and there is no gcc on this machine, so CI is the first place it runs.

Scaffolded both affected harnesses and checked them: Claude Code has eight scc--named skills and no commands/ directory; opencode has the same eight skills plus its eight command stubs. The entry file's layout block names a commands directory only where one exists. scc validate is clean on both.

…fix onto the skill

Claude Code registers a skill at `skills/<name>/SKILL.md` as `/<name>` by itself,
and its own documentation now says commands and skills are one mechanism with
nothing a command can do that a skill cannot. So `commands/scc-wiki.md` beside
`skills/scc-wiki/` was two entry points in the picker for one thing and — the
half that is not cosmetic — a second `description` preloaded into every request
whether anybody ran it or not. Eight of them, ~980 characters of saying twice
what the skill's own description says once.

`paths.Harness.SkillsAreCommands` is the capability. opencode still gets command
files because nothing there turns a skill into one; Codex still gets none
because its prompts are user-global and deprecated in favour of skills.

The rename is what makes the removal safe rather than a second collision. With
no command file the skill's own name is what the user types, and `/init` is a
command Claude Code already ships — the same failure the review agents had under
their unprefixed names one version ago, arriving by the same door. So the skills
are `scc-init`, `scc-wiki` and the rest, and every reference to `/scc-init`
already written keeps resolving, in the Dockerfile and in `scc launch`.

What the command bodies carried and the skills did not is the default job: what
to do when nobody typed an argument, which for five of them is "run
`scc validate` and clear this artifact's findings". That is in the skill bodies
now, where the run that invokes it pays for it instead of every session, and
`argument-hint` moved with it since SKILL.md takes the same key. The command
templates opencode still gets are a dispatch stub, so there is one source.

Preloaded, Claude Code, fresh workspace: 40178 -> 39074 bytes.
@protonspy
protonspy merged commit d067f29 into main Sep 15, 2026
4 checks passed
protonspy added a commit that referenced this pull request Sep 15, 2026
… 31 (#48)

#46 landed just below #47, so the .claude/ tree committed by the knowledge-base run
was already a version behind main's own templates: it still carried .claude/commands/
and the unprefixed skill and agent names that #46 removed. `scc update` closes that,
and `scc update --dry-run` is clean afterwards.

  create  8 scc-* skills, scc-code-review, scc-security-review
  update  rules/delivery.md, knowledge-base.md, specs.md, tasks.md
  delete  .claude/commands/ entirely, the unprefixed skills and agents

Two things were verified rather than assumed. The manifest's `check` object survives
the rebuild — Manifest.CarryOver does what it says, so the four gate commands
recorded by #47 are untouched. And .claude/rules/project.md and CLAUDE.md were both
reported as yours and left alone.

The emptied directories are removed by hand, because `scc update` does not prune
them: it deletes the managed file and leaves the directory, and the skills validator
then reports skill.missing-skill-md on each one — eight of them here. Git does not
track empty directories, so this never reaches a clone, but it fires for anyone
running `scc update` in place. Recorded as n-0006; fixing internal/scaffold is not
this branch's job.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant