Skip to content

RFD 0007: Plugin migration from v1 skills

Summary

v1 ships 78 skills (21 language guides, 30 framework guides, 19 Samuel-original workflows, 7 Anthropic community workflows, 1 commit-message) embedded in the framework binary. v2 migrates them to per-plugin Git repos under github.com/samuelpkg/samuel-*, indexed by a separate samuel-registry repo, with a samuel-starter meta-plugin that auto-installs the 12 Samuel-Way workflows on samuel init.

The migration is mostly mechanical (scripted), with manual review for edge cases. Four skills become built-in v2 framework features instead of plugins (autoralph methodology; create-skillsamuel skill create command content; sync-claude-md + generate-agents-mdsamuel sync command content). Two skills drop entirely (initialize-project and update-framework are replaced by samuel init and samuel update).

Plus: two translator plugins ship at v2.0 launch (claude-translator, codex-translator) to prove the agnostic-by-design story and validate the WASM plugin tier with real usage.

Problem statement

After [[0001|RFD 0001]] (plugin format), [[0003|RFD 0003]] (manifest schema + signing), and [[0005|RFD 0005]] (plugin loader), v2 has the mechanism to load plugins. What it lacks is plugins. samuel install go-guide would fail at v2.0 launch because no go-guide plugin exists.

v1's 78 skills represent significant accumulated content — language guides, framework patterns, workflow methodologies. Discarding them and asking the community to rewrite from scratch would lose months of work and break the v1 → v2 narrative.

The work is mechanical but high-volume:

  • 78 skills → 78 plugin repos
  • 1 registry repo with 85 entries (78 ports + 7 Anthropic community via subpath)
  • 1 meta-plugin (samuel-starter) depending on 12 of the 78
  • 2 translator plugins (claude-translator, codex-translator)
  • 1 reusable release workflow (consumed by every plugin repo)

= 83+ artifacts produced from one migration milestone.

Requirements

  • Every v1 skill that survives ([[../../wiki/sources/2026-05-12-v1-skill-content-survey]]) has a corresponding v2 plugin at v2.0 launch.
  • Plugin manifests are auto-generated from v1's SKILL.md frontmatter where possible.
  • The migration is scriptable — running it twice produces the same output (idempotent).
  • Each plugin repo has its own release workflow (using the reusable workflow from [[0003|RFD 0003]]) so updates flow naturally per-plugin.
  • The registry's index.toml is the single source of truth for "which plugins exist and what's their latest version."
  • samuel install resolves names against the registry transparently.
  • Smoke test passes: clean samuel init → starter pack installs 12 plugins → manually install go-guide + react + claude-translator → run samuel run → everything works.

Constraints

  • The 78 plugin repos can't all be force-pushed in one operation — GitHub rate-limits API operations.
  • Some v1 skills have metadata.author: anthropic and live upstream at github.com/anthropics/skills. These are not forked; the registry references them by subpath.
  • v2.0 must launch with both translator plugins functional, or the agnostic-by-design story is theoretical.

Background

v1 skill triage (recap from [[../../wiki/sources/2026-05-12-v1-skill-content-survey]])

Four buckets for the 78 skills:

  1. Built into v2 framework (4): auto becomes the ralph methodology in framework code; create-skill becomes content of the samuel skill create command; sync-claude-md + generate-agents-md collapse into samuel sync (AGENTS.md-only per [[0002|RFD 0002]]).

  2. Starter-pack plugins (12): the Samuel-Way workflows that get auto-installed by samuel init. Aggregated into the samuel-starter meta-plugin. The list: create-rfd, create-prd, generate-tasks, code-review, commit-message, document-work, refactoring, security-audit, testing-strategy, troubleshooting, cleanup-project, dependency-update.

  3. Pure plugins (58): all language guides (21) + framework guides (30) + Anthropic community (7). Installable on demand. Not auto-installed.

  4. Drop (2): initialize-project (replaced by samuel init); update-framework (replaced by samuel update).

Plus two new plugins (not from v1): claude-translator (WASM) and codex-translator (WASM).

Why one repo per plugin

Three viable repository structures were considered ([[../../wiki/synthesis/v2-skill-migration-plan]]):

  1. One repo per plugingithub.com/samuelpkg/samuel-go-guide, samuel-react, etc.
  2. Monorepo with subpathsgithub.com/samuelpkg/samuel-plugins/<name>/.
  3. Hybrid — official plugins in monorepo, community in own repos.

The user-confirmed decision (after weighing during wiki discussion) is Option 1 (one repo per plugin) with org github.com/ar4mirez/* initially. Reasons: standard ecosystem pattern (npm packages, cargo crates), per-plugin versioning + issues + PRs + release cadence, easier for community plugins to follow the pattern. Migration to a dedicated github.com/samuel-plugins/* org deferred for later if community grows.

Options considered

Option A: One repo per plugin, single org, migration script, reusable release workflow (chosen)

Bulk-create 78 repos under github.com/samuelpkg/samuel-* via a one-time migration script. Each repo uses the reusable release workflow from [[0003|RFD 0003]] for builds + signing. A separate samuel-registry repo with index.toml indexes them.

Pros: - Per-plugin versioning, issues, PRs, release notes. - Maps to standard ecosystem mental models (npm packages, cargo crates). - Plugin authors copy this pattern when writing their own plugins. - The registry is one small file, easy to audit and PR. - The reusable release workflow keeps each plugin repo's .github/workflows/release.yml to ~10 lines.

Cons: - 78 repos to bulk-create. GitHub API rate limits push back; needs sequencing. - 78 repos to maintain. Inactive ones accumulate. - Per-plugin CI minutes (small for public repos but non-zero).

Effort: 4-5 days (scripted migration). Plus a few hours of manual review on edge-case skills with non-standard frontmatter.

Option B: Monorepo with subpaths

All plugins live in github.com/samuelpkg/samuel-plugins/<plugin-name>/. One repo, many plugins.

Pros: - One place to PR multiple plugins at once. - Less repository bloat in the org. - Migration script is simpler (one repo init, populate, push).

Cons: - Versioning is awkward — one tag per plugin (go-guide-v1.0.0)? Tags per global release? Either is unconventional. - Per-plugin issues become labeled / projected onto a monorepo issue tracker. - Doesn't match how community plugins will be published (one repo each). - Migration to one-repo-per-plugin later is harder than starting that way.

Effort: Lower (one repo). But long-term cost is higher.

Option C: Hybrid — official plugins in monorepo, community in own repos

The 78 ports live in a monorepo; future community plugins live in their own repos.

Pros: - Compromise — easier migration, conventional community pattern.

Cons: - Two structures to support in the registry resolver. - Confusing for plugin authors: "Why is go-guide in a monorepo but my new plugin is its own repo?" - Cargo / npm / pip / Maven all use one-pattern-everywhere.

Effort: Same as Option B for migration; ongoing complexity for the registry.

Option D: No migration

Start v2 with no plugins. Let the community rebuild plugins as they need them.

Pros: - Zero migration work. - v2 launches as a "pure" framework with no opinionated content.

Cons: - v2.0 launch is functional-but-empty. No language guides, no framework guides, no workflows. - Loses months of v1 content investment. - Community is small enough that "let the community rebuild" means "rebuilds happen slowly or never." - Breaks the v1 → v2 narrative ("here's the upgrade") into "here's a different product."

Effort: Zero migration; high opportunity cost.

Decision

Adopt Option A: one repo per plugin, single org (github.com/samuelpkg/samuel-*), scripted migration, reusable release workflow, separate samuel-registry repo.

The decision rests on three judgments:

  1. The 78 SKILL.md files are real preservable value. Each one is high-quality, multi-paragraph content with concrete guardrails. Throwing them away would force users to rebuild — slow, error-prone, contrary to the v1 → v2 upgrade narrative.

  2. One-repo-per-plugin matches ecosystem norms. Cargo, npm, pip, Maven all use it. Plugin authors writing the next plugin copy the pattern. Inconsistency (Option C) creates ongoing complexity.

  3. The migration is mechanical and scriptable. 78 repos sounds like a lot, but the script handles 95% of cases identically. Manual review for the 5% takes hours, not days.

Implementation plan

Phase 1 — migration script (PRD 0005, days 1-2)

scripts/migrate-v1-skills.go — one-time tool, deleted after migration. Takes samuel_v1/.claude/skills/ as input, produces migration-output/samuel-<name>/ per skill.

For each skill directory:

  1. Parse SKILL.md frontmatter (YAML).
  2. Generate samuel-plugin.toml:
  3. name from frontmatter
  4. version = "1.0.0" (clean baseline at migration time)
  5. kind = "skill" (almost all v1 skills are pure text; the few with scripts/ are still skills because they don't currently execute)
  6. samuel.framework = "^2.0.0"
  7. samuel.protocol = "^1.0.0"
  8. provides.skills = [name]
  9. capabilities.filesystem.read = ["/workspace"] (default for pure-text skills)
  10. metadata.category from v1 frontmatter (language / framework / workflow)
  11. metadata.language and metadata.extensions from v1 frontmatter (drives auto-load)
  12. metadata.description from v1 frontmatter (first line of description)
  13. Copy SKILL.md unchanged.
  14. Copy scripts/, references/, assets/ if present.
  15. Generate README.md from the manifest (description, install command, link to upstream).
  16. Generate LICENSE (MIT).
  17. Generate .github/workflows/release.yml that uses the reusable workflow from [[0003|RFD 0003]].
  18. git init, commit, tag v1.0.0.

The script has a --dry-run mode that prints what would happen. Idempotent — re-running updates existing repos without failing.

Phase 2 — bulk repo creation + push (PRD 0005, day 3)

For each migration-output/samuel-<name>/:

  1. Create the GitHub repo via API: gh repo create samuelpkg/samuel-<name> --public --description "<desc>".
  2. Add the local repo as a remote: git remote add origin git@github.com:samuelpkg/samuel-<name>.git.
  3. Push: git push -u origin main.
  4. Push tag: git push origin v1.0.0 (triggers release workflow → cosign signing → GitHub release with signed artifacts).

Rate-limit: do this in batches of 10-15 with sleeps to avoid GitHub's secondary rate limits. ~30-45 minutes for all 76 (78 minus the 4 that became built-in minus the 2 dropped).

Phase 3 — registry repo (PRD 0005, day 4)

Create github.com/samuelpkg/samuel-registry:

samuel-registry/
├── index.toml                      # the canonical index
├── README.md
├── CONTRIBUTING.md                 # how to add a plugin to the registry
└── .github/workflows/validate.yml  # CI: validate index.toml schema + resolve repos + check tags

The index.toml is generated from the migration script output. Schema per [[0001|RFD 0001]] and [[0003|RFD 0003]]:

schema_version = 1

[plugin.go-guide]
repo = "github.com/samuelpkg/samuel-go-guide"
latest = "1.0.0"
description = "Go language guardrails and patterns"
categories = ["language"]
tags = ["go", "golang", "guardrails"]

[plugin.react]
repo = "github.com/samuelpkg/samuel-react"
latest = "1.0.0"
description = "React 18+ framework guardrails"
categories = ["framework"]
tags = ["react", "typescript", "frontend"]

# Anthropic community plugins via subpath, tracking upstream main:
[plugin.mcp-builder]
repo = "github.com/anthropics/skills"
subpath = "mcp-builder"
latest = "main"                              # tracks upstream HEAD continuously
description = "MCP server development guide"
categories = ["workflow"]
upstream = true                              # signals: hands-off, don't expect signature

CI validates: schema parses, every repo URL is reachable (HTTP HEAD), every latest tag exists (git ls-remote --tags).

Registry updates: when a plugin releases a new version, a workflow in the plugin's repo opens a PR against samuel-registry/index.toml updating the latest field. Manual review for the first 6 months; consider automation later.

Phase 4 — starter-pack meta-plugin (PRD 0005, day 4)

Create github.com/samuelpkg/samuel-starter:

# samuel-plugin.toml
name = "samuel-starter"
version = "1.0.0"
kind = "meta"                                # special kind: no payload, just declares dependencies

[samuel]
framework = "^2.0.0"

[requires]
create-rfd = "^1.0.0"
create-prd = "^1.0.0"
generate-tasks = "^1.0.0"
code-review = "^1.0.0"
commit-message = "^1.0.0"
document-work = "^1.0.0"
refactoring = "^1.0.0"
security-audit = "^1.0.0"
testing-strategy = "^1.0.0"
troubleshooting = "^1.0.0"
cleanup-project = "^1.0.0"
dependency-update = "^1.0.0"

[metadata]
description = "The Samuel Way — twelve methodology workflows installed by default"
category = "starter"

samuel init installs samuel-starter by default, which transitively installs the 12 dependencies. samuel init --minimal skips. samuel init --without create-rfd,security-audit installs the starter but drops the two named plugins (the loader processes --without against meta-plugin [requires] before resolution).

Phase 5 — translator plugins (PRD 0005, days 5-6)

Two WASM plugins authored in TinyGo:

github.com/samuelpkg/samuel-claude-translator:

name = "claude-translator"
version = "1.0.0"
kind = "wasm"

[samuel]
framework = "^2.0.0"
protocol = "^1.0.0"

[provides]
hooks = ["sync.after", "init.after"]

[capabilities.filesystem]
read = ["/workspace"]
write = ["/workspace/**/CLAUDE.md", "/workspace/.claude/**"]

[wasm]
module = "plugin.wasm"
exports = ["init", "on_sync_after", "on_init_after", "health"]

[metadata]
description = "Mirror AGENTS.md to CLAUDE.md for Claude Code compatibility"
category = "translator"
target_tool = "claude-code"

The WASM module's on_sync_after hook reads every AGENTS.md the framework wrote, emits a sibling CLAUDE.md (verbatim copy). on_init_after installs a stub .claude/settings.json with PreToolUse hook scaffolding per [[../../wiki/concepts/claude-code-hooks]].

github.com/samuelpkg/samuel-codex-translator:

name = "codex-translator"
version = "1.0.0"
kind = "wasm"

[capabilities.filesystem]
read = ["/workspace"]
write = ["/workspace/**/AGENTS.md", "/workspace/.codex/**"]

[metadata]
description = "Emit Codex-specific files alongside AGENTS.md"
category = "translator"
target_tool = "codex"

The Codex-specific behavior depends on Codex's 2026 conventions. At minimum, it confirms AGENTS.md exists and emits .codex/config.toml if Codex uses one. Lighter than claude-translator because Codex aligns more closely with the AGENTS.md standard.

Both plugins are reference implementations for plugin authors writing translators for other tools (Cursor, Continue, Aider, etc.).

Phase 6 — smoke test (PRD 0005, day 7)

End-to-end in a clean directory:

$ samuel init my-test-project
 Installed samuel-starter (12 plugins)
 Created samuel.toml
 Created AGENTS.md (root + per-folder)

$ cd my-test-project
$ samuel install go-guide
 Installed go-guide v1.0.0

$ samuel install react
 Installed react v1.0.0

$ samuel install claude-translator
 Installed claude-translator v1.0.0 (WASM)

$ samuel sync
 Regenerated AGENTS.md (2 files)
 claude-translator: mirrored to CLAUDE.md (2 files)

$ samuel install codex-translator
 Installed codex-translator v1.0.0 (WASM)

$ samuel sync
 Regenerated AGENTS.md (2 files)
 claude-translator: mirrored to CLAUDE.md (2 files)
 codex-translator: emitted .codex/config.toml

$ ls -la
... AGENTS.md, CLAUDE.md, .claude/, .codex/, .samuel/ ...

$ samuel run init --prd .samuel/tasks/test-prd.md
 prd.toon created

$ samuel run start --iterations 1 --agent codex
... runs against Codex in OCI sandbox ...

Confirms: agnostic invariant holds (no CLAUDE.md until claude-translator installs), three plugin tiers all work (skill + WASM + OCI), starter pack installs cleanly, translator plugins do their job.

Acceptance criteria

  • Migration script produces 76 valid plugin directories in migration-output/ (78 minus 2 dropped).
  • Each generated samuel-plugin.toml parses and validates.
  • All 76 repos pushed to github.com/samuelpkg/samuel-*, tagged v1.0.0.
  • Each repo has a signed GitHub release with cosign signature.
  • samuel-registry/index.toml has 83 entries (76 ports + 7 Anthropic community).
  • Registry CI validates clean (schema OK, repos reachable, tags exist).
  • samuel-starter meta-plugin published; samuel install samuel-starter resolves the 12 dependencies and installs them.
  • claude-translator plugin installable; emits CLAUDE.md mirroring AGENTS.md.
  • codex-translator plugin installable; emits Codex-specific files.
  • End-to-end smoke test passes (commands above).
  • No .claude/ files exist until claude-translator is installed (agnostic invariant).
  • samuel init --minimal skips starter pack entirely.
  • samuel init --without create-rfd,security-audit installs 10 of the 12 starters.

Compatibility and migration

  • For v1 users: v1's samuel.yaml installed list is meaningless in v2. The migration notice ([[../.samuel/tasks/0006-prd-polish-launch]]) explains: "v1's installed languages/frameworks/workflows are now plugins. Reinstall what you want via samuel install <name>."
  • For v1 skill authors who customized: any v1 SKILL.md edits live at .claude/skills/<name>/SKILL.md. v2 doesn't touch that path. Users can read their old customizations, port them to the v2 plugin (PR upstream or fork).
  • For Anthropic community plugins: registry uses subpath references — content stays at github.com/anthropics/skills. We don't fork. If upstream changes, registry curators update the latest field (or leave at main for continuous tracking).

Risks

Risk Likelihood Mitigation
GitHub API rate limits during bulk push High Batch in groups of 10 with sleeps. Resume from partial completion (script is idempotent).
Migration script generates malformed manifest for edge-case skills Medium Validate every generated manifest with samuel plugin validate (PRD 0003) before push. Manual review for the 5% of skills with non-standard frontmatter.
Anthropic upstream skill content changes after migration Low upstream = true flag in registry tells curators to defer to upstream. Re-running the migration regenerates subpath entries from current upstream state.
Per-plugin CI quota burns through GitHub Actions minutes Low Reusable workflow caches TinyGo install; releases trigger only on tag push (rare). Public repos have unlimited minutes.
TinyGo can't compile the translator plugins Medium Translator logic is simple (read AGENTS.md → write CLAUDE.md). TinyGo handles file IO via WASI. Fallback to Rust + wasm32-wasi if needed.
Bulk-creating 76 repos creates org clutter Medium Acceptable trade-off. Migration to github.com/samuel-plugins/* org is a future option if needed.
Smoke test catches integration bugs only post-migration High Run smoke test against a subset (5 plugins covering all three tiers) early — before pushing all 76. Iterate on bugs.
Cosign signing setup is per-plugin chore Medium The reusable workflow handles signing identically across all plugins. Plugin authors don't see the complexity.
Anthropic community plugins fail signature verification (they're not signed by us) Certain Registry's upstream = true flag tells the install path to skip signature requirement. --allow-unsigned not needed for these.

Resolved decisions (2026-05-12)

  1. samuel-starter opt-out granularity: --without accepts comma-separated names AND negative wildcards. samuel init --without 'security-*' skips all matching starter plugins.

  2. commit-message skill placement: confirmed in the starter pack (it was already in the list of 12). Samuel Way workflow used by samuel run (per agent prompt about conventional commits).

  3. Migration script as a published utility: one-shot. scripts/migrate-v1-skills.go is deleted after the 78-plugin migration. Future migrations have different shapes (per-plugin major bumps, not bulk porting).

  4. Anthropic community plugin update cadence: latest = "main" — track upstream HEAD continuously. Cleaner operationally. Risk accepted: upstream changes could surface in user environments without curator review. Trade-off favors freshness; upstream changes are typically refinements, not breaking.

  5. Plugin README content: auto-generated from manifest for the 78 ports. Minimal but functional. Plugin authors can replace per-repo if they want richer docs.

  6. Plugin docs page generation: yes — docs/plugins/<name>.md auto-generated at docs build time from the registry index + each plugin's README. Implementation lands in Milestone 6 polish.

Outcome

To be filled in post-v2.0 launch. Expected outcomes:

  • All 78 v1 skills are accessible to v2 users via samuel install <name>.
  • Average plugin install time < 5 seconds for skill tier, < 15 seconds for WASM tier (translator plugins).
  • The samuel-starter meta-plugin pattern is copied by other plugin authors (e.g., samuel-rust-starter, samuel-fullstack-starter) within a year.
  • One or two of the 78 ports surface as misclassified — a skill that should have been kept built-in, or a plugin that should be in the starter pack but wasn't. Quick patches as v2.0.x releases.
  • [[0001|RFD 0001]] — plugin format (defines kind = "skill", kind = "wasm", kind = "meta")
  • [[0002|RFD 0002]] — AGENTS.md primary (drives translator plugin design)
  • [[0003|RFD 0003]] — manifest schema + Sigstore (defines what migration generates)
  • [[0005|RFD 0005]] — plugin loader (the system that installs migrated plugins)
  • [[0008|RFD 0008]] — gstack/gbrain drop (doesn't get migrated — these are dropped, not moved)
  • [[../../wiki/sources/2026-05-12-v1-skill-content-survey]] — wiki source: full 78-skill triage
  • [[../../wiki/synthesis/v2-skill-migration-plan]] — wiki synthesis: detailed migration approach
  • PRD 0005 (Skill Migration) — implements all phases above