feat(cli): install agent skill at user level#284
Merged
Conversation
…to repos `no-mistakes init` no longer writes SKILL.md into each target repo's .claude/skills and .agents/skills. It now installs/refreshes the skill at user level: ~/.claude/skills/no-mistakes/SKILL.md (Claude Code, OpenCode) and ~/.agents/skills/no-mistakes/SKILL.md (Codex, OpenCode, Rovo Dev, Pi). Both locations were verified against each harness's documented user-level skill discovery. The symlink-aware install logic is reused unchanged with the home directory as root, and install stays idempotent and best-effort. When init finds a vendored copy left by an older version it prints a one-line notice that the copy can be removed, without touching it. The metadata.internal frontmatter marker is gone: it existed solely to hide vendored per-repo copies from repo skill listings, and the user-level copy is a genuine user installation that should stay discoverable. With no vendored copies anywhere, InstalledMarkdown() is deleted, genskill renders only the canonical skills/no-mistakes/SKILL.md, and this repo's own committed .agents/skills copy and .claude/skills symlink are removed.
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.
Intent
Change no-mistakes init so it stops vendoring the agent skill into every target repo and installs it at user level instead. Old behavior: init wrote SKILL.md into .claude/skills/no-mistakes/ and .agents/skills/no-mistakes/ inside each target repo, polluting every initialized repo with tool-generated files that had to be committed. New behavior: (1) init writes no skill files into the target repo; (2) it installs/refreshes the skill at user level, ~/.claude/skills/no-mistakes/SKILL.md and ~/.agents/skills/no-mistakes/SKILL.md - these two locations were verified against each supported harness's documented user-level skill discovery: Claude Code reads ~/.claude/skills (OpenCode reads it too), and Codex, OpenCode, Rovo Dev, and Pi all read the vendor-neutral ~/.agents/skills; the existing symlink-aware Install logic is reused unchanged with the home directory as root via a new skill.InstallUser(); (3) install stays idempotent and best-effort exactly as before - failure prints the dim 'skipped' note and never fails init; (4) legacy cleanup: when init runs in a repo that still contains a vendored copy, it does NOT delete it - it prints a one-line dim notice that the vendored copy is no longer needed and can be removed (new skill.Vendored helper detects them); (5) deliberate decision: the metadata.internal: true frontmatter marker is dropped entirely - it existed solely to hide vendored per-repo copies from repo skill listings, and the user-level copy is a genuine user installation that should stay discoverable, so InstalledMarkdown() and the markdown(internal bool) split were deleted and only the public Markdown() rendering remains; (6) deliberate decision: this repo's own committed vendored copy (.agents/skills/no-mistakes/SKILL.md and the .claude/skills symlink) is removed and cmd/genskill now renders only the canonical skills/no-mistakes/SKILL.md - the vendored copy's stated rationale was 'identical to what init writes into any target repo', which no longer holds, and keeping it would make init print the legacy notice inside our own repo; contributors get the skill at user level by running init. Init output text now says 'installed for agents at user level'. Docs updated (guides/agents.md, concepts/gate-model.md, reference/cli.md, start-here/introduction.md, quick-start.md, README sample output). Tests: skill package tests rewritten for the single rendering plus new InstallUser (HOME/USERPROFILE isolated via t.Setenv) and Vendored tests; e2e assertSkillInstalled now checks the user-level copies under the harness home, asserts no internal marker, and asserts the repo tree stays untouched; TestInitIsIdempotent now proves a stale user-level copy is refreshed; new TestInitLegacyNotice proves the notice prints and the vendored file is left byte-identical (test name kept deliberately short because the macOS Unix socket path limit applies to NM_HOME under t.TempDir, same as TestInitRepoRename). A dual-location compatibility flag was deliberately left out per the task constraint - user-level only is the desired end state. gofmt, make lint, go test -race ./..., and make e2e all pass; manual verification was done with HOME and NM_HOME pointed at temp dirs, never the real home.
What Changed
no-mistakes initto install or refresh the agent skill in user-level Claude and vendor-neutral skill directories instead of writing skill files into each target repo.Risk Assessment
✅ Low: The change is well-bounded to init skill installation, generated skill output, and matching documentation/tests, and I did not find a material correctness, security, or migration issue in the reviewed diff.
Testing
Targeted skill tests, targeted init e2e tests, and a manual isolated
no-mistakes inittranscript all exercised the user-level install and legacy-notice behavior successfully; the full race suite passed after retrying one transient localgit statussegfault in an unrelated pipeline-step test.Evidence: Manual init user-level skill transcript
Source: Manual init user-level skill transcript
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 1 issue found → auto-fixed ✅
docs/src/content/docs/start-here/quick-start.md:89- This quick-start sentence still saysno-mistakes initinstalled the/no-mistakesskill into the repo, which contradicts the new user-level installation behavior and can make users look for or expect committed.claude/.agentsfiles that init no longer creates.🔧 Fix: Fix quick-start skill install wording
✅ Re-checked - no issues remain.
internal/pipeline/steps/test_test.go:70- The first fullgo test -race ./...run failed inTestTestStep_FixModebecause agit status --porcelainsubprocess exited withsignal: segmentation fault. The exact test passed on immediate retry, and the full race suite passed on the next run, so this appears to be an intermittent local git/subprocess flake rather than a deterministic failure in this change.go test -race ./internal/skillgo test -tags=e2e ./internal/e2e -run 'TestInit(IsIdempotent|LegacyNotice)$' -count=1Manual CLI verification using a locally built./cmd/no-mistakesbinary with isolatedHOME,USERPROFILE, andNM_HOME: initialized a clean git repo and checked user-level skill files plus absence of repo-vendored skill files; initialized a repo with a legacy.agents/skills/no-mistakes/SKILL.mdand checked the notice plus byte-identical preservation.go test -race ./...(first run exposed transientgit status --porcelainsegfault inTestTestStep_FixMode)go test -race ./internal/pipeline/steps -run '^TestTestStep_FixMode$' -count=1go test -race ./...(retry passed)✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.