JSPM

  • Created
  • Published
  • Downloads 786
  • Score
    100M100P100Q114503F
  • License ISC

OpenCode plugin for opencode-wizard published skills

Package Exports

  • @aexol/opencode-wizard/server
  • @aexol/opencode-wizard/tui

Readme

@aexol/opencode-wizard

@aexol/opencode-wizard is a separately releasable OpenCode and Pi plugin package for fetching published skills from the opencode-wizard backend runtime and surfacing plugin status in OpenCode/Pi hosts.

Package target

  • oc-plugin: ["server", "tui"]
  • ./serverdist/server.js
  • ./tuidist/tui.js
  • pi.extensions: ["./dist/pi.js"]
  • ./pidist/pi.js
  • no generated runtime skill directory is published; the plugin stays fetch-only at runtime
  • native OpenCode skills.urls is treated as a public/static registry complement, not as the private wizard delivery authority
  • the TUI is a compact status panel: it shows backend URL, signed-in identity, role, and catalog counts while mutations still run through guarded tools

Local development

This monorepo still path-loads the same package from ./plugins/opencode-wizard during local OpenCode development.

Compatibility smoke target: OpenCode 1.17.3 with @opencode-ai/plugin ^1.17.3 and OpenTUI @opentui/{core,keymap,solid} ^0.3.4; restart both OpenCode server and TUI after dependency or plugin entrypoint changes.

Backend origin resolution defaults to the deployed backend at https://opencode-wizard.aexol.work for both local path-loaded and packaged plugin usage. Set OPENCODE_WIZARD_BACKEND_ORIGIN explicitly to target a local/backend URL. Generic host APP_URL and PORT are ignored so released plugin usage does not accidentally target placeholder app URLs or the OpenCode host port.

Useful commands:

npm run typecheck
npm run test
npm run build
npm run release:check
npm pack --dry-run

Published package usage

OpenCode server/plugin host can install the published package by package name instead of a repo-local path:

{
  "plugin": ["@aexol/opencode-wizard@latest"]
}

For repo-local development, continue using the local path-based config already documented in this repository.

Pi package usage

The same npm package can be loaded by Pi as a native Pi package/plugin; it does not use MCP and does not duplicate degraded static catalog stubs.

pi install -l ./plugins/opencode-wizard
# or use the published package when available:
pi install @aexol/opencode-wizard@latest

Pi loads the pi.extensions entrypoint at ./dist/pi.js, registers Pi-native tools, and bridges them to the same real backend/client/runtime handlers used by the OpenCode server plugin:

  • wizard_statusopencode_wizard_status
  • wizard_catalog_fetchopencode_wizard_catalog_fetch
  • wizard_artifact_fetchopencode_wizard_artifact_fetch
  • wizard_artifact_preference_setopencode_wizard_artifact_preference_set
  • wizard_published_skills_fetchopencode_wizard_published_skills_fetch
  • wizard_published_skill_preference_setopencode_wizard_published_skill_preference_set
  • wizard_report_issueopencode_wizard_report_issue
  • editor-only tools include wizard_initopencode_wizard_init and wizard_updateopencode_wizard_update

The Pi before_agent_start hook calls the same runtime system-note path as OpenCode, so dynamic prompt context comes from real backend catalog/status resolution when auth and catalog fetches succeed. Missing auth, forbidden role, backend, or catalog failures are returned as explicit operational states by the existing wizard runtime; no tokens are exposed.

Pi usage has the same backend configuration and auth prerequisites as OpenCode usage: the backend origin defaults to https://opencode-wizard.aexol.work, OPENCODE_WIZARD_BACKEND_ORIGIN can override it, and plugin session auth is stored in ~/.config/opencode/opencode-wizard.json.

Native skills.urls compatibility

OpenCode's native skills.urls support downloads public/static skill registries from base URLs that expose an index.json and file paths under that base URL. Current support has no plugin session/header integration, so it must not be pointed at private opencode-wizard skill delivery.

Use skills.urls only for public registries that are intentionally cacheable by OpenCode. Private workspace-scoped wizard artifacts remain authenticated and directory-scoped through opencode_wizard_artifact_fetch or compatibility opencode_wizard_published_skills_fetch; same-named native/local seed skill bodies are not authoritative for wizard-listed skills.

Catalog discovery and auth bootstrap

Catalog discovery uses the backend-issued plugin session token stored at ~/.config/opencode/opencode-wizard.json (auth field); the plugin does not persist or send Microsoft/Entra tokens to GraphQL. If no valid plugin session exists, no-arg opencode_wizard_catalog_fetch, opencode_wizard_artifact_fetch, compatibility no-arg opencode_wizard_published_skills_fetch, and explicit opencode_wizard_status may start the browser Entra PKCE flow and exchange the callback for a fresh backend-issued plugin session. Chat/system-context startup is passive: it reports degraded auth and points to those explicit tools instead of starting browser login. The TUI panel displays the resulting backend URL, auth identity, role, and catalog counts from that status payload.

The shared plugin tools opencode_wizard_catalog_fetch, opencode_wizard_artifact_fetch, opencode_wizard_artifact_preference_set, compatibility published-skill tools, opencode_wizard_status, and opencode_wizard_report_issue are always exposed by the plugin. Missing auth, forbidden role, backend, or catalog/report problems are reported by tool output/status metadata instead of hiding these shared tools; opencode_wizard_editor_create_or_update_skill, opencode_wizard_editor_publish_skill, opencode_wizard_artifact_import, opencode_wizard_editor_list_reports, opencode_wizard_editor_update_report, opencode_wizard_init, and opencode_wizard_update stay editor-only.

Use opencode_wizard_report_issue for authenticated Wizard BUG/FEATURE reports. Required args are reportType (BUG or FEATURE), title, and description; optional safe fields include severity/priority, reproduction steps, expected/actual behavior, impact, labels, related tool, directory override, and a repo-relative path. The tool sends source: OPENCODE, safe workspace/repository/directory context, and bounded metadata only; it does not capture transcripts, prompts, env, secrets, tokens, raw logs, or unbounded local absolute paths.

Use opencode_wizard_editor_list_reports from ADMIN/EDITOR sessions to read Wizard BUG/FEATURE reports through the backend admin.bugFeatureReports API without browser UI login. It defaults to BUG, accepts optional reportType/kind, status, priority, source, page, pageSize, and directory, and returns bounded report previews plus pagination and workspace-resolution metadata without exposing tokens, metadata blobs, or unbounded local paths.

Call opencode_wizard_catalog_fetch with artifactKind: SKILL, opencode_wizard_artifact_fetch with artifact identifiers, or compatibility opencode_wizard_published_skills_fetch without skill or skills to manually bootstrap plugin login if needed and return scoped artifact/skill output for the current directory scope.

Canonical artifact discovery/fetch uses generic wizard artifact persistence for both SKILL and DESIGN_DOC: catalogs return metadata only, and explicit detail fetches return SKILL.md or DESIGN.md body/files for effective assignments. Compatibility opencode_wizard_published_skills_fetch keeps the legacy published-skill payload shape for legacy skills. Use the fetched markdownDocument/markdownBody as the authoritative wizard skill body before applying a wizard-listed skill.

Workspace delivery still follows the backend contract: the plugin sends workspaceSlug when it has one, otherwise falls back to repositoryUrl. The plugin now prefers configured or learned workspace slug mappings over a repo-basename fallback, and learns durable slug-to-repo mappings from successful backend catalog responses so worktrees and nontrivial repo roots stay aligned.

Published skill fetches still support refresh: true, but normal cache entries now self-expire after 30 seconds and fetch/status payloads surface source, workspaceSlug, and workspaceSlugSource so stale-vs-refreshed behavior is visible without relying on manual cache deletion. Try refresh: true and report the tool-output auth/catalog/source/cache/workspace-resolution state before deleting ~/.cache/opencode/*.

Use canonical opencode_wizard_artifact_preference_set for generic SKILL/DESIGN_DOC preference actions (install, uninstall, ignore, unignore); compatibility opencode_wizard_published_skill_preference_set remains for legacy skills and falls back to generic SKILL artifacts when no legacy match exists. The TUI panel stays read-only and does not run preference mutations directly.

EDITOR skill creation flow

For new or updated skills, the canonical plugin path is direct markdown creation:

  1. Draft the complete SKILL.md markdown content in chat or another editor.
  2. Call opencode_wizard_editor_create_or_update_skill with markdownContent and optional directory.
  3. Use opencode_wizard_artifact_fetch with artifactKind: "SKILL" or compatibility opencode_wizard_published_skills_fetch to verify the backend-published body that became runtime authority.

Keep opencode_wizard_editor_publish_skill for the legacy seed-file flow when .opencode/skills/<slug>/SKILL.md already exists locally. Keep opencode_wizard_artifact_import for external SKILL/DESIGN_DOC sources such as GitHub skill repos or npx getdesign@latest add ... inputs. EDITOR role is checked both when exposing these tools and again at execution time.

Editors can import external artifacts without writing project files via opencode_wizard_artifact_import: use source: "npx getdesign@latest add bmw-m" for a DESIGN_DOC, or source: "https://github.com/vercel-labs/agent-skills --skill react-best-practices" for a SKILL. The plugin import path is a command/raw-source bridge into generic backend artifact persistence: it fetches markdown or a zip-backed SKILL.md/README.md, sends it to the backend import mutation, records the importing editor in existing created/published actor fields plus source metadata, and imports as a production runtime artifact. By default it also requests a workspace/path assignment for the current directory; pass assignmentScope: "user" or "none" to skip assignment and use preference/assignment tools later. The admin Skills Catalog UI can browse Vercel, Skillta, and Design Docs sources and unzip archives in the browser; the plugin keeps generic artifact tool naming because the same backend artifact flow supports both SKILL and DESIGN_DOC.

GLOBAL_CONTEXT skills are active context skills and are not meant to be installed per project. PROJECT_INSTALLABLE skills are gallery/installable skills that may be attached globally or to a workspace/path through assignment records; those assignments remain the source of truth for what is active in a catalog response.

EDITOR workspace init flow

Use opencode_wizard_init to bootstrap a repository workspace without reading project instruction files:

  1. Call without confirm to get a non-mutating preview with detected git root/remote/directory, suggested workspace name/slug, ACTIVE PROJECT_INSTALLABLE skills, selected/missing skills, questionBlock, and a suggested follow-up call.
  2. Choose skillSlugs or set assignAllSkills: true; if no skills are selected, even confirm: true returns needs_input and does not mutate.
  3. Rerun with confirm: true to create or resolve the workspace, persist the repo-to-workspace slug mapping, and bulk assign selected skills as ACTIVE PATH assignments using scopePath (default current directory path) and includeChildren (default true).

Pi exposes the same flow as wizard_init.

EDITOR workspace update flow

Use opencode_wizard_update after init to reconcile an existing workspace without destructive changes:

  1. Call without confirm to resolve the existing workspace by slug/learned mapping/repository URL and preview current matching skills, missing assignable skills, unavailable assignments, different-scope assignments, questionBlock, and a suggested follow-up call.
  2. Choose missing additions with skillSlugs or set assignAllSkills: true; if nothing new is selected, even confirm: true returns no_changes/needs_input and does not mutate.
  3. Rerun with confirm: true to add only selected missing ACTIVE PROJECT_INSTALLABLE skills as ACTIVE PATH assignments for scopePath and includeChildren; existing assignments are never removed or deactivated.

If no existing workspace resolves, the tool returns needs_init and points the caller to opencode_wizard_init. Pi exposes the same flow as wizard_update.

Release flow

  1. Bump version in plugins/opencode-wizard/package.json.
  2. Run npm run plugin:release:check from the repo root.
  3. If you are following the repo release-tag convention, create Git tag plugin-opencode-wizard-v<version>.
  4. Push the release commit/tag so GitLab can run the shared npm public publish job.

The CI publish job comes from ci/templates/node/npm-publish-public.yml, stays manual on the repo deploy stage, runs from plugins/opencode-wizard via APP_ROOT, runs npm run release:check including npm pack --dry-run, deletes the inherited @aexol GitLab registry override, packs the exact release tarball with npm pack, and publishes that tarball with npm publish --provenance --access public --registry https://registry.npmjs.org/ ./*.tgz.

GitLab provides a SIGSTORE_ID_TOKEN (aud: sigstore) for npm provenance, and the packed *.tgz is retained as a 30-day job artifact. The current flow still requires the existing NPM_AUTH_TOKEN; npm trusted publishing for GitLab would be the stronger future option once configured because it can remove the long-lived npm token. After release, npm audit signatures from a throwaway install is an optional registry verification check.