Skip to content
Back to skills

Create Voyager Plugin

ASecurity

Create or change a Voyager declarative plugin, site adapter, or native primitive.

  • 20,307 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 21, 2026
ai-agentstestinggit

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned September 21, 2026

npx -y skills add Nagi-ovo/voyager --skill create-voyager-plugin --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Create Voyager Plugin?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Create Voyager Plugin
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/nagi-ovo-create-voyager-plugin/badge)](https://www.skillsdirectory.com/skills/nagi-ovo-create-voyager-plugin)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: create-voyager-plugin
description: Create or change a Voyager declarative plugin, site adapter, or native primitive.
metadata:
  version: '1.2.0'
---

# Create a Voyager plugin

## Select the path

Read only the matching implementation reference. Paths are relative to `src/features/plugins/`.

| Change                                                 | Reference                                       | Distribution                                                            |
| ------------------------------------------------------ | ----------------------------------------------- | ----------------------------------------------------------------------- |
| CSS/JSON plugin using DOM ops or an existing primitive | [Declarative plugin](references/declarative.md) | `catalog/sites/<site>/plugins/<id>/`; bundled and remote                |
| Site selectors, theme, URL matching or a new site      | [Site adapter](references/site-adapter.md)      | `catalog/sites/<site>/site.json`; existing-site updates travel remotely |
| Behavior needing events, state or generated DOM        | [Native primitive](references/primitive.md)     | `verbs/`; packaged executable code, requires an extension release       |

A new site also requires host permission and content-script registration in an extension release. A primitive needs a declarative plugin that invokes it, so read that reference too when adding the caller.

New features follow `.github/CONTRIBUTING.md`; a new primitive or site requires explicit maintainer approval of the approach. Reuse a direct maintainer instruction in the current task as approval; loading this skill grants none. A selector fix within an existing site's approved scope needs no new feature approval.

For architecture or distribution changes, read `src/features/plugins/README.md` and `.github/docs/PLUGIN_DISTRIBUTION_PLAN.md`. PR preparation uses `voyager-contribute`; live checks use `verify-in-browser` (Safari loading uses `update-safari-extension`).

## Shared constraints

- Every injected class is `gv-` prefixed; plugin-scoped classes are
  `gv-plugin-<site>-<id>`. Nothing leaks to the host page unscoped.
- No remote resources in CSS: no `@import`, no `http(s)://` or protocol-relative
  `url()`. `data:` URIs are fine. `validateStyleCss` rejects the rest.
- Prefer a semantic key over a raw selector:
  `{ "kind": "semantic", "key": "userTurn" }`. Raw selectors are for what the
  vocabulary cannot name, and they are the first thing to break on a redesign.
- A plugin's `matches` stays inside its site's `matches` (D18).
  `catalog:build` fails otherwise. Patterns are read as Chrome reads them:
  `*.example.com` needs a subdomain (the apex host is outside it) and `*://`
  means http or https only; the build and the runtime agree, so a pattern that
  passes the build also resolves a site.
- `conversationIdPattern`, in `site.json` or as a `turnNavigator` param, is a
  plain anchored capture such as `^/c/([^/?#]+)`: no lookarounds or
  backreferences, no repeated group that holds a quantifier or `|`, at most
  eight quantifiers and 200 characters. It runs on the page's main thread
  against every URL, so the gate (`sites/safeRegex.ts`) refuses anything that
  can backtrack.
- `requires.handlers` lists every primitive the plugin invokes, and `engine`'s
  minimum is at least each primitive's `sinceEngine`. That ordering is the
  point: an old build then says "update Voyager" (`needs-engine`) instead of
  `needs-handler`, which is left meaning a real configuration mistake.
- Ten locales. English lives in the top-level `name` / `description`; the other
  nine sit under `i18n.<locale>` with `name`, `description`, `changelog` when
  set, and a label for every setting.
- `marketplace.json` gets the entry, and the plugin directory gets a `README.md`
  next to the manifest. A test enforces both.
- `params` is configuration, not instructions (plan §5, C1): no conditions, no
  ordering, no code. A selector-valued parameter such as `yieldWhen` is still
  data, so do not reject one on its name.
- Themes come from the site, not from guesswork: `site.json`'s `theme` block
  records the host, light and dark selectors. Check both. That block is the
  **only** place a host's own dark-mode dialect is ever named:
  `pages/content/platformTheme/scheme.ts` resolves it once and stamps
  `html[data-gv-scheme='light'|'dark']` plus `html[data-gv-platform='<siteId>']`.
- So scope every light/dark rule — in plugin CSS and in `contentStyle.css` — with
  `html[data-gv-scheme='…']`, never with the host's class (`html.dark`,
  `body.dark-theme`, `:root:not(.dark)`). Get `theme` right and a new site
  inherits every existing Voyager surface with no theme CSS of its own.
  `contentStyleTheme.test.ts` fails on a host dialect that slips back in.
- Accent likewise: `brandColor` in `site.json` (or a plugin's `theme.brand`)
  becomes `--gv-pm-brand`, `--gv-pm-brand-fg` and `--gv-pm-brand-h` on the root.
  Voyager UI that should carry the site's colour reads
  `oklch(L C var(--gv-pm-brand-h, var(--gv-pm-brand-h-default)))`, never a
  literal — a hard-coded hue is how the Vim HUD stayed Gemini green on DeepSeek.
  A rule for one platform only keys off `html[data-gv-platform='<id>']`;
  `gv-platform-themed` means "some brand applies" and three sites share it.
- Never hand-edit `dist_*` or `docs/public/catalog`; `catalog:build` writes the
  published catalog.

## Verification and completion

Use the selected path's validators and focused tests during implementation. Before a code PR, run `bun run verify:pr` on the final tree per `AGENTS.md`; reuse covered results for unchanged inputs. Run `catalog:build` for catalog/contract changes and inspect its generated diff. Keep the evidence tied to the final changed files; later relevant edits invalidate it.

The PR needs:

- A screenshot or recording on a real conversation in both light and dark themes. Record the site and approximate conversation length; redact conversation/account details from shared evidence.
- The submitted directory's `plugin:check` output and the target selector match count, measured in the page (for example `document.querySelectorAll('<selector>').length`). For pure CSS without countable targets, use visible before/after evidence.
- For a primitive, passing contract tests and parametric tests against two sites' fixtures.

Confirm the intended extension/catalog version is loaded before collecting evidence. A plugin target count of zero while the adapter's `userTurn` matches is the `no-effect` failure (`runtime/healthMonitor.ts`, design D12); investigate missing selectors. Pure-CSS plugins are not tracked by this counter.

Complete when the selected path's requirements pass and a reviewer can see the real behavior in both themes. Apply the affected-browser requirements in [browser-testing.md](../voyager-contribute/references/browser-testing.md) when preparing a contribution. If coverage is unavailable, report the gap and owner; it remains pending.

Files in this skill

  • SKILL.md6.9 KB
  • references/declarative.md2.3 KB
  • references/primitive.md2.8 KB
  • references/site-adapter.md2.4 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…