Skip to content

Add --tag/--category group selection to skill install and uninstall (#102) - #108

Merged
devrimcavusoglu merged 3 commits into
mainfrom
feature/install-tag-filter
Aug 19, 2026
Merged

Add --tag/--category group selection to skill install and uninstall (#102)#108
devrimcavusoglu merged 3 commits into
mainfrom
feature/install-tag-filter

Conversation

@devrimcavusoglu

Copy link
Copy Markdown
Owner

Summary

Fixes #102.

  • skill install and skill uninstall accept --tag, --category (repeatable), and --include-untagged — the same filters skill list has. They're defined once as a skillFilter in skill_helpers.go (flags + help + match semantics), and skill list is refactored onto it too, so the three commands can't drift.
  • Filters resolve against the registry at --scope (consistent with how install already does reg.Get(name, scopeVal)); resolved names are processed in sorted order and reported per-skill exactly like a name batch.
  • Names and filters are mutually exclusive (validation error, exit 2), and passing neither is also a validation error (previously cobra's MinimumNArgs plain error).
  • Empty match is an errorno registered skills match --tag X in <scope> scope (exit 1), never a silent no-op.
  • uninstall --tag resolves the group from the registry, then intersects with InstalledSkills(scope): tagged-but-not-installed skills are skipped rather than reported as per-skill failures; nothing installed → no installed skills match --tag X on <platform> (<scope> scope).
  • --enforce-budget counts the resolved group.

Issue DoD

  • --tag on skill install and skill uninstall (plus --category, since it's the same filter object)
  • --tag and explicit names are mutually exclusive — documented and enforced
  • Empty match is a clear message, not a silent no-op

Test plan

  • 9 new tests in platform_test.go: install by tag, tag AND category, category comma-list OR, empty match, names+filter conflict, neither-given, malformed --category, scope-respecting resolution, --enforce-budget with resolved count, uninstall-by-tag skips uninstalled, uninstall nothing-installed error, uninstall conflict
  • go test ./..., make lint green
  • Manual smoke with the built binary (transcript in the session): install --tag workflow → two installs; --tag nope → exit 1 with message; b1 --tag workflow → exit 2; uninstall --tag workflow → both removed

🤖 Generated with Claude Code

devrimcavusoglu added a commit that referenced this pull request Aug 19, 2026
#108 removed the then-unused skill import from skill_install.go and #109
needs it again for ValidateExcludePatterns. The four near-term roadmap
entries are all closed by this stack, so the group heading goes too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@devrimcavusoglu
devrimcavusoglu force-pushed the feature/install-tag-filter branch from 27b2ab4 to 3fa77bc Compare August 19, 2026 13:14
@devrimcavusoglu
devrimcavusoglu changed the base branch from main to feature/init-no-instructions August 19, 2026 13:14
@devrimcavusoglu

Copy link
Copy Markdown
Owner Author

Review (adversarial pass against #102)

DoD: all three items hold (mutual exclusion chosen and enforced consistently in help/docs/CHANGELOG; empty match is exit 1 with a message; skill list is a pure refactor — help text and --json output byte-identical to main).

Findings and what changed in af01d75 / 3fa77bc:

Sev Finding Resolution
Medium TestSkillInstall_Filter_EnforceBudgetCountsResolved only ran the happy path — reverting the fix to len(args) still passed Test seeds the platform to threshold-1 and asserts the refusal, then fits exactly at threshold
Low/Med Registry parse warnings were swallowed by install/uninstall --tag (a malformed SKILL.md can be why a tag matches nothing; skill list shows them) Warnings appended to the empty-match error and printed to stderr otherwise (TestSkillInstall_Filter_SurfacesParseWarnings)
Low Installed-but-already-removed-from-registry skills are unreachable by uninstall --tag (by design) Documented: uninstall a group before removing it from the registry
Low uninstall duplicated the names-path of resolveActionTargets resolveActionTargets takes a lazy registry constructor; duplication gone
Nit Roadmap still listed #102; guides didn't show group installs Fixed

Noted, not changed: no-args install/uninstall now exit 2 (ValidationError) instead of cobra's exit 1 — deliberate, matches the repo's "validation failure" code, called out in the CHANGELOG.

Stacked on #107 (base feature/init-no-instructions); CI runs once the base becomes main.

@devrimcavusoglu
devrimcavusoglu force-pushed the feature/init-no-instructions branch from 196d7a8 to 9158cfc Compare August 19, 2026 13:47
@devrimcavusoglu
devrimcavusoglu changed the base branch from feature/init-no-instructions to main August 19, 2026 13:50
devrimcavusoglu and others added 3 commits August 19, 2026 16:50
…102)

Factor the tag/category filter that skill list uses into a shared
skillFilter (flags, help text, and match semantics in one place) and
accept it on install and uninstall. The filter resolves against the
registry at --scope; names and filters are mutually exclusive (exit 2);
an empty match is an error rather than a silent no-op. uninstall
narrows the group to what is installed on the platform and skips the
rest. --enforce-budget counts the resolved group.

Closes #102

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e warnings

- The budget test now seeds the platform to threshold-1 and asserts the
  refusal (the previous happy-path test passed with the pre-fix code).
- Filter resolution returns registry parse warnings; they are appended to
  the empty-match error and printed to stderr otherwise, as `skill list`
  does, so a malformed SKILL.md is not a silent reason for "matches nothing".
- resolveActionTargets takes a lazy registry constructor, removing the
  duplicated names-path in uninstall.
- Docs: ghost-skill note for uninstall --tag, group-install examples in the
  guides, roadmap line dropped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@devrimcavusoglu
devrimcavusoglu force-pushed the feature/install-tag-filter branch from 3fa77bc to 3c155ae Compare August 19, 2026 13:50
@devrimcavusoglu
devrimcavusoglu merged commit e852458 into main Aug 19, 2026
5 checks passed
devrimcavusoglu added a commit that referenced this pull request Aug 19, 2026
#108 removed the then-unused skill import from skill_install.go and #109
needs it again for ValidateExcludePatterns. The four near-term roadmap
entries are all closed by this stack, so the group heading goes too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@devrimcavusoglu
devrimcavusoglu deleted the feature/install-tag-filter branch August 19, 2026 13:52
devrimcavusoglu added a commit that referenced this pull request Aug 19, 2026
…rm copies (#103) (#109)

* Add install.exclude frontmatter to keep companion files out of platform copies (#103)

skill install copied the whole skill tree, so eval corpora and fixtures
landed in every agent's context. Model an author-owned `install.exclude`
list of path.Match globs on Skill/frontmatter; match each relative path
and its leading directories in skill.MatchExclude; thread the patterns
through a new platform.InstallOptions argument on Platform.Install so
copyDir prunes matched files and directories. The registry always keeps
the full directory. skill validate errors on malformed, absolute, or
`..` patterns and anything matching SKILL.md, and warns when a pattern
matches nothing or excludes a body-referenced file.

Closes #103

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Address review: diff install.exclude, pass through install.* extras, refuse bad patterns at install

- skill diff reports a changed install.exclude list (it went blind once
  install became a modeled key) and diffs install.* extras.
- InstallConfig gets an inline Extra map (+ collision guard) so other keys
  under install: round-trip like every other unmodeled key; `exclude`
  accepts a bare string as a one-element list.
- skill install refuses a skill whose patterns fail validation instead of
  silently copying what path.Match could not parse; `**` is rejected
  outright rather than degrading to `*`.
- Only the literal SKILL.md is an error: wildcards that also match it are
  legal since MatchExclude never excludes the manifest. Backslashes are
  left alone (path.Match escape), validator field carries [index] for
  multi-entry lists.
- Docs: no `--files` flag; exact matching/escape/compat rules; roadmap
  line dropped; json tag omitzero.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Restore skill import after restack; drop emptied roadmap heading

#108 removed the then-unused skill import from skill_install.go and #109
needs it again for ValidateExcludePatterns. The four near-term roadmap
entries are all closed by this stack, so the group heading goes too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

Add --tag to skill install and skill uninstall for group installs

1 participant