docs: skills + revisions + proposals reference, plus cheatsheet update
Phase 7 of the Skills + Revisions + Proposals work — documentation pass for the surface added in PR-1 through PR-6. Reference material only; no code changes. ## What's added - `docs/skills.md` — skill model, scoping rules, CLI surface, the `mcpctl config claude --project` setup flow, metadata schema (with the deferred-execution note for hooks/mcpServers/postInstall), the on-disk state file shape, atomic install mechanics, failure semantics, and what's deferred. - `docs/revisions.md` — ResourceRevision model, semver auto-bump rules, contentHash diff key (cross-resource sync), CLI for history / diff / restore, RBAC, audit emission, storage growth note. - `docs/proposals.md` — ResourceProposal model, the reviewer flow (CLI + web UI), atomic-approval mechanics, the propose_prompt / propose_skill MCP tools, the propose-learnings global skill that steers Claude toward engaging with them, and the deferred legacy PromptRequest cutover. ## What's edited - Top-level `CLAUDE.md` — resource cheatsheet adds `skill`, `proposal`, `revision` with cross-references to the new docs. The legacy `promptrequest` entry stays (still on the legacy code path) but notes that new work should use `proposal`. ## What's NOT in this PR - The PromptRequest → ResourceProposal cutover migration. Both run side-by-side today; the focused cutover PR will rename + backfill + drop. Keeping that out of PR-7 means review can stay on docs. - Bundle-backup / `mcpctl apply -f` skill support (deferred from PR-3). - `metadata.hooks` / `metadata.mcpServers` / `metadata.postInstall` execution (deferred from PR-5). - Existing-page UI migration to Tailwind (deferred from PR-6 — old inline-styled pages coexist fine inside the new Layout). These are tracked as future PRs; each is its own focused change. ## Verification `pnpm test:run` whole monorepo: 162 test files / 2157 tests green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
214
docs/skills.md
Normal file
214
docs/skills.md
Normal file
@@ -0,0 +1,214 @@
|
||||
# Skills
|
||||
|
||||
Skills are Claude Code skill bundles distributed by mcpctl. Each skill is a
|
||||
named bundle of files — at minimum a `SKILL.md` explaining the skill's purpose
|
||||
and triggers, optionally with auxiliary scripts, templates, or data files. The
|
||||
mcpctl daemon (mcpd) is the source of truth; `mcpctl skills sync` materialises
|
||||
the skills onto each dev machine under `~/.claude/skills/<name>/`, where Claude
|
||||
Code reads them natively.
|
||||
|
||||
```
|
||||
┌─ mcpd (Postgres) ──────────────────────────────┐
|
||||
│ Skill rows (content + files{} + metadata) │
|
||||
└────────────────┬───────────────────────────────┘
|
||||
│ HTTP, hash-pinned diff
|
||||
▼
|
||||
┌─ ~/.claude/skills/<name>/ ─────────────────────┐
|
||||
│ SKILL.md │
|
||||
│ scripts/setup.sh │
|
||||
│ … │
|
||||
└────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Trust model
|
||||
|
||||
Skills are added by senior admins together with a security reviewer at
|
||||
publish time on mcpd. Once content is in mcpd, clients trust what mcpd
|
||||
serves — no client-side sandboxing, no signature checks, no consent
|
||||
prompts. The rigor lives on the publishing side (RBAC, audit, the
|
||||
reviewer queue). See [proposals.md](proposals.md) for the
|
||||
review→approve flow.
|
||||
|
||||
If you're publishing skills to clients you don't trust (e.g. an open-
|
||||
source distribution), the design is wrong for that — the skill format
|
||||
itself is fine, but the unguarded client trust assumption isn't.
|
||||
|
||||
## Scoping
|
||||
|
||||
A skill attaches to one of:
|
||||
|
||||
- **Global** — `projectId` and `agentId` both null. Synced onto every dev
|
||||
machine when its sync runs (with or without a project context).
|
||||
- **Project-scoped** — `projectId` set. Synced onto machines whose
|
||||
`.mcpctl-project` marker matches.
|
||||
- **Agent-scoped** — `agentId` set. Surfaced administratively via the
|
||||
API; not currently materialised onto disk by `mcpctl skills sync`
|
||||
(see "Future" below).
|
||||
|
||||
The same `<name>` can exist at multiple scopes simultaneously. The two
|
||||
unique constraints are `(name, projectId)` and `(name, agentId)`.
|
||||
|
||||
## CLI
|
||||
|
||||
### Create
|
||||
|
||||
```bash
|
||||
mcpctl create skill <name> \
|
||||
[--project <name> | --agent <name>] \
|
||||
--content / --content-file <path> \
|
||||
[--description "<text>"] \
|
||||
[--priority <1-10>] \
|
||||
[--semver <X.Y.Z>] \
|
||||
[--metadata-file <path>] \
|
||||
[--files-dir <path>]
|
||||
```
|
||||
|
||||
`--content-file` provides the `SKILL.md` body. `--metadata-file`
|
||||
accepts YAML or JSON; see "Metadata" below for the schema. `--files-dir`
|
||||
walks a directory tree into the `files{}` map (UTF-8 only; non-text
|
||||
files rejected — extend later if needed).
|
||||
|
||||
### Edit
|
||||
|
||||
```bash
|
||||
# Edit content in $EDITOR
|
||||
mcpctl edit skill <name>
|
||||
|
||||
# Edit + bump semver
|
||||
mcpctl edit skill <name> --bump major|minor|patch --note "<message>"
|
||||
|
||||
# Edit + set explicit semver
|
||||
mcpctl edit skill <name> --semver 1.2.3
|
||||
```
|
||||
|
||||
Each save records a `ResourceRevision` automatically. See
|
||||
[revisions.md](revisions.md).
|
||||
|
||||
### Sync to disk
|
||||
|
||||
```bash
|
||||
# In a project directory (with .mcpctl-project marker):
|
||||
mcpctl skills sync
|
||||
|
||||
# Override project:
|
||||
mcpctl skills sync --project <name>
|
||||
|
||||
# Globals only (no project context, no marker):
|
||||
cd / && mcpctl skills sync
|
||||
|
||||
# Used by the SessionStart hook — fail-open on network errors:
|
||||
mcpctl skills sync --quiet
|
||||
```
|
||||
|
||||
Useful flags:
|
||||
|
||||
| Flag | Purpose |
|
||||
|---------------------|-----------------------------------------------------------|
|
||||
| `--dry-run` | Print what would change, don't write anything. |
|
||||
| `--force` | Overwrite locally-modified skills. |
|
||||
| `--quiet` | Suppress output unless something changed; fail-open. |
|
||||
| `--keep-orphans` | Don't remove skills no longer in the server set. |
|
||||
| `--skip-postinstall`| Reserved for the postInstall executor (deferred). |
|
||||
|
||||
## Project setup
|
||||
|
||||
`mcpctl config claude --project <name>` does the full pickup chain:
|
||||
|
||||
1. Writes `.mcp.json` so Claude Code routes MCP traffic through mcplocal.
|
||||
2. Writes `.mcpctl-project` (single line, project name) so `skills sync`
|
||||
knows which project's skills to pull when run from anywhere under
|
||||
that directory.
|
||||
3. Runs an initial `skills sync` synchronously.
|
||||
4. Installs a SessionStart hook in `~/.claude/settings.json` that runs
|
||||
`mcpctl skills sync --quiet` before every Claude session. Tagged
|
||||
with `_mcpctl_managed: true` so subsequent runs find and update it
|
||||
instead of duplicating it.
|
||||
|
||||
Pass `--skip-skills` to opt out of steps 2–4 (useful in CI).
|
||||
|
||||
## Metadata
|
||||
|
||||
The `metadata` field is a typed JSON blob:
|
||||
|
||||
```yaml
|
||||
hooks:
|
||||
PreToolUse:
|
||||
- type: command
|
||||
command: "echo before-tool"
|
||||
PostToolUse:
|
||||
- type: command
|
||||
command: "echo after-tool"
|
||||
SessionStart:
|
||||
- type: command
|
||||
command: "echo session-started"
|
||||
mcpServers:
|
||||
- name: my-grafana
|
||||
fromTemplate: grafana
|
||||
project: monitoring
|
||||
postInstall: scripts/install.sh
|
||||
preUninstall: scripts/cleanup.sh
|
||||
postInstallTimeoutSec: 60
|
||||
```
|
||||
|
||||
**v1 sync executes none of these — they're stored verbatim and
|
||||
materialisation is deferred to a follow-up.** Once enabled:
|
||||
|
||||
- `hooks` will be written into `~/.claude/settings.json` with
|
||||
`_mcpctl_managed: true` markers (see Project Setup above for how
|
||||
the SessionStart hook works today).
|
||||
- `mcpServers` will be auto-attached via the mcpd attach API.
|
||||
- `postInstall` will run as the user with a curated env, hard timeout,
|
||||
and an audit event emitted back to mcpd. Hash-pinned: re-syncs of
|
||||
unchanged scripts won't re-execute.
|
||||
|
||||
## State
|
||||
|
||||
`~/.mcpctl/skills-state.json` tracks the last-synced state:
|
||||
|
||||
- per-skill: `id`, `semver`, `contentHash` (matches mcpd's hash),
|
||||
`installDir`, per-file `sha256` + size, `postInstallHash`,
|
||||
`lastSyncedAt`.
|
||||
- top-level: `lastSync`, `lastSyncProject`, `schemaVersion`.
|
||||
|
||||
The state file is written atomically (temp + rename). Per-file SHA-256
|
||||
detects local edits — sync warns and skips modified files unless you
|
||||
pass `--force`.
|
||||
|
||||
State lives outside `~/.claude/skills/` deliberately so Claude Code
|
||||
doesn't see our bookkeeping in its tree.
|
||||
|
||||
## Atomic install
|
||||
|
||||
Each skill is staged under `<targetDir>.mcpctl-staging-<pid>/`, then
|
||||
the existing directory (if any) is renamed to
|
||||
`<targetDir>.mcpctl-trash-<pid>`, the staging dir is moved into place,
|
||||
and the trash is rmtree'd. A concurrent reader (Claude Code starting up)
|
||||
never sees a partial tree.
|
||||
|
||||
Symmetric atomic delete for orphan removal: rename to trash, rmtree.
|
||||
Locally-modified skills are preserved (warned + skipped) unless `--force`.
|
||||
|
||||
## Failure semantics
|
||||
|
||||
| Situation | Exit code | Behaviour |
|
||||
|----------------------------------|-----------|------------------------------------|
|
||||
| Network/timeout in `--quiet` | 0 | Skip silently. SessionStart hook never blocks Claude. |
|
||||
| Auth failure | 1 | "run mcpctl login" message. |
|
||||
| Disk full / state save failure | 2 | Loud error. |
|
||||
| Per-skill error | 0 | Logged in result errors[]; sync continues. |
|
||||
|
||||
The fail-open behaviour in `--quiet` is non-negotiable — a hung mcpd
|
||||
must never block Claude Code starting up.
|
||||
|
||||
## Future
|
||||
|
||||
The following are deferred to follow-up PRs:
|
||||
|
||||
- `metadata.hooks` materialisation into `~/.claude/settings.json`
|
||||
- `metadata.mcpServers` auto-attach
|
||||
- `metadata.postInstall` execution with curated env + audit emission
|
||||
- Agent-scoped skills synced to disk (would need an agent-identity-on-
|
||||
disk concept that doesn't exist yet)
|
||||
- Bundle backup support for skills (bundle-backup is one path; git-backup
|
||||
is the other and is wired today)
|
||||
- `mcpctl apply -f skill.yaml` declarative skill apply
|
||||
Reference in New Issue
Block a user