Plugins API Reference
The plugin system extends pubm without forking the core publish pipeline.
PubmPlugin
Section titled “PubmPlugin”export interface PubmPlugin { name: string; registries?: PackageRegistry[]; ecosystems?: Ecosystem[]; hooks?: PluginHooks; commands?: PluginCommand[]; credentials?: (ctx: PubmContext) => PluginCredential[]; checks?: (ctx: PubmContext) => PluginCheck[];}credentialsreturns the list of tokens this plugin needs. Pubm calls it once during initialization so it can prompt for missing tokens, inject them into the environment, and sync them to GitHub Secrets when running--ci-prepare.checksreturns preflight checks that run alongside the core prerequisite and condition phases. Each check uses itsphasefield to choose when it runs.
export interface PluginHooks { // Lifecycle hooks beforeTest?: HookFn; afterTest?: HookFn; beforeBuild?: HookFn; afterBuild?: HookFn; beforeVersion?: HookFn; afterVersion?: HookFn; beforePublish?: HookFn; afterPublish?: HookFn; beforePush?: HookFn; afterPush?: HookFn; afterRelease?: AfterReleaseHookFn; onError?: ErrorHookFn; onSuccess?: HookFn;
// Asset pipeline hooks resolveAssets?: AssetPipelineHooks["resolveAssets"]; transformAsset?: AssetPipelineHooks["transformAsset"]; compressAsset?: AssetPipelineHooks["compressAsset"]; nameAsset?: AssetPipelineHooks["nameAsset"]; generateChecksums?: AssetPipelineHooks["generateChecksums"]; uploadAssets?: AssetPipelineHooks["uploadAssets"];}Asset pipeline hooks
Section titled “Asset pipeline hooks”These hooks let plugins intercept each stage of the release asset pipeline. They run between the build step and the GitHub Release upload.
| Hook | When it runs | Input → Output |
|---|---|---|
resolveAssets | After glob matching | ResolvedAsset[] → ResolvedAsset[] |
transformAsset | Per asset, before compression | ResolvedAsset → TransformedAsset | TransformedAsset[] |
compressAsset | Per asset, replaces built-in compression | TransformedAsset → CompressedAsset |
nameAsset | Per asset, after compression | CompressedAsset → string |
generateChecksums | After all assets are named and hashed | PreparedAsset[] → PreparedAsset[] |
uploadAssets | After GitHub Release upload | PreparedAsset[] → UploadedAsset[] |
When multiple plugins register the same asset pipeline hook, they are chained in registration order. uploadAssets is an exception: each plugin receives the same input independently and all results are concatenated.
Read Asset Pipeline Hooks for full signatures, examples, and composition rules.
Hook signatures
Section titled “Hook signatures”type HookFn = (ctx: PubmContext) => Promise<void> | void;type ErrorHookFn = (ctx: PubmContext, error: Error) => Promise<void> | void;type AfterReleaseHookFn = ( ctx: PubmContext, releaseCtx: ReleaseContext,) => Promise<void> | void;PubmContext
Section titled “PubmContext”Hooks receive the current pipeline context:
export interface PubmContext { readonly config: ResolvedPubmConfig; readonly options: ResolvedOptions; readonly cwd: string; runtime: { tag: string; promptEnabled: boolean; cleanWorkingTree: boolean; pluginRunner: PluginRunner; versionPlan?: VersionPlan; releaseContext?: ReleaseContext; tempDir?: string; pluginTokens?: Record<string, string>; };}Key fields:
ctx.config: resolved pubm config (packages, registries, plugins, releaseAssets, etc.)ctx.options: resolved CLI options (version, tag, mode, dryRun, etc.)ctx.cwd: working directoryctx.runtime: mutable runtime state (version plan, temp directory, etc.)ctx.runtime.pluginTokens: map of resolved plugin credential values keyed byPluginCredential.key. Populated after the credential collection step and available in all subsequent hooks.
Rollback API
Section titled “Rollback API”Plugins can register rollback actions that execute automatically when the publish pipeline fails. Actions run in LIFO (last-in, first-out) order.
Register rollback actions with ctx.runtime.rollback.add() inside any hook:
hooks: { afterVersion: async (ctx) => { // Perform side effect const backup = readFileSync(filePath, "utf-8"); modifyFile(filePath);
// Register rollback to undo it ctx.runtime.rollback.add({ label: `Restore ${filePath}`, fn: async () => { writeFileSync(filePath, backup, "utf-8"); }, }); },}RollbackAction
Section titled “RollbackAction”| Property | Type | Description |
|---|---|---|
label | string | Label shown during rollback |
fn | (ctx: PubmContext) => Promise<void> | Async function that reverses the side effect |
confirm | boolean? | If true, prompts for confirmation in TTY mode before executing. Auto-executes in CI. |
PluginCredential
Section titled “PluginCredential”Declarative descriptor for a token or secret that a plugin requires.
export interface PluginCredential { key: string; env: string; label: string; tokenUrl?: string; tokenUrlLabel?: string; ghSecretName?: string; required?: boolean; resolve?: () => Promise<string | null>; validate?: (token: string, task: PluginTaskContext) => Promise<boolean>;}| Field | Type | Description |
|---|---|---|
key | string | Internal identifier used to look up the value in ctx.runtime.pluginTokens. |
env | string | Environment variable name that provides the token in CI. |
label | string | Human-readable label shown in interactive prompts. |
tokenUrl | string | Optional URL where the user can create the token. |
tokenUrlLabel | string | Optional display label for tokenUrl. |
ghSecretName | string | Name of the GitHub Secret that should hold this token, used by --ci-prepare sync. |
required | boolean | When true, pubm errors if the credential cannot be resolved. Defaults to true. |
resolve | function | Optional custom resolver (no arguments, returns Promise<string | null>). Called before the keyring/prompt fallback. |
validate | function | Optional token validator. Receives the resolved token and a PluginTaskContext; return false to re-prompt. |
Resolution order: env variable → resolve() → keyring (SecureStore) → interactive prompt.
PluginCheck
Section titled “PluginCheck”Descriptor for a preflight check contributed by a plugin.
export interface PluginCheck { title: string; phase: "prerequisites" | "conditions"; task: (ctx: PubmContext, task: PluginTaskContext) => Promise<void> | void;}| Field | Type | Description |
|---|---|---|
title | string | Label shown in the task list UI. |
phase | "prerequisites" | "conditions" | When to run: "prerequisites" runs before network calls; "conditions" runs after registry connectivity is confirmed. |
task | function | The check implementation. Throw to fail the check. |
PluginTaskContext
Section titled “PluginTaskContext”A listr2-agnostic wrapper passed as the second argument to PluginCheck.task.
export interface PluginTaskContext { output: string; title: string; prompt<T = unknown>(options: { type: string; message: string; [key: string]: unknown; }): Promise<T>;}outputdisplays a status line beneath the check title in the task list UI.titlechanges the task title dynamically.prompt()runs an enquirer prompt, available in interactive mode.
Example
Section titled “Example”const notifyPlugin = { name: "notify-plugin", hooks: { async afterPublish(ctx) { const label = ctx.versions && ctx.versions.size > 0 ? [...ctx.versions].map(([name, version]) => `${name}@${version}`).join(", ") : `v${ctx.version}`;
console.log(`Published ${label}`); }, },};Custom commands
Section titled “Custom commands”export interface PluginCommand { name: string; description: string; subcommands?: PluginSubcommand[];}
export interface PluginSubcommand { name: string; description: string; options?: PluginCommandOption[]; action: (args: Record<string, unknown>) => Promise<void>;}Custom registries and ecosystems
Section titled “Custom registries and ecosystems”Use custom registries when you need another publish destination. Use custom ecosystems when you need pubm to read and write versions for another package type.