Thanks for helping improve pm-cli. This project is designed for deterministic, agent-friendly workflows and uses pm itself as the source of truth for planning and implementation tracking.
- Node.js 20+
- pnpm 10+
pnpm install
pnpm build
node dist/cli.js --helpFor maintainer sessions that mutate real tracker data in this repository:
# from repository root
export PM_AUTHOR="maintainer-agent"
# refresh global pm from this repository and verify availability
npm install -g .
pm --version
# prefer global pm after refresh; fallback to the built CLI if needed
export PM_CMD="pm"
# export PM_CMD="node dist/cli.js"
$PM_CMD --version
node -v
pnpm -v
pnpm buildFor real repository tracking, do not override PM_PATH.
For tests, always use sandboxed storage via node scripts/run-tests.mjs ... (sets both PM_PATH and PM_GLOBAL_PATH).
- Track work in
pmitems (claim, link files/tests/docs, and log comments/evidence). - Treat
pmdata and runtime behavior as the source of truth; update user-facing docs as needed without using them as test contracts. - Prefer small, reviewable changesets with deterministic behavior.
Run standard checks:
pnpm build
pnpm typecheck
pnpm test
pnpm test:coverageFor pm-linked safe execution (required when running tests through pm test / pm test-all), use:
node scripts/run-tests.mjs test
node scripts/run-tests.mjs coverageThe runner creates a temporary sandbox and sets PM_PATH and PM_GLOBAL_PATH so tests never touch repository planning data.
When validating linked-test automation behavior, include guard-flag coverage for --fail-on-skipped, --fail-on-empty-test-run, and --require-assertions-for-pm.
When changing validation behavior, include targeted checks for:
pm validate --check-metadata --metadata-profile core|strict|custompm validate --check-files --scan-mode tracked-allpm validate --check-files --scan-mode tracked-all-strict
When changing stdin, output, exit handling, or linked test execution, run targeted terminal-compatibility regressions before full-suite validation:
node scripts/run-tests.mjs test -- \
tests/unit/parse-utils.spec.ts \
tests/unit/beads-command.spec.ts \
tests/unit/test-command.spec.ts \
tests/integration/cli.integration.spec.ts \
tests/integration/release-readiness-runtime.spec.tsBehavior expectations to preserve:
- Interactive TTY stdin is rejected for piped-only
-inputs with actionable guidance. - Exit-code mappings stay stable (
0..5) while CLI failures remain deterministic. - Linked test orchestration remains non-interactive and reports timeout/maxBuffer failures clearly.
For deeper context on implementation and extension development:
- docs/ARCHITECTURE.md — source tree, item storage, mutation contract, history/restore, search, and testing internals.
- docs/EXTENSIONS.md — full extension development guide: manifest format, ExtensionApi reference, lifecycle hooks, and a working example.
- docs/RELEASING.md — maintainer release procedure for calendar versioning, CI gates, npm publish, and GitHub Release automation.
pm-cli extensions live in .agents/pm/extensions/ (project) or ~/.pm-cli/extensions/ (global). See docs/EXTENSIONS.md for the full guide. Each extension needs:
- A manifest file
manifest.jsondeclaringname,version,entry,priority, andcapabilities. - An entry module exporting
activate(api).
The api object provides:
api.registerCommand({ name, run })— add or override command handlers (handlerremains backward-compatible but emits migration warning; preferrun).api.registerRenderer(format, renderer)— overridetoon/jsonoutput.api.registerImporter(name, importer)— adds<name> importcommand path.api.registerExporter(name, exporter)— adds<name> exportcommand path.api.registerFlags(targetCommand, flags)— declare flags for extension commands.api.registerItemFields(fields)— declare custom schema fields.api.registerMigration(def)— declare schema migrations.api.registerSearchProvider(provider)— add custom search providers.api.registerVectorStoreAdapter(adapter)— add custom vector store adapters.api.hooks.beforeCommand/afterCommand/onWrite/onRead/onIndex— lifecycle hooks.
Use the published SDK import path for extension type contracts:
import { defineExtension, type ExtensionApi } from "@unbrained/pm-cli/sdk";Dispatch behavior is extension-first for registered command handlers: matching extension command paths can replace core command execution at runtime. Keep compatibility in mind and provide explicit rollback instructions (--no-extensions) in docs/tests when introducing new override behavior.
Only register capabilities that are listed in your manifest's capabilities array. Registration outside declared capabilities fails extension activation deterministically.
Run pm health to inspect extension load/activation status, capability guidance/contract metadata, and migration summaries.
Use pm extension --doctor --detail deep --trace when triaging activation failures, and pm extension --manage --runtime-probe when you need opt-in runtime parity in manage output.
When unmanaged extension state is expected to be managed, use pm extension --doctor --fix-managed-state or pm extension --manage --fix-managed-state before re-running diagnostics.
- Include focused scope and rationale.
- Confirm all checks pass (
pnpm build && pnpm typecheck && pnpm test:coverage). - Update relevant user-facing docs when behavior changes, but keep enforcement in pm data and runtime tests.
- Add/maintain tests for any new behavior (100% coverage required).
- Reference relevant
pmitem IDs in PR description.