feat(cc-config): list a plugin's skills, agents and commands by name

A plugin card showed "7 skills, 5 agents" and nothing more — the counts
were the whole story, so finding out WHICH skills a plugin ships meant
opening its install directory by hand. The contribution chips are now
buttons: clicking one expands a list naming each artifact with its
description, one surface open at a time. Commands render with their
slash. Hooks stay a plain chip — a plugin's hooks are matcher/command
pairs declared inline in plugin.json, not named artifacts.

`contributes.items` carries the four surfaces server-side; the existing
counts keep their type and are now derived from those lists, so a chip
reading "3 commands" can never sit beside a list holding two.

That also fixes a real blind spot. Each surface was read only from the
conventional install subdirectory, but plugin.json may declare its own
paths — this repo's own `ccam` lists three files under
plugins/ccam/commands/ and keeps commands/ empty, so it reported zero
commands. Both sources are now read and de-duplicated. A declared path
resolving outside the plugin's install directory is dropped: a manifest
is third-party data and must not turn the dashboard into an arbitrary
file reader.

Also pins the Refresh button's width: both labels share one grid cell so
the button is always as wide as "Refreshing…" / "Đang làm mới…" and no
longer resizes the toolbar when the state flips. Measuring the longest
real string beats a min-width that would be wrong in the next language.

Verified: npm run test:server (1370 tests, +6 for the new discovery),
npm run test:client (457, +3 for the expand behaviour), tsc --noEmit,
prettier and check-headers clean. Docs synced: docs/API.md, openapi.yaml
(new CcConfigPluginItem schema), ARCHITECTURE.md, docs/PLUGINS.md.
This commit is contained in:
2026-09-04 11:21:12 +07:00
parent 965c62c5cf
commit 677cdf007b
10 changed files with 540 additions and 49 deletions
+76 -9
View File
@@ -1890,38 +1890,91 @@ components:
type: string
description: First 320 characters of the markdown body (after frontmatter).
example: Review backend route and hook logic for regressions...
CcConfigPluginItem:
type: object
description: One named artifact a plugin contributes - a skill, subagent, slash command or output style.
required:
- name
- description
- file
properties:
name:
type: string
description: Frontmatter `name` when the file declares one (that is what Claude Code addresses it by), else the filename without its .md extension.
example: ship-feature-lane
description:
type: string
nullable: true
description: Frontmatter `description`, or null when the file declares none.
example: Autonomous end-to-end feature pipeline for ONE CCAM lane.
file:
type: string
description: Absolute path of the backing markdown file (SKILL.md for a skill).
example: /Users/son/.claude/plugins/cache/sg/ccam/skills/ship-feature-lane/SKILL.md
CcConfigPluginContributions:
type: object
nullable: true
description: Counts of artifacts a plugin contributes, plus its parsed .claude-plugin/plugin.json. Null when the plugin's installPath does not exist on disk.
description: Counts of artifacts a plugin contributes, the same surfaces listed by name under `items`, plus its parsed .claude-plugin/plugin.json. Null when the plugin's installPath does not exist on disk.
required:
- skills
- agents
- commands
- outputStyles
- hooks
- items
- pluginJson
properties:
skills:
type: integer
description: Number of skill directories (containing SKILL.md) under the plugin.
description: Number of skills the plugin contributes; always equals `items.skills.length`.
example: 3
agents:
type: integer
description: Number of .md agent files under the plugin.
description: Number of subagents the plugin contributes; always equals `items.agents.length`.
example: 2
commands:
type: integer
description: Number of .md command files under the plugin.
description: Number of slash commands the plugin contributes; always equals `items.commands.length`.
example: 5
outputStyles:
type: integer
description: Number of .md output-style files under the plugin.
description: Number of output styles the plugin contributes; always equals `items.outputStyles.length`.
example: 0
hooks:
type: integer
description: Number of files under the plugin's hooks/ directory.
description: Number of files under the plugin's hooks/ directory. Has no `items` list - a plugin's hooks are matcher/command pairs declared inline in plugin.json, not named artifacts.
example: 1
items:
type: object
description: >-
The contributed artifacts by name, so a client can show WHICH skills,
subagents, commands and output styles a plugin ships. Each surface
covers both the conventional directory (`skills/`, `agents/`,
`commands/`, `output-styles/`) and any path plugin.json declares for
that key; a declared path escaping the plugin's own install directory
is ignored.
required:
- skills
- agents
- commands
- outputStyles
properties:
skills:
type: array
items:
$ref: '#/components/schemas/CcConfigPluginItem'
agents:
type: array
items:
$ref: '#/components/schemas/CcConfigPluginItem'
commands:
type: array
items:
$ref: '#/components/schemas/CcConfigPluginItem'
outputStyles:
type: array
items:
$ref: '#/components/schemas/CcConfigPluginItem'
pluginJson:
type: object
nullable: true
@@ -7511,11 +7564,25 @@ paths:
installPathExists: true
enabled: true
contributes:
skills: 3
agents: 2
commands: 5
skills: 2
agents: 1
commands: 0
outputStyles: 0
hooks: 1
items:
skills:
- name: brainstorming
description: Explores intent and design before implementation.
file: /Users/son/.claude/plugins/superpowers/skills/brainstorming/SKILL.md
- name: writing-plans
description: Turns a spec into a step-by-step implementation plan.
file: /Users/son/.claude/plugins/superpowers/skills/writing-plans/SKILL.md
agents:
- name: code-reviewer
description: Reviews a diff for correctness regressions.
file: /Users/son/.claude/plugins/superpowers/agents/code-reviewer.md
commands: []
outputStyles: []
pluginJson:
name: superpowers
version: 1.2.0