name: publish-setup description: Set up pubm in a project (install, config, registries, CI) allowed-tools: - Bash - Read - Write - Edit - Glob - Grep - AskUserQuestion
Set Up pubm
Set up pubm in the current project.
pubm can publish to npm, jsr, crates.io, and private registries in one run. It supports JavaScript/TypeScript and Rust projects with automatic detection.
Workflow
1. Analyze project structure
Start by mapping out the project layout so the rest of the setup matches the repo.
Scan the following:
- Manifest files:
package.json,jsr.json,deno.json,deno.jsonc,Cargo.tomlto detect the ecosystem (JS, Rust, or both) - Workspace config:
pnpm-workspace.yaml,package.jsonworkspaces,Cargo.toml [workspace]to detect monorepo structure - Package manager: lock files (
bun.lockb,pnpm-lock.yaml,package-lock.json,yarn.lock) to determine install commands - Existing config:
pubm.config.ts/.js/.mjsto check if pubm is already configured - CI/CD:
.github/workflows/,.gitlab-ci.yml, etc. for existing CI setup - Version references: files outside manifests that contain version strings, such as README badges or
plugin.json - Build artifacts:
dist/,build/,bin/to understand build outputs - Release workflow: existing release scripts in
package.json,Makefile, and similar files
Present findings to the user:
- Project type: single-package, monorepo, or multi-ecosystem
- Detected packages and their ecosystems
- Current release workflow, if there is one
- Likely needs such as version sync, Homebrew, or CI automation
Use this analysis to decide which registries to suggest, which supported release path to recommend, whether a config file is needed, and whether custom plugins are required.
2. Ask about release path, CI/CD, and changesets
Ask the user:
- Release path: Direct Release (
pubm) or Split CI Release (localpubm --phase prepare, CIpubm --phase publish). Usereferences/decision-guides.mdto recommend one. - Set up CI/CD for Split CI Release publishing? Only generate publish workflows after the user chooses Split CI Release.
- Use changesets workflow? (Track changes per PR, automate versioning + CHANGELOG)
Store the answers for subsequent steps. Do this before installing plugins, writing config, or generating workflows so later choices match the release path.
3. Check if pubm is installed
Check package.json devDependencies for pubm. If it is missing, ask whether to install:
npm install -D pubmorpnpm add -D pubm(detect package manager from lock files)- pubm itself is an npm package, so even Rust projects need Node.js and npm to use it
4. Review auto-detected packages and registries
Run pubm inspect packages to show the detected ecosystem, packages, and target registries.
pubm auto-detects:
- Ecosystem: JavaScript (package.json, deno.json, deno.jsonc) or Rust (Cargo.toml)
- Packages: Workspace packages via pnpm-workspace.yaml, package.json workspaces, or Cargo.toml [workspace]. Falls back to single-package if no workspace found.
- Registries per package:
- JS: npm (default when package.json exists), jsr (when jsr.json or deno.json/deno.jsonc exists), private registry (from publishConfig.registry or .npmrc)
- Rust: crates (always)
Show the output and ask:
- Is this detection correct?
- Is there any additional registry to publish to, such as adding jsr to a package that only has npm or adding a private registry URL?
If the user wants changes (add/remove registries, add/remove packages), note them for config generation in Step 6.
5. Ask about official plugins
Show the available official plugins and ask which, if any, to use:
| Plugin | Package | Description |
|---|---|---|
externalVersionSync() |
@pubm/plugin-external-version-sync |
Sync version to non-manifest files (plugin.json, README badges, etc.) |
brewCore() |
@pubm/plugin-brew |
Open PR to homebrew-core on release |
brewTap() |
@pubm/plugin-brew |
Update formula in a custom Homebrew tap repo on release |
If externalVersionSync selected:
- Install the plugin:
npm install -D @pubm/plugin-external-version-sync(or pnpm/bun equivalent) - Run
pubm sync --discoverto scan for version references outside manifest files - Show discovered references and ask which to include as sync targets
- If the project uses independent versioning (monorepo), ask which package's version to sync, and note the
versioncallback for config
If brewCore selected:
- Install the plugin:
npm install -D @pubm/plugin-brew - Ask for the formula file path (default:
Formula/<package-name>.rb) - Optionally ask for
packageNamefilter (for monorepo per-package releases)
If brewTap selected:
- Install the plugin:
npm install -D @pubm/plugin-brew - Ask for the formula file path (default:
Formula/<package-name>.rb) - Ask for the tap repo (e.g.,
user/homebrew-tap) - Optionally ask for
packageNamefilter
5.1. Evaluate need for custom plugins
Based on the project analysis in Step 1, if the user needs something that pubm's built-in features or official plugins do not cover, guide them to create a custom plugin.
Signals that a custom plugin is needed:
- Post-release notifications (Slack, Discord, email, etc.)
- Custom artifact publishing (S3, CDN, etc.)
- Integration with external services (Sentry release tracking, deployment triggers, etc.)
- Custom validation or pre-publish checks beyond what pubm provides
- Automated documentation updates on release
When a custom plugin is needed:
- Explain which hook(s) would be appropriate for the requirement
- Ask the user: "이 기능을 위해 커스텀 플러그인을 만들까요?"
- If yes, invoke the
/create-pluginskill to scaffold the plugin - After the plugin is created, return to this setup flow and include it in config generation in Step 6
5.2. Install jsr CLI (if jsr is among registries)
If any package targets jsr, check package.json devDependencies for jsr. If not installed, install it using the project's package manager.
6. Generate pubm config file (conditional)
Only create pubm.config.ts when needed. Create one when:
- User overrode auto-detected registries (explicit packages config required)
- User selected plugins
- User needs non-default config (versioning strategy, etc.)
When config is NOT needed: Tell the user that pubm's auto-detection covers the setup and no config file is required.
When creating config:
Use defineConfig() from pubm for type safety. Use packages array with per-package path and registries. Read references/config-examples.md for templates.
Example with plugins:
import { defineConfig } from 'pubm'
import { externalVersionSync } from '@pubm/plugin-external-version-sync'
export default defineConfig({
packages: [
{ path: 'packages/core', registries: ['npm', 'jsr'] },
{ path: 'packages/cli', registries: ['npm'] },
],
plugins: [
externalVersionSync({
targets: [
{ file: 'plugins/.claude-plugin/plugin.json', jsonPath: 'version' },
],
}),
],
})
7. Generate missing registry config files
For each registry a package targets, check whether its required config file exists. If not, generate it from whichever source file is available.
Generation rules:
| Target registry | Required file | Source file | Reference |
|---|---|---|---|
jsr |
jsr.json |
package.json or deno.json/deno.jsonc |
references/registry-jsr.md |
npm or custom URL |
package.json |
jsr.json or deno.json/deno.jsonc |
references/registry-npm.md |
crates |
Cargo.toml |
package.json |
references/registry-crates.md |
Read the corresponding registry reference file for the template and constraints.
Behavior:
- If the required file already exists, skip silently.
- If neither source file nor target file exists, inform the user and ask them to create one manually.
- Before writing any generated file, show the content and ask for confirmation.
8. CI setup (if Split CI Release was selected in Step 2)
- Ask CI platform: Default to GitHub Actions if not specified.
- Ask trigger method:
- Tag-based (recommended for single-package): push a
v*tag to trigger publish - Commit-based (recommended for monorepo): trigger on "Version Packages" commit to main
- Manual (workflow_dispatch): trigger from the GitHub Actions UI
- Both: supports multiple triggers
- Tag-based (recommended for single-package): push a
- Determine registries: Use the registries confirmed in Step 3.
- Generate workflow file: Read
references/ci-templates.mdfor the appropriate template. Create.github/workflows/publish.yml. - List required secrets: Based on the target registries:
GITHUB_TOKENfor GitHub Releases (automatically available assecrets.GITHUB_TOKEN; no manual setup needed)NODE_AUTH_TOKENfor npm (create at npmjs.com > Access Tokens > Automation)JSR_TOKENfor jsr (create at jsr.io/account/tokens/create)CARGO_REGISTRY_TOKENfor crates.io (create at crates.io > Account Settings > API Tokens)
9. Changesets Workflow (if selected in Step 2)
Run the CLI to set up the changesets workflow:
pubm init
This creates:
.github/workflows/changeset-check.yml- PR changeset detection with bot comments After running, tell the user:- Every PR with code changes needs a changeset (
pubm changesets add) no-changesetlabel skips the check for docs/CI-only changes- On release, pubm consumes changesets to determine version bumps and generate CHANGELOG
Then write the following section to the project's CLAUDE.md (append if file exists, create if not):
## Changesets Workflow
This project uses pubm changesets to track changes and automate versioning.
### Rules
- Every PR that changes runtime code must include a changeset file
- Add a changeset: `pubm changesets add`
- Changeset identifiers use package path (e.g., `packages/core`), not registry name. Package names are also accepted and auto-resolved to paths.
- Changeset summaries should be written from the user's perspective
- PRs with `no-changeset` label skip the changeset check (use for docs, CI config, etc.)
### Workflow
1. Make changes on a feature branch
2. Run `pubm changesets add` to select packages, bump type, and summary
3. Commit the generated `.pubm/changesets/<id>.md` file with your PR
4. On merge, changesets accumulate on main
5. When releasing, `pubm` consumes pending changesets to determine versions and generate CHANGELOG
### Bump Type Guide
- **patch**: Bug fixes, internal refactors with no API changes
- **minor**: New features, backward-compatible additions
- **major**: Breaking changes, removed/renamed public APIs
### Review Checklist
- [ ] Changeset file included (or `no-changeset` label applied)
- [ ] Bump type matches the scope of changes
- [ ] Summary is clear and user-facing
10. Add npm scripts (JS projects only)
Add to package.json. The release script depends on whether CI was set up:
If Split CI Release was selected (publishing is handled by CI):
{
"scripts": {
"release": "pubm --phase prepare",
"release:ci": "pubm --phase publish"
}
}
For Split CI Release, --phase prepare runs Prepare for CI publish: it validates the project, collects/syncs tokens, writes versions, creates tags, pushes the release commit and tags, and does not publish packages. --phase publish runs Publish prepared release in CI: it reads manifest versions, publishes packages, and creates GitHub Releases.
If Direct Release was selected (publishing is done locally or by one controlled job):
{
"scripts": {
"release": "pubm"
}
}
11. Present summary
List all files created or modified and remind them about required authentication. Show only the lines for registries the user selected:
- npm: Run
npm loginlocally, or setNODE_AUTH_TOKENsecret in GitHub - jsr: Run
pubmlocally (interactive token prompt), or setJSR_TOKENsecret in GitHub - crates.io: Run
cargo loginlocally, or setCARGO_REGISTRY_TOKENsecret in GitHub
Remind the user they can run pubm inspect packages at any time to check the detected setup.
Constraints
- Always use
defineConfig()frompubmfor type safety in config files. - Config uses a
packagesarray with per-packageregistries; there is no top-levelregistriesfield onPubmConfig. - The config file is optional. Only create it when auto-detection needs to be overridden or plugins are used.
- If you are not sure which registries the user wants, ask.
- When suggesting npm scripts, use
"release": "pubm"for Direct Release. Use"release": "pubm --phase prepare"and"release:ci": "pubm --phase publish"for Split CI Release. - In CI, use
--phase publishfor Publish prepared release: publish packages plus GitHub Release creation. - When Step 1 reveals requirements beyond built-in features and official plugins, use the
/create-pluginskill to scaffold a custom plugin before generating the config file.
References
references/registry-jsr.md-- JSR-specific constraints and templatesreferences/registry-npm.md-- npm-specific constraints and templatesreferences/registry-crates.md-- crates.io-specific constraints and templatesreferences/config-examples.md-- Config file templates and type referencereferences/ci-templates.md-- CI/CD pipeline templates (package manager-specific setup blocks)references/official-plugins.md-- Official plugin API reference (externalVersionSync, brewTap, brewCore)references/homebrew-setup.md-- Homebrew distribution setup and CI installation guide