Skip to content

v1.0.0

Choose a tag to compare

@sogeisetsu sogeisetsu released this 23 Oct 11:02
· 74 commits to main since this release

What this is

skill_management adds a switchboard for the skills installed in your OpenCode setup: see what is installed, find out why one will not load, take one out of the model's view, and put it back.

Disabling never touches skill files. It writes one skill permission rule into your global config (effect: "deny", or "ask" for a soft disable). Nothing is deleted, moved or rewritten, and removing that rule restores the skill exactly as it was.

This is the first stable release: the surface described below is frozen for 1.x.

What it does

Action What it does Writes config
list Every registered skill with its effective state for the calling agent (available / disabled / ask) no
inspect Why one skill is (un)available: the matching rule, per-agent differences, how its id was derived no
disable Hide it from the model and reject loading it (effect: "ask" keeps it listed and asks on load) yes
enable Remove the blocking rule again, whoever wrote it yes

How a permission is resolved: the host reads the rule set of the agent that is calling, takes the last match (findLast) with * / ? globs, and — when nothing matches — falls back to ask, not allow. That is why list and inspect evaluate per agent and name the agent they used.

disable writes exactly this line (the trailing comment is the origin marker that enable uses):

{ "action": "skill", "resource": "windows-shell", "effect": "deny" } // skill_management

With deny the skill disappears from the model-visible skill list, and loading it through the built-in skill tool is rejected (permission.rejected).

How to use

skill_management({ action: "list" })
skill_management({ action: "inspect", id: "windows-shell" })
skill_management({ action: "disable", id: "windows-shell" })
skill_management({ action: "disable", id: "windows-shell", dryRun: true })
skill_management({ action: "disable", id: "windows-shell", effect: "ask" })
skill_management({ action: "enable",  id: "windows-shell" })
  • id is the primary key from the host registry; name works as an alias when it is unambiguous (an ambiguous name returns candidates, never a guess).
  • dryRun: true prints the exact lines that would be written and writes nothing.
  • Writes are atomic (.tmp + rename) and preserve indentation, key order, line endings (CRLF/LF) and BOM. One backup is kept under <config>/skill_management.backups/ — it is a full copy of the config, which may contain credentials, so delete it if you keep secrets there.
  • After writing, the tool reloads the host and polls the agent rule sets to confirm the change actually landed; if it did not, the file is rolled back.
  • enable removes the one blocking rule for that id — it does not have to be a rule this tool wrote. It refuses, and shows you the rule, when it cannot uniquely identify it, or when the blocker is a wildcard rule, an agent-level permissions entry, or a policy (those are only reported, never edited).

What's changed since v0.2.0

Fixed — disable with effect: "ask" could report success without doing anything. The read-back check asked "is the caller's effective effect not deny?". The host falls back to ask when no rule matches, and an agent's own rule can sit after the global one and turn it into allow — neither is deny, so the check passed even when the host had never loaded the rule. It now verifies that the number of matching { skill, id, ask } rules in the caller's rule set actually went up (0 → 1 appears in the output). If the rule was loaded but a later agent rule overrides it, the output says so instead of claiming it took effect.

Fixed — a single-line permissions array produced invalid JSON. With "permissions": [{ … }] all on one line, adding a rule put the comma after the new entry, leaving a config the host could not parse. Insertion now handles the one-line case.

Fixed — a damaged state file could be trusted, and a broken config threw. <config>/skill_management.state.json is now rejected as a whole when it is not valid JSON, has no rules array, or carries an unknown version; list reports it instead of silently ignoring it. enable now reports a syntactically broken config file instead of throwing.

Faster. list no longer parses the target config twice, glob matching skips the regex when the pattern has no wildcard, and strict JSONC validation no longer spreads the whole file into a character array. Measured on 29 skills × 12 agents × 10 rules over a 13.6 KB config: 3.72 ms → 2.24 ms median (60 runs).

Frozen for 1.x: the four actions' inputs and output semantics, the rule shape above, the same-line marker comment, and the single-file plugin layout. Breaking any of them requires 2.0.0.

Maintenance. Publishing from CI is idempotent: re-running the publish workflow for an already published version exits successfully instead of failing.

Install or upgrade

Pick one. Recommended: the git spec — no registry lookup and no token.

opencode plugin add github:sogeisetsu/opencode-skill-management
# npm
opencode plugin add opencode-skill-management@1.0.0

Offline / single file (no registry, no npm): download skill_management.js from the assets below and drop it into <config>/plugins/ — %USERPROFILE%\.config\opencode\plugins\ on Windows, ~/.config/opencode/plugins/ elsewhere. The host scans that directory at startup; no config entry is needed.

opencode plugin list --builtin
# skill_management   local   <config>/plugins/skill_management.js

--builtin is required: without it, directory plugins are not listed and you will see No plugins found.

Which asset is which

Asset What it is When to use it
skill_management.js the whole plugin, one file drop into <config>/plugins/ — no npm, no network
opencode-skill-management-1.0.0.tgz the exact npm tarball (npm pack output) unpack it yourself, mirror it internally, or check what npm is actually serving

Source code (zip) / Source code (tar.gz) are GitHub's automatic snapshots of the repository; the two assets above are the installable artifacts.

Requirements and what was verified

  • OpenCode V2, tested on 2.0.32 (Windows and Linux). Other V2 builds are not claimed — the host APIs used here are exercised end-to-end by the acceptance suite, so an upgrade is easy to re-check.
  • Node 18+; only node: built-ins, no dependencies, no shell calls.
  • 248 assertions pass on Windows and on Linux (node tools/verify.mjs). The disable → rejected load → enable round trip was re-run on a real host in a fresh process: the skill disappears from the model-visible list, loading it returns permission.rejected, and enable restores the config byte for byte.

Limits. Only the global config's skill permission rules are written — not project config, not skill files, not policies. ask is a soft disable: the skill stays listed and each load asks. list's state column is evaluated for the calling agent, so sub-agents that deny everything by default will show different states; inspect prints the per-agent table.

Full changelog: v0.2.0...v1.0.0