84 lines
5.4 KiB
Markdown
84 lines
5.4 KiB
Markdown
# mattpocock-skills-opencode
|
|
|
|
OpenCode v2 integration for the [Matt Pocock skills](https://github.com/mattpocock/skills) ecosystem.
|
|
Upstream is the source of truth for the methodology; OpenCode v2 is the source of truth for execution
|
|
architecture. We translate, never copy Claude Code's plugin architecture.
|
|
|
|
## Session start protocol (long-running project)
|
|
|
|
1. `git status` + current branch — never destroy uncommitted work.
|
|
2. Read `TODO.md` — the persistent task list.
|
|
3. Read `.opencode/state/status.md` — current phase and last completed work.
|
|
4. Read `.opencode/state/decisions.md` — binding decisions; don't re-litigate them without new evidence.
|
|
5. Read `.opencode/state/upstream.json` — last synchronized upstream revision.
|
|
6. Pick the highest-value unfinished task from `TODO.md` and continue.
|
|
|
|
Before context runs low: update `status.md` + `TODO.md`, record failures and exact next steps, commit
|
|
safe intermediate work.
|
|
|
|
## Layout
|
|
|
|
- `upstream/` — pristine vendored snapshot of mattpocock/skills (`skills/` subtree). **Never hand-edit.**
|
|
Updated only by `scripts/sync-upstream.ts`.
|
|
- `skills/` — generated OpenCode skill tree + `manifest.json` (output of `scripts/generate.ts`). Hand-edit
|
|
only the overlay inputs under `overlay/`, never the output.
|
|
- `agents/` — generated OpenCode v2 agent markdown files. Edit templates in `agent-templates/`, then regenerate.
|
|
- `.opencode/state/` — machine- and human-readable project state (upstream revision, classification, status).
|
|
- `docs/architecture.md` — the design. `docs/skill-mapping.md` — per-skill classification record (generated
|
|
from `.opencode/state/classification.json`).
|
|
- `scripts/` — sync, generate, release (Gitea npm registry publish without `npm publish`), smoke.
|
|
- `test/` — `node --test` on TypeScript sources directly (Node ≥ 22.18 type stripping, like the reference repo).
|
|
|
|
## Conventions
|
|
|
|
- TypeScript ESM, `type: module`, prettier (`semi: false`, `printWidth: 100`), `tsc --noEmit` gate.
|
|
- Generated agent frontmatter uses **V2-native fields only**: `mode`, `description`, `model`
|
|
(`provider/model#variant`), `permissions` (array of `{action, resource, effect}`), `steps`, `hidden`,
|
|
`request` (sparingly — body overlays are not sent by the runner yet). Never `prompt`, `permission`,
|
|
`tools`, `disable`, `maxSteps`, `temperature` at top level.
|
|
- Commits: `sync:`, `feat:`, `fix:`, `test:`, `chore:`, `docs:` — logically separated, conventional style.
|
|
- Versioning: semver; `CHANGELOG.md` `## [x.y.z]` headings are the release source of truth
|
|
(fastcrw pattern). Upstream revision tracked separately in state + changelog entries.
|
|
- Registry credentials only from Gitea Action secrets (`PACKAGE_TOKEN`). Never commit them.
|
|
|
|
## Key V2 facts this repo relies on (verified 2026-10-14 against opencode docs/source)
|
|
|
|
- Plugins: `Plugin.define({ id, setup(ctx) })` from `@opencode/plugin`; config key `plugins`;
|
|
npm package needs `type: module` + `exports["."]`.
|
|
- `ctx.skill.transform(editor)` **can add** skills programmatically. `Skill.Info` (verified in
|
|
`@opencode/plugin@2.0.29` typings) = `{ id, name, description?, autoinvoke?, path, content }` —
|
|
`path` must be absolute (we point it at the bundled SKILL.md so supporting files resolve); there is
|
|
**no `slash` field** in `Skill.Info` (slash is file-frontmatter only — verify `/name` exposure for
|
|
injected skills at runtime; fallback: document a `skills: ["<pkg>/skills"]` config entry).
|
|
`ctx.agent.transform(editor)` **cannot add** agents — only list/get/update/remove/default. Hence:
|
|
skills ship via plugin injection, agents via `init` copy.
|
|
- `Agent.Info` (verified): `{ id, name, mode: subagent|primary|all, description?, model?, system?,
|
|
hidden, color?, steps?, request{settings,headers,body}, permissions[{action,resource,effect}] }`.
|
|
- Skills frontmatter honored: `name`, `description`, `slash`, `disable-model-invocation` /
|
|
`metadata.opencode/autoinvoke` (hidden from model, still loadable by id/slash).
|
|
- Agent files: `.opencode/agents/<name>.md` (project), `~/.config/opencode/agents/` (global);
|
|
frontmatter = agent config, body = system prompt.
|
|
- Permission rules are ordered, last match wins; per-agent skill restrictions via
|
|
`{action: "skill", resource: "<pattern>", effect: ...}`. V2 actions include `shell`, `edit`,
|
|
`read`/`glob`/`grep`, `webfetch`, `skill`, `subagent`, `external_directory`; no rule → ask.
|
|
- Runtime-verified on v2.0.29 (see docs/runtime-checks.md): local plugin entries must be
|
|
DIRECTORIES (file entries ignored); `/api/skill` omits `autoinvoke` when true; injected skills
|
|
get no slash commands (file-based only); default rules already allow `external_directory /tmp/*`;
|
|
injected content must have frontmatter stripped; serve prints its Basic-auth password.
|
|
- Agent `steps` replaces `maxSteps`; `temperature`/`top_p` go under `request.body` (not yet sent by
|
|
the runner — avoid).
|
|
|
|
## Agent skills
|
|
|
|
### Issue tracker
|
|
|
|
Issues live in this repo's Gitea Issues (`git.arthurerlich.de`), driven via the `tea` CLI; relations are body conventions (`Part of #`, `Blocked by:`) since Gitea has no sub-issues. See `docs/agents/issue-tracker.md`.
|
|
|
|
### Triage labels
|
|
|
|
Default five-role vocabulary (`needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`, `wontfix`), label strings equal to role names. See `docs/agents/triage-labels.md`.
|
|
|
|
### Domain docs
|
|
|
|
Single-context: one `GLOSSARY.md` + `docs/adr/` at the repo root. See `docs/agents/domain.md`.
|