TypeScript reference extension for pm-cli covering all 9 SDK capability types in one fully-typed index.ts, aligned to the pm-cli 2026.8.7 SDK.
Each capability is a small, SAFE, inert demo with teaching comments. Copy the
ones you need into your own extension and delete the rest. The reference also
ships demo commands that integrate with the newer pm surfaces (plan, context,
search, history-compact) and a guided ts-starter setup --interactive onboarding.
pm install github.com/unbraind/pm-ts-starter --globalEvery capability declared in manifest.json is demonstrated in index.ts. Each
maps to one or more register*/hooks.* calls on the typed ExtensionApi.
| # | Capability | ExtensionApi call(s) |
What the demo registers |
|---|---|---|---|
| 1 | commands | registerCommand, registerFlags |
pm hello, pm ts-starter info; plus an inert --ts-starter-tag flag added to native list |
| 2 | renderers | registerRenderer |
json renderer override that reshapes only the ts_starter-tagged payload, passing everything else through |
| 3 | hooks | hooks.beforeCommand, hooks.afterCommand, hooks.onWrite, hooks.onRead, hooks.onIndex |
All five lifecycle hooks (observe-only; opt-in logging via PM_TS_STARTER_VERBOSE) |
| 4 | schema | registerItemFields, registerItemTypes, registerMigration |
Optional field ts_starter_ref, a Spike item type, and a no-op migration ts-starter-noop |
| 5 | importers | registerImporter, registerExporter |
pm ts-starter-demo import / pm ts-starter-demo export (both inert) |
| 6 | search | registerSearchProvider, registerVectorStoreAdapter |
Search provider ts-starter-prefix (ID-prefix match) and in-memory vector store adapter ts-starter-memory |
| 7 | parser | registerParser |
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 |
pm hello
pm hello --name World --loudpm ts-starter inforegisterImporter("ts-starter-demo") and registerExporter("ts-starter-demo")
auto-create:
pm ts-starter-demo import
pm ts-starter-demo exportThe current SDK accepts an optional third options argument
(ImportExportRegistrationOptions) that adds a full command definition
(description, flags, intent, examples, failure_hints, positional arguments)
to the auto-created command path — surfaced in help exactly like
registerCommand. This reference supplies it for both.
These demo commands shell out to the live pm binary (zero-runtime-coupling —
the extension never imports @unbrained/pm-cli at runtime) and return parsed
JSON, so an author can copy the wiring into a real extension that augments
these surfaces:
pm ts-starter plan-demo [--id <plan-id>] [--depth brief|standard|deep]
pm ts-starter context-demo [--format markdown|toon|json] [--depth brief|standard|deep]
pm ts-starter search-demo [--query <text>] [--limit <n>]
pm ts-starter history-compact-demo --id <item-id> # always --dry-runpm ts-starter setup # prints a non-interactive summary
pm ts-starter setup --interactive # prompted onboarding wizard (TTY only)--interactive is skipped automatically when stdin is not a TTY, so the
command is safe to run in CI and tests.
Every registerCommand definition now carries:
failure_hints— short, actionable strings surfaced to the CLI's error-guidance layer when a command fails.arguments— typed positional argument definitions (ExtensionCommandArgumentDefinition), so help output and runtime contracts describe positional args, not just flags.value_typeon every flag (string|number|boolean), the field the current SDK reads first (over the legacytype).
Command handlers throw PmCliExpectedError-shaped errors built locally
(pmExpectedError) rather than importing the CLI's error class at runtime.
The CLI recognises expected errors by name === "PmCliError", so a locally
constructed error with exitCode + structured context exits cleanly with a
guided message instead of a stack trace.
defineExtension is the SDK's typed identity helper — it returns its argument
unchanged but constrains it to the ExtensionModule shape so TypeScript can
type-check activate(api) and the metadata fields against the real SDK.
It is imported as a type only (import type). A standalone-installed
extension loads only its own dist/ at runtime, so @unbrained/pm-cli is not
resolvable as a runtime value; importing the real function would crash at
activation. We provide a trivial identity implementation and rely on the type
import for full compile-time checking with zero runtime coupling to the CLI
package. The real CLI supplies the live api object when it calls activate.
- Clone this repo
- Edit
index.ts— remove capabilities you don't need - Update
manifest.jsonname and capabilities npm install && npm run buildpm install ./path/to/dir --project
MIT
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.
This repo tracks its project management in .agents/pm/ and ships a committed .gitattributes
that maps those tracker artifacts to pm-cli's field-aware Git merge drivers, so concurrent-branch
tracker edits merge cleanly instead of hard-conflicting. The driver definitions live in
per-clone Git config; npm install / npm ci wires them automatically via the prepare script (a thin
launcher, scripts/prepare-merge-driver.ts, over the canonical pm-ops/merge-driver export: it runs
pm merge install only when the pm CLI is on PATH, and no-ops cleanly when pm is absent. Registry installs of this package never run prepare; a production install of a clone (npm ci --omit=dev) omits pm-ops too, so it must pass --ignore-scripts; being Node-based it behaves identically
on POSIX shells and Windows cmd.exe). To (re)run manually: npm run merge:install.
After merging a branch that touched .agents/pm/, reconcile any residual history-hash drift with
pm merge reconcile (pm-cli ≥ 2026.7.22): preview with pm merge reconcile --dry-run, apply with
pm merge reconcile --message "post-merge reconcile", then confirm with pm validate, which scans the
whole tracker and flags remaining history drift across every affected item (pm merge reconcile
itself lists each affected stream in its output; pm history --verify <id> spot-checks one item). The field-aware driver already unions every author's
content, so reconcile only re-greens the hash chain (no data loss) — see the authoritative
pm-cli merge-safety guide. The
older blunt pm history-repair --all remains available as a lower-level primitive.