Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,12 @@ hyphens are both valid segment separators; dots enable namespace-style names
lowercase alphanumeric segments joined by hyphens, with at most one colon
separating category from value. Uppercase is rejected on write so stored tags
have one canonical form; tag *filters* stay case-insensitive so legacy
hand-edited tags still match. `skill list` filters on them via `--tag` (flat)
and `--category` (namespaced, repeatable, OR within a category, AND across
categories).
hand-edited tags still match. `skill list`, `skill install`, and
`skill uninstall` filter on them via `--tag` (flat) and `--category`
(namespaced, repeatable, OR within a category, AND across categories) — one
`skillFilter` in `internal/cli/skill_helpers.go` defines the flags and match
semantics for all three; on install/uninstall the filter is mutually
exclusive with positional names.

**Unmodeled keys pass through.** The fields above are the keys skern models;
any other key — top-level, `metadata.*`, or nested in `metadata.author` /
Expand Down Expand Up @@ -326,7 +329,6 @@ Everything planned is a tracked issue; this list is a map, not a commitment.

**Correctness and ergonomics (near-term)**

- [#102] — `--tag` on `skill install` / `skill uninstall` for group installs
- [#103] — exclude companion directories (eval corpora, fixtures) from install

**Adapter model** — all three need the declarative-hook mechanism from design
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`--tool-forming-loop`. The non-interactive contract is now documented and
enforced: when stdin is not a TTY or `--json` is set, `init` never prompts
and both questions resolve to "no". ([#104])
- **`--tag` / `--category` on `skern skill install` and `skill uninstall`.**
Select a group of registry skills with the same filters `skill list`
accepts instead of naming each one — `skern skill install --tag workflow
--platform claude-code`. Names and filters are mutually exclusive (exit 2
if mixed or if neither is given); a filter that matches nothing is an error,
never a silent no-op (registry parse warnings are surfaced rather than
swallowed). `uninstall --tag` narrows the group to what is actually
installed on the platform and skips the rest. `--enforce-budget` counts
the resolved group. ([#102])

### Changed

Expand Down Expand Up @@ -81,6 +90,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#97]: https://github.com/devrimcavusoglu/skern/pull/97
[#98]: https://github.com/devrimcavusoglu/skern/pull/98
[#100]: https://github.com/devrimcavusoglu/skern/issues/100
[#102]: https://github.com/devrimcavusoglu/skern/issues/102
[#104]: https://github.com/devrimcavusoglu/skern/issues/104

## [v0.3.1] — 2026-05-13
Expand Down
9 changes: 9 additions & 0 deletions docs/concepts/platform-adapters.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@ skern skill install code-review test-runner deploy-checker --platform claude-cod
skern skill uninstall stale-a stale-b --platform claude-code
```

A batch can also be selected by tag instead of by name, using the same `--tag` / `--category` filters as `skill list`:

```sh
skern skill install --tag workflow --platform claude-code --scope project
skern skill uninstall --tag workflow --platform claude-code --scope project
```

Names and filters are mutually exclusive; a filter that matches nothing is an error, not a silent no-op. See [Commands › install](/reference/commands#group-installs-tag-category).

Each skill's outcome is reported separately in the JSON output's `skills` array, and a `capacity` block reports the platform's installed-skill count after the batch.

## Platform Status Matrix
Expand Down
1 change: 1 addition & 0 deletions docs/guide/agent-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ skern skill list --with-platforms --json # adds installed_on per skill
skern skill search "review" --json
skern skill show code-review --json
skern skill install code-review --platform claude-code --json
skern skill install --tag workflow --platform claude-code --json # group install by tag
```

The `install`/`uninstall` JSON envelope carries a `skills[]` array (one entry per skill) and a top-level `capacity` block (`installed`, `threshold`, `headroom`, `over_budget`). Agents can react to capacity pressure without an extra query.
Expand Down
3 changes: 2 additions & 1 deletion docs/guide/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ for p in claude-code codex-cli opencode cursor gemini-cli; do
done
```

Multiple skill names can be installed in a single call:
Multiple skill names can be installed in a single call, or a whole tagged group at once:

```sh
skern skill install code-review test-runner deploy-checker --platform claude-code
skern skill install --tag workflow --platform claude-code # every registry skill tagged "workflow"
```

The response includes a `capacity` block reporting the installed-skill count, threshold, and remaining headroom for the platform. Pass `--enforce-budget` to refuse the install when the count would exceed the threshold.
Expand Down
19 changes: 19 additions & 0 deletions docs/reference/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,20 @@ Install one or more skills to a single platform.

```sh
skern skill install <name>... --platform <platform>
skern skill install --tag <tag> --platform <platform> # install a tagged group
skern skill install --category lang:python --platform <platform> # or a namespaced-tag group
```

Each invocation targets exactly one platform — `--platform all` is not accepted. Multiple skill names can be passed in one call. Each skill's outcome is reported in the `skills[]` array; a failure on one skill does not abort the batch — the command exits non-zero only when *every* install fails.

### Group installs (`--tag`, `--category`)

Instead of names, select a group with the same filters [`skill list`](#skern-skill-list) accepts: `--tag <tag>` (flat tag) and/or `--category <category:value>` (repeatable, comma-lists values, OR within a category, AND across categories; `--include-untagged` applies as in `list`). The filter resolves against the registry at `--scope`, so `--tag workflow --scope project` installs the project-registry skills tagged `workflow`. Resolved names are installed in sorted order and reported per-skill exactly as a name batch would be.

- Names and filters are **mutually exclusive** — passing both is a validation error (exit 2), as is passing neither.
- A filter that matches no registered skill is an **error** (exit 1: `no registered skills match --tag workflow in user scope`), never a silent no-op. Registry parse warnings (a skill directory whose `SKILL.md` could not be read — which may be exactly why a tag matched nothing) are included in that error, and printed to stderr when the filter does match.
- `--enforce-budget` counts the resolved group.

The response includes a top-level `capacity` block reporting the platform's installed-skill count after the operation, the threshold for that scope, and remaining headroom.

**Flags:**
Expand All @@ -308,21 +318,30 @@ The response includes a top-level `capacity` block reporting the platform's inst
| `--scope` | `user` | `user` or `project` |
| `--force` | `false` | Overwrite existing installation |
| `--enforce-budget` | `false` | Refuse the operation if it would push the platform's installed-skill count past the per-scope threshold |
| `--tag` | — | Select registry skills carrying this tag instead of naming them. Mutually exclusive with names. |
| `--category` | — | Select by namespaced tag `category:value`; repeatable, comma-lists values. Mutually exclusive with names. |
| `--include-untagged` | `false` | With `--category`: treat a skill with no tag in a requested category as matching it. |

## `skern skill uninstall`

Remove one or more skills from a platform. Mirrors `install` semantics: one platform per call, multiple skills allowed, partial failures reported per-skill, post-op `capacity` block in the response. The registry copy is **not** affected — use `skern skill remove` for that.

```sh
skern skill uninstall <name>... --platform <platform>
skern skill uninstall --tag <tag> --platform <platform> # evict a tagged group
```

`--tag` / `--category` select a group the same way as on `install`: the filter resolves against the registry at `--scope`, then is narrowed to the skills actually installed on the platform. Tagged-but-not-installed skills are skipped, not reported as failures. If nothing in the group is installed the command errors (`no installed skills match --tag workflow on claude-code (user scope)`); if the tag matches nothing in the registry, the error says so instead. Names and filters are mutually exclusive.

Because the registry defines the group, a skill that was already removed from the registry (`skern skill remove`) is no longer reachable by tag — uninstall it by name. Retire a group by uninstalling it from platforms *before* removing it from the registry.

**Flags:**

| Flag | Description |
|------|-------------|
| `--platform` | Required. Same enumeration as `install`. |
| `--scope` | `user` or `project` |
| `--tag` / `--category` / `--include-untagged` | Group selection, as on `install`. |

## `skern platform list`

Expand Down
Loading