Agent Native

plugin-transfer

This skill guides migrating an existing plugin repository into the Sanity plugins monorepo using the copy-plugin generator.

by SanityOfficial publisherNot reviewed

Identity proven by GitHub's verified organisation badge (sanity-io)

Agents
Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode, claude.ai and API
License
MIT (permissive)
Pin
a80a997pinned Oct 9, 2026
Context cost
about 3,100 tokenswhen the skill loads
GitHub stars
20on sanity-io/plugins
Scripts
None found

What it does

“Guides agents through migrating an existing plugin into this monorepo with the copy-plugin generator workflow.”
The author's description, from SKILL.md

Generated summary from the skill's own text

This skill guides migrating an existing plugin repository into the Sanity plugins monorepo using the copy-plugin generator. It covers scaffolding monorepo-compatible files, cleaning up stale documentation, running verification checks, and preparing a transfer PR with proper changeset credits to original contributors.

When to use it

  • Moving a standalone plugin repository into sanity-io/plugins monorepo
  • Porting plugin code while maintaining its original history and authorship
  • Setting up plugin test-studio wiring and configuration during migration
  • Preparing transfer PR with breaking changes documentation and contributor credits

When not to

  • Creating a new plugin from scratch in the monorepo
  • Migrating styled-components styling to vanilla-extract during initial transfer
  • Updating .github/CODEOWNERS unless explicitly requested by maintainers

Install

These commands install from the publisher's repository and need no account.

skills CLI

npx skills add sanity-io/plugins --skill plugin-transfer

Installs from the repository's default branch, which may have changed since the commit we checked.

GitHub CLI 2.90 or later

gh skill install sanity-io/plugins plugin-transfer@a80a997e3d11d188f9639ac3efab1d8f93a276ef

Installs the commit we checked (a80a997).

Copy by hand

Download the folder at a80a997 and put it in .claude/skills/plugin-transfer for Claude Code and in .agents/skills/plugin-transfer for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode.

Skill folder on GitHub at a80a997

Claude Code plugin

/plugin install sanity@claude-plugins-official

The publisher's plugin in Claude's official marketplace. It may hold more than this skill, and we have not pinned it.

Copy for your agent

A prompt for any coding agent. It installs this skill from GitHub at the pinned commit, copies the files as they are, and runs nothing unless you ask.

Prompt

Install the agent skill "plugin-transfer" by Sanity.

Source, pinned to commit a80a997e3d11d188f9639ac3efab1d8f93a276ef:
https://github.com/sanity-io/plugins/tree/a80a997e3d11d188f9639ac3efab1d8f93a276ef/.agents/skills/plugin-transfer

1. Download that folder at exactly this commit. Do not use the default branch.
2. Copy every file unchanged, keeping the folder structure, into .claude/skills/plugin-transfer/ for Claude Code and .agents/skills/plugin-transfer/ for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode. Create the folders if they do not exist.
3. Do not edit the files, and do not run any script in the folder unless I ask you to.
4. When you are done, list the files you copied and where you put them.

Listing and checks: https://www.agentnative.dev/skills/sanity/plugin-transfer

SKILL.md at the pin

---
name: plugin-transfer
description: Guides agents through migrating an existing plugin into this monorepo with the copy-plugin generator workflow.
---

# Plugin Transfer

Use this skill when migrating an existing plugin repository into `sanity-io/plugins`.

## Start Here

Always start with:

```bash
pnpm generate "copy plugin"
```

This is the canonical transfer flow and scaffolds monorepo-compatible files and test-studio wiring.

**Do not keep migration TODOs in the repo.** If the generator creates `README.todo.md`, delete it after moving its contents into the transfer PR description. Maintainers can update PR checklists directly on GitHub without a code change.

## Required vs Unnecessary Config

Keep and maintain these monorepo config files in the transferred plugin:

- `package.json`
- `tsdown.config.ts`
- `tsconfig.json`
- `vitest.config.ts`

Do not copy standalone-repo-only setup such as custom root CI/build/lint/test configs that are already handled by this monorepo.

## Clean Up the Transferred README

The original `README.md` is preserved, but old standalone-repo content is almost always stale in the monorepo. Remove or rewrite the following before opening the PR:

- **Old release/development sections.** Delete sections that describe the original repo's release or dev tooling, e.g. `## Develop & test` (typically references `@sanity/plugin-kit`) and `### Release new version` (references the original repo's GitHub Actions / semantic-release). The monorepo handles building, testing, and releasing centrally, so these instructions are wrong here.
- **Links to old/forked versions.** Remove pointers like "for the v2 version, see this other repo" that link to pre-transfer forks or legacy repositories.
- **Specific Sanity Studio major versions.** Do not reference the current latest Studio major (e.g. "Sanity Studio v6") since it ages quickly, and do not mention long-gone majors like v3. Reword phrasing such as "migrated to Sanity Studio V3" / "only the v3 version is maintained" to a version-agnostic statement (e.g. "maintained by Sanity.io"). Only mention a version when genuinely necessary—at most as `v2 - legacy` to disambiguate a legacy line—and usually omit it entirely.

Keep the substance that is still accurate: intro/description, screenshots, acknowledgements, install, usage, configuration, and license sections.

## Required Transfer Checks

1. Keep the original plugin `README.md` in the new plugin workspace, but clean it up (see [Clean Up the Transferred README](#clean-up-the-transferred-readme)).
2. Restore `LICENSE` from the original repository when it credits authors beyond Sanity.io alone (the copy-plugin generator deletes it during cleanup). If kept, update the copyright year(s) to the current year.
3. Add and verify the generated test-studio example under `dev/test-studio/src/<plugin-example>/index.tsx`.
4. Confirm the plugin is wired in `dev/test-studio/sanity.config.ts`.
5. Do **not** update `.github/CODEOWNERS` during transfer unless explicitly requested.
6. Add a changeset with a **major** bump for the transferred plugin (see [Changesets](#changesets)).
7. Update the root `README.md` plugins table with the transferred plugin.
8. Add pending transfer TODOs to the transfer PR description only (see [PR description checklist](#pr-description-checklist)—not in a README or other repo file).
9. Run the full pre-PR verification suite (see [Before Submitting a PR](#before-submitting-a-pr)).

## Before Submitting a PR

Run these commands in order. **All must pass** or CI will fail:

```bash
# 1. Format code
pnpm format

# 2. Check for unused exports, dependencies, and catalog entries
pnpm knip

# 3. Run linters (includes TypeScript type checking)
pnpm lint

# 4. Build all packages
pnpm build

# 5. Run tests
pnpm test run
```

### Knip

The copy-plugin generator adds a workspace entry to `knip.jsonc`. After transfer, fix any knip issues in the plugin:

- Remove unused exports (e.g. helpers only used internally should not be exported).
- Remove dead code flagged as unused.

Catalog warnings for `dev/*` workspaces (e.g. `@sanity/vision` used only by `dev/test-studio`) are expected—the root `knip.jsonc` sets `"catalog": "warn"` for those.

### Lint

Transferred plugins may carry legacy patterns that fail monorepo lint rules. Fix what you can; for remaining issues in legacy `src/` or `test/` code, add targeted `.oxlintrc.json` overrides or `ignorePatterns` rather than disabling rules repo-wide.

Common legacy fixes:

- Replace `createRequire` / `require()` with ESM `import` (add `"resolveJsonModule": true` to the plugin `tsconfig.json` for JSON imports).
- Use `import.meta.url` with `fileURLToPath` instead of `__dirname` in tests.
- Remove stale `eslint-disable` comments that oxlint reports as unused.

#### Duplicate `sanity` peer variants break type-aware lint

Type-aware lint can fail (sometimes intermittently, especially on cold installs) with errors like `Type 'import(".../.pnpm/sanity@X_<hashA>/...").D' is not assignable to type 'import(".../.pnpm/sanity@X_<hashB>/...").D'` in `dev/test-studio/src/**` examples. This happens when the transferred plugin resolves `sanity` to a different pnpm peer-variant than the other plugins, creating an extra duplicate copy of sanity's type definitions.

To keep the plugin on the shared `sanity` variant, declare these in the plugin `devDependencies`:

- `"@types/node": "catalog:"`
- `"styled-components": "catalog:"` (when the plugin depends on `@sanity/ui`, which peers on styled-components; without the declaration pnpm may auto-install a separate copy of the peer)

Verify alignment by checking that the plugin importer's `sanity` version string in `pnpm-lock.yaml` matches other plugins (e.g. `plugins/@sanity/sfcc`).

> **Do not migrate styling during a transfer.** When the plugin already uses `styled-components`, leave it in place for the initial port — the goal is a faithful, low-risk move. `styled-components` is still migrated to vanilla-extract (the styling target for every plugin), but in a **separate follow-up PR**, done with care to preserve visual fidelity and avoid regressions. The `styled-components: catalog:` alignment above applies until then. For the follow-up, use the `migrate-styled-components-to-vanilla-extract` skill; the `sanity-plugin-best-practices` styling reference (`Migrating off styled-components`) covers the patterns.

### Tests

Vitest runs against built `dist/` output (`pretest` builds packages automatically). Fix path resolution and module import issues in legacy test files. The plugin's own `test/` suite (if present) runs via the root vitest config when included in the plugin workspace.

## Changesets

Every transferred plugin needs a **major** changeset. Compare the transferred plugin's `package.json` (peer dependencies, engines, exports, and build config) against the last published version on npm. Do not copy a template blindly—only list breaking changes that actually apply.

### Credit every contributor

Because the transfer PR is opened by someone else (often the `🤖 bot`), the generated release would otherwise thank the wrong person. Add an `author:` directive so the changelog credits the people who actually built the plugin. [Multiple `author:` lines are supported](https://github.com/changesets/changesets/blob/c2db1dd5d2da6c6eb514d86bbe05cbb7227b067f/packages/changelog-github/src/index.test.ts#L229-L243), so list **everyone** who worked on the plugin being ported — not just the latest author — so they all get their thanks in the release notes.

- Use the contributors' **GitHub usernames**, always with a leading `@` (e.g. `author: @stipsan`).
- Put each `author:` line on its own line, before the summary text. The lines are stripped from the rendered changelog.
- Gather contributors from the original repo's commit history, `package.json` `author`/`contributors`, and the README acknowledgements.

```markdown
---
'package-name': major
---

author: @stipsan
author: @rexxars

Port PACKAGE-NAME to the Sanity plugins monorepo
```

This produces a release line thanking each contributor:

> Thanks [@stipsan](https://github.com/stipsan), [@rexxars](https://github.com/rexxars)! - Port PACKAGE-NAME to the Sanity plugins monorepo

See [AGENTS.md → Crediting Original Authors](../../../AGENTS.md) for the full rationale.

### Format

Use this format (add the `author:` lines from [Credit every contributor](#credit-every-contributor) above the summary):

```markdown
---
'package-name': major
---

author: @stipsan
author: @rexxars

Port PACKAGE-NAME to the Sanity plugins monorepo

This major release includes several breaking changes as part of the migration to the monorepo:

- **React Compiler enabled**: ...
- **ESM-only**: CommonJS support has been removed. The package now ships only ESM
- **React 19.2+ required**: ...
- **Sanity Studio v5+ required**: ...
- **Node.js 20.19+ required**: ...
```

Include additional bullets only when they apply to the plugin—for example:

- **styled-components 6.1+ required** (UI plugins that use styled-components)
- **react-dom 19.2+ required** (when newly added as a peer dependency)
- **Dropped Sanity v3/v4 support** (when the previous peer range allowed older Studio versions)

Example for `sanity-naive-html-serializer`:

```markdown
---
'sanity-naive-html-serializer': major
---

author: @stipsan
author: @rexxars

Port sanity-naive-html-serializer to the Sanity plugins monorepo

This major release includes several breaking changes as part of the migration to the monorepo:

- **React Compiler enabled**: The package is now built with React Compiler targeting React 19
- **ESM-only**: CommonJS support has been removed. The package now ships only ESM
- **React 19.2+ required**: Minimum React version is now 19.2 (previously ^18.3 || ^19)
- **react-dom 19.2+ required**: `react-dom` is now a required peer dependency
- **Sanity Studio v5+ required**: Minimum Sanity version is now v5 (Sanity v3 and v4 are no longer supported)
- **Node.js 20.19+ required**: Minimum Node.js version is now 20.19 (previously >=18)
```

## PR description checklist

Put all pending transfer work in the **PR description** as unchecked checkboxes. Do not create `README.todo.md` or similar todo files in the plugin workspace—the maintainer should be able to check items off on GitHub without opening a PR to edit repo files.

Include these sections in every transfer PR:

### Transfer verification

- [ ] Trusted publishing configured: `npm trust github <package-name> --file=release.yml --repository=sanity-io/plugins`
- [ ] `package.json` dependencies/peerDependencies/exports verified against original repo
- [ ] `LICENSE` restored with updated copyright year when the original credits authors beyond Sanity.io alone
- [ ] Test studio example wired and manually verified (`pnpm dev`)
- [ ] `pnpm format`, `pnpm knip`, `pnpm lint`, `pnpm build`, `pnpm test run` all pass
- [ ] Major changeset added with validated breaking changes

### Maintainer follow-up

Agents cannot complete these steps themselves. Ask the maintainer to handle them:

- [ ] Update the original repo README (`<link to readme>`) and replace it with: `# [This plugin has moved](<new location>)`
- [ ] Transfer pending issues from the original repo to this monorepo and label them as `<plugin-name>`
- [ ] Archive the original repo: `<repo link>/settings`

Example for `sanity-naive-html-serializer`:

- [ ] Update the original repo README (https://github.com/sanity-io/sanity-naive-html-serializer/blob/main/README.md) and replace it with: `# [This plugin has moved](https://github.com/sanity-io/plugins/tree/main/plugins/sanity-naive-html-serializer)`
- [ ] Transfer pending issues from the original repo to this monorepo and label them as `naive-html-serializer`
- [ ] Archive the original repo: https://github.com/sanity-io/sanity-naive-html-serializer/settings

## Anything Else To Consider

- **Do not migrate styling during the transfer.** Keep an existing `styled-components` plugin on `styled-components` for the initial port; defer any vanilla-extract migration to a follow-up PR using the `migrate-styled-components-to-vanilla-extract` skill (see [the styling note above](#duplicate-sanity-peer-variants-break-type-aware-lint)).
- Review copied dependencies and peer dependencies carefully.
- Run the [Before Submitting a PR](#before-submitting-a-pr) verification suite—not just `pnpm build` and `pnpm dev`.
- Use `pnpm dev` to manually verify the test-studio example after the automated checks pass.

From sanity-io/plugins at a80a997, shown as plain text under its license: MIT (permissive). The license text is in LICENSE.

View SKILL.md on GitHub at a80a997

Files

1 file, 13 KB in total. Each file has a sha256 in the pin's manifest; the first 12 characters are shown.

Skill folder on GitHub at a80a997
All 24 skills from Sanity

More from Sanity

  • sanity-live-cache-components

    Integrates Sanity Live with Next.js Cache Components in next-sanity v13+ apps, setting up shared cached data fetching through sanityFetch, live content…

    Claude Code, Codex, Cursor +4 · about 4K tokens · pinned 6 days ago

  • content-experimentation-best-practices

    This skill provides guidance for designing and running content experiments using A/B and multivariate testing.

    Claude Code, Codex, Cursor +4 · about 360 tokens · pinned 6 days ago

  • content-modeling-best-practices

    Guides agents through structured content modeling principles for headless CMSes like Sanity, covering schema design, content reuse strategies, and field…

    Claude Code, Codex, Cursor +4 · about 340 tokens · pinned 6 days ago

  • portable-text-conversion

    Converts HTML and Markdown content into Portable Text blocks for Sanity using markdownToPortableText, htmlToBlocks, or manual construction.

    Claude Code, Codex, Cursor +4 · about 510 tokens · pinned 6 days ago

  • portable-text-serialization

    This skill enables rendering Portable Text content across multiple frameworks and output formats using the @portabletext library family.

    Claude Code, Codex, Cursor +4 · about 940 tokens · pinned 6 days ago

  • sanity-best-practices

    This skill provides best practices for Sanity headless CMS development across schema design, GROQ queries, framework integrations (Next.js, Nuxt, Astro…

    Claude Code, Codex, Cursor +4 · about 1.1K tokens · pinned 6 days ago

All Coding workflow skills
  • planning

    This skill orchestrates multi-workflow projects with dependencies and shared data tables by creating a task graph in the orchestrator via the create-tasks tool.

    by n8nOfficial publisher

    Claude Code, Codex, Cursor +3 · about 2.4K tokens · pinned 6 days ago

  • progressive-building

    This skill implements incremental workflow development for agents building or extending workflows.

    by n8nOfficial publisher

    Claude Code, Codex, Cursor +3 · about 1.4K tokens · pinned 6 days ago

  • workflow-builder

    Builds and edits n8n workflows using the TypeScript SDK.

    by n8nOfficial publisher

    Claude Code, Codex, Cursor +3 · about 14.2K tokens · pinned 6 days ago

  • remotion-upgrade

    This skill upgrades Remotion and its related packages to the latest stable version.

    by RemotionOfficial publisher

    Claude Code, Codex, Cursor +3 · about 460 tokens · pinned 6 days ago

  • remotion-upgrade

    This skill upgrades Remotion and related packages across a project, automatically detecting the package manager and workspaces.

    by RemotionOfficial publisher

    Claude Code, Codex, Cursor +3 · about 460 tokens · pinned 6 days ago

  • final-release-review

    Audits Python SDK release candidates or plans against the previous release, comparing diffs for regressions, API changes, and version compatibility.

    by OpenAIOfficial publisher

    Contains scripts

    Claude Code, Codex, Cursor +3 · about 5.4K tokens · pinned 6 days ago

The skills listed here are third-party software, collected from public GitHub repositories as a catalog of recent skills and provided as is. Agent Native does not write or control them and is not responsible for any harm, loss or damage caused by installing or using them. Labels and checks describe what we saw at one commit and are not a guarantee. Read a skill's files before you run it. Terms of use