This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
motrixapp/plugin-sdk is a pnpm workspace holding the four packages that
make up the Motrix plugin-authoring SDK:
| Package | Role |
|---|---|
packages/plugin-manifest-schema |
Zod schema for the plugin manifest plus the shared pack-time validation rules — single source of truth for both |
packages/plugin-api |
Guest-facing types + the motrix:plugin-api virtual-module declaration |
packages/plugin-cli |
motrix-plugin CLI (init/validate/lint/pack/dev) |
packages/create-motrix-plugin |
pnpm create motrix-plugin scaffolder, delegates to plugin-cli |
plugin-manifest-schema has two source modules behind one barrel: schema.ts
(manifest structure) and validate.ts (cross-field + asset rules the schema
cannot express, e.g. hooks ⇒ hostPermissions, locale coverage). validate.ts
is consumed by BOTH publishing pipelines — this CLI and builtin-plugins'
scripts/pack.mjs — so keep it free of node:fs and every other Node builtin;
callers own the I/O.
Dependency chain: plugin-manifest-schema ← plugin-cli ← create-motrix-plugin;
plugin-api is standalone. Internal deps are workspace:*, rewritten to real
version ranges by pnpm at publish time.
pnpm build # pnpm -r build
pnpm typecheck # pnpm -r typecheck
pnpm test # pnpm -r test
pnpm lint # biome check .
pnpm run check:facade # scripts/check-facade.mjs
pnpm run release # validate, build and pack; never uploads by defaultPrefer pnpm exec over npx for one-off CLI invocations in this workspace.
- Façade purity:
packages/plugin-cli/src/manifest-schema.tsmust stay a pureexport * from '@motrix/plugin-manifest-schema're-export — nothing else.scripts/check-facade.mjs(run in CI) enforces this. Any manifest validation change belongs inpackages/plugin-manifest-schema/, never in the façade file. - Published versions are load-bearing: these packages ship to consumers
via npm — once published,
motrix-turboandbuiltin-pluginspin a^2.xrange. Any wire-shape or API change requires a publish here plus a dependency bump there; it does not take effect by editing source alone. - Every pack-time gate runs before esbuild writes anything.
packmust reject a plugin without leaving a half-builtdist/plugin.jsbehind, and — the reason this matters — must never be able to emit a.moextthe host refuses to install. Add new gates alongside the existingvalidateManifest/validateLocaleCoveragecalls at the top ofcommands/pack.ts, never after the bundle step. packoutput is reproducible; keep it that way. Every zip entry is added in sorted order with a pinnedmtime(DOS_EPOCH) andmode, so the same source tree always yields the same sha256 — which is what makes a registry entry'spackage.sha256verifiable by anyone.DOS_EPOCHis built with the LOCAL-timeDateconstructor on purpose: yazl converts it back with local-time getters, so the two cancel out and the digest is timezone-independent without mutatingprocess.env.TZ(a library must not).tests/cli.test.tslocks this across UTC / +8 / −5 / +14.- No
.moext/ Ed25519 signing in this repo. That signing pipeline belongs to thebuiltin-pluginsrepo (it signs plugin bundles, not npm packages). Note the split: the validation rules are shared with that repo viaplugin-manifest-schema; the signing and release orchestration are not, and must not migrate here. - Schema/CLI publish lockstep:
packages/plugin-manifest-schemais inlined into@motrix/plugin-cliat build time (tsup.config.tsnoExternal). Any schema change MUST republish@motrix/plugin-cliin the same publish batch — otherwise plugin authors'motrix-plugin validateand the Motrix host will disagree about manifest validity. Sincebuiltin-pluginsnow importsvalidate.tsfrom the schema package directly, a schema release also means bumping the dependency there. plugin-cliis bin-only by design.tsup.config.tsbuilds only the two bins, with nomain/exportsanddts: false, so consumers resolve zero transitive@motrixdeps. Anything another repo needs to reuse therefore belongs inplugin-manifest-schema, not here — that constraint is why the hooks invariant was hand-copied intobuiltin-pluginsin the first place.
pnpm run release is the canonical SDK preparation entrypoint. It installs
locked dependencies, validates, builds, tests and packs all four packages.
Agents may run this default/dry-run mode.
pnpm run release -- --publish is human-run only — never executed by an
agent. It requires a clean, current main, an interactive terminal outside CI,
and explicit confirmation after the package plan is displayed. It invokes
pnpm publish for verified tarballs in this order:
plugin-manifest-schema → plugin-api → plugin-cli → create-motrix-plugin
See the release guide and its Chinese counterpart for requirements, artifacts and partial-release recovery. The script does not create tags, merge PRs or sign plugin bundles.
- Conversation language is Chinese; code, commits, identifiers, and file names stay in English (workspace-wide convention).
- README is bilingual:
README.md(English) +README.zh-CN.md(Chinese). Any file with CJK content must be written via a bash heredoc (cat > file << 'EOF'), never theWritetool —Writeemits\uXXXXescapes instead of literal characters.