pm-starter
v2026.6.8
Published
Complete starter/scaffold extension for pm-cli showing all capability types
Maintainers
Readme
pm-starter
The CANONICAL scaffold for pm-cli extensions. A single, heavily-commented index.ts demonstrates all 9 SDK capability types with small, SAFE, inert examples.
Use this as a starting template for building your own extensions: copy the capability you need and delete the rest.
Installation
pm install github.com/unbraind/pm-starter --projectCapabilities
Every capability declared in manifest.json is demonstrated in index.ts. Each
maps to one or more register*/hooks.* calls on the ExtensionApi.
| # | Capability | ExtensionApi call(s) | What the demo registers |
|---|---|---|---|
| 1 | commands | registerCommand | pm starter greet, pm starter summary, pm starter demo |
| 2 | renderers | registerRenderer | json + toon renderer overrides (reshape only the starter demo payload, pass through everything else) |
| 3 | hooks | hooks.beforeCommand, hooks.afterCommand, hooks.onWrite, hooks.onRead, hooks.onIndex | All five lifecycle hooks (observe-only; opt-in logging via PM_STARTER_HOOKS) |
| 4 | schema | registerItemFields, registerItemTypes, registerMigration | Optional fields starter_origin/starter_score, a StarterNote item type, and a no-op migration pm-starter-0001-noop |
| 5 | importers | registerImporter, registerExporter | pm starter-demo import (inert dry-run) and pm starter-demo export (read-only JSON dump) |
| 6 | search | registerSearchProvider, registerVectorStoreAdapter | Search provider starter-substring and in-memory vector store adapter starter-memory |
| 7 | parser | registerParser | Identity pass-through parser override for the native list command |
| 8 | preflight | registerPreflight | Pass-through preflight decision override (no behavior change) |
| 9 | services | registerService | Pass-through override of the output_format core service |
Flags: the demo commands declare typed
flags, andregisterFlags("list", …)adds an inert--starter-tagflag to the nativelistcommand. Flag registration is part of the commands capability — it does not need its own manifest entry.
Commands
pm starter greet
pm starter greet
pm starter greet --name Developer --emoji 🚀 --uppercasepm starter summary
pm starter summary
pm starter summary --verbosepm starter demo
pm starter demo # structured payload reshaped by the starter renderer
pm starter demo --jsonImporter / exporter command paths
registerImporter("starter-demo") and registerExporter("starter-demo") auto-create:
pm starter-demo import # inert dry-run preview
pm starter-demo export # read-only JSON dump of itemsHuman-facing commands are namespaced under
pm starter …while the importer/exporter live underpm starter-demo …so the two command paths never collide.pm extension doctorreports 0 collisions as a result.
Architecture
Each capability lives in its own setup* function for clarity. Delete the ones
you don't need and prune manifest.json to match:
setupCommands(api)—registerCommand(with typed flags)setupRenderers(api)—registerRendererforjson/toonsetupHooks(api)—hooks.beforeCommand/afterCommand/onWrite/onRead/onIndexsetupSchema(api)—registerItemFields/registerItemTypes/registerMigrationsetupImportExport(api)—registerImporter/registerExportersetupSearch(api)—registerSearchProvider/registerVectorStoreAdaptersetupParser(api)—registerParsersetupPreflight(api)—registerPreflightsetupServices(api)—registerServicesetupFlags(api)—registerFlags
The zero-runtime-coupling pattern
Standalone-installed extensions load only their own dist/ at runtime, so
@unbrained/pm-cli is not resolvable as a runtime value. index.ts therefore
imports defineExtension as a type only and provides a trivial identity
implementation; the real CLI supplies the live api object at activation time.
For the same reason the EXIT_CODE / CommandError error contract is
re-implemented locally rather than imported from the SDK.
Creating a New Extension
# 1. Clone this repo
git clone https://github.com/unbraind/pm-starter.git my-extension
cd my-extension
# 2. Edit files
# - manifest.json: update name, description, capabilities
# - index.ts: keep only the capabilities you need, implement your logic
# - package.json: update name
# 3. Build and test
npm install
npm run build
# 4. Install locally
pm install ./my-extension --projectLicense
MIT
Release Automation
This package is release-ready for GitHub, npm, and Bun-compatible installs. CI runs type checking, build, production dependency audit, package packing, Bun install verification, and pm-changelog validation. The daily release workflow publishes only when commits exist after the latest release tag and uses pm-changelog to generate CHANGELOG.md and GitHub release notes.
