@unbrained/pm-cli 2026.5.10 → 2026.5.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +4 -4
- package/AGENTS.md +3 -116
- package/CHANGELOG.md +14 -0
- package/PRD.md +11 -11
- package/README.md +20 -2
- package/dist/cli/argv-utils.d.ts +5 -0
- package/dist/cli/argv-utils.js +34 -0
- package/dist/cli/argv-utils.js.map +1 -0
- package/dist/cli/bootstrap-args.d.ts +15 -0
- package/dist/cli/bootstrap-args.js +211 -0
- package/dist/cli/bootstrap-args.js.map +1 -1
- package/dist/cli/commander-usage.js +109 -3
- package/dist/cli/commander-usage.js.map +1 -1
- package/dist/cli/commands/completion.js +7 -3
- package/dist/cli/commands/completion.js.map +1 -1
- package/dist/cli/commands/contracts.d.ts +19 -0
- package/dist/cli/commands/contracts.js +40 -2
- package/dist/cli/commands/contracts.js.map +1 -1
- package/dist/cli/commands/create.js +112 -51
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/commands/docs.js +9 -2
- package/dist/cli/commands/docs.js.map +1 -1
- package/dist/cli/commands/extension.d.ts +12 -3
- package/dist/cli/commands/extension.js +421 -69
- package/dist/cli/commands/extension.js.map +1 -1
- package/dist/cli/commands/files.js +9 -2
- package/dist/cli/commands/files.js.map +1 -1
- package/dist/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.js +1 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts +2 -0
- package/dist/cli/commands/init.js +21 -1
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/metadata-normalizers.d.ts +4 -0
- package/dist/cli/commands/metadata-normalizers.js +37 -0
- package/dist/cli/commands/metadata-normalizers.js.map +1 -0
- package/dist/cli/commands/reindex.js +173 -135
- package/dist/cli/commands/reindex.js.map +1 -1
- package/dist/cli/commands/search.js +16 -6
- package/dist/cli/commands/search.js.map +1 -1
- package/dist/cli/commands/test.js +23 -8
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/commands/update.js +70 -39
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/upgrade.d.ts +63 -0
- package/dist/cli/commands/upgrade.js +260 -0
- package/dist/cli/commands/upgrade.js.map +1 -0
- package/dist/cli/error-guidance.d.ts +9 -1
- package/dist/cli/error-guidance.js +147 -6
- package/dist/cli/error-guidance.js.map +1 -1
- package/dist/cli/guide-topics.js +18 -16
- package/dist/cli/guide-topics.js.map +1 -1
- package/dist/cli/help-content.js +42 -2
- package/dist/cli/help-content.js.map +1 -1
- package/dist/cli/help-json-payload.js +11 -1
- package/dist/cli/help-json-payload.js.map +1 -1
- package/dist/cli/main.js +69 -6
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/register-setup.js +174 -82
- package/dist/cli/register-setup.js.map +1 -1
- package/dist/cli/telemetry-flush.d.ts +2 -0
- package/dist/cli/telemetry-flush.js +4 -0
- package/dist/cli/telemetry-flush.js.map +1 -0
- package/dist/cli.js +1 -2
- package/dist/cli.js.map +1 -1
- package/dist/core/extensions/extension-types.d.ts +72 -0
- package/dist/core/extensions/extension-types.js +24 -0
- package/dist/core/extensions/extension-types.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +1 -0
- package/dist/core/extensions/loader.js +766 -7
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/lock/lock.js +2 -0
- package/dist/core/lock/lock.js.map +1 -1
- package/dist/core/packages/manifest.d.ts +13 -0
- package/dist/core/packages/manifest.js +139 -0
- package/dist/core/packages/manifest.js.map +1 -0
- package/dist/core/sentry/instrument.d.ts +15 -0
- package/dist/core/sentry/instrument.js +35 -3
- package/dist/core/sentry/instrument.js.map +1 -1
- package/dist/core/shared/constants.js +20 -0
- package/dist/core/shared/constants.js.map +1 -1
- package/dist/core/shared/errors.d.ts +8 -0
- package/dist/core/shared/errors.js.map +1 -1
- package/dist/core/shared/levenshtein.d.ts +1 -0
- package/dist/core/shared/levenshtein.js +37 -0
- package/dist/core/shared/levenshtein.js.map +1 -0
- package/dist/core/store/paths.js +34 -1
- package/dist/core/store/paths.js.map +1 -1
- package/dist/core/store/settings.js +210 -1
- package/dist/core/store/settings.js.map +1 -1
- package/dist/core/telemetry/runtime.d.ts +1 -0
- package/dist/core/telemetry/runtime.js +102 -3
- package/dist/core/telemetry/runtime.js.map +1 -1
- package/dist/mcp/server.js +11 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/sdk/cli-contracts.d.ts +38 -17
- package/dist/sdk/cli-contracts.js +387 -35
- package/dist/sdk/cli-contracts.js.map +1 -1
- package/dist/sdk/index.d.ts +13 -1
- package/dist/sdk/index.js +9 -1
- package/dist/sdk/index.js.map +1 -1
- package/dist/types.d.ts +41 -0
- package/dist/types.js.map +1 -1
- package/docs/ARCHITECTURE.md +1 -1
- package/docs/CLAUDE_CODE_PLUGIN.md +39 -0
- package/docs/COMMANDS.md +14 -1
- package/docs/EXTENSIONS.md +782 -12
- package/docs/MIGRATION_CLI_SIMPLIFICATION.md +64 -0
- package/docs/QUICKSTART.md +10 -2
- package/docs/README.md +4 -6
- package/docs/SDK.md +445 -0
- package/docs/examples/ci/github-actions-pm-extension-gate.yml +53 -0
- package/docs/examples/ci/gitlab-ci-pm-extension-gate.yml +41 -0
- package/docs/examples/ci/jenkins-pm-extension-gate.Jenkinsfile +45 -0
- package/docs/examples/policy-restricted-extension/README.md +74 -0
- package/docs/examples/policy-restricted-extension/index.js +21 -0
- package/docs/examples/policy-restricted-extension/manifest.json +21 -0
- package/docs/examples/policy-restricted-extension/package.json +8 -0
- package/docs/examples/sdk-app-embedding/README.md +39 -0
- package/docs/examples/sdk-app-embedding/package.json +9 -0
- package/docs/examples/sdk-app-embedding/run-embedded-pm.mjs +61 -0
- package/docs/examples/sdk-contract-consumer/README.md +57 -0
- package/docs/examples/sdk-contract-consumer/inspect-contracts.mjs +47 -0
- package/docs/examples/sdk-contract-consumer/package.json +10 -0
- package/docs/examples/starter-extension/README.md +57 -42
- package/docs/examples/starter-extension/manifest.json +15 -0
- package/marketplace.json +3 -3
- package/package.json +5 -23
- package/packages/pm-beads/README.md +10 -0
- package/{.agents/pm → packages/pm-beads}/extensions/beads/index.js +24 -9
- package/packages/pm-beads/extensions/beads/index.ts +131 -0
- package/packages/pm-beads/package.json +17 -0
- package/packages/pm-todos/README.md +11 -0
- package/{.agents/pm → packages/pm-todos}/extensions/todos/index.js +24 -9
- package/packages/pm-todos/extensions/todos/index.ts +149 -0
- package/{.agents/pm → packages/pm-todos}/extensions/todos/runtime.js +1 -1
- package/{.agents/pm → packages/pm-todos}/extensions/todos/runtime.ts +1 -1
- package/packages/pm-todos/package.json +17 -0
- package/plugins/pm-cli-claude/.claude-plugin/plugin.json +2 -2
- package/plugins/pm-cli-claude/README.md +54 -14
- package/plugins/pm-cli-claude/agents/pm-delivery-chain.md +88 -0
- package/plugins/pm-cli-claude/agents/pm-triage-agent.md +83 -0
- package/plugins/pm-cli-claude/agents/pm-verification-agent.md +88 -0
- package/plugins/pm-cli-claude/hooks/session-start.mjs +35 -21
- package/.agents/pm/extensions/.managed-extensions.json +0 -42
- package/.agents/skills/HARNESS_COMPATIBILITY.md +0 -45
- package/.agents/skills/README.md +0 -21
- package/.agents/skills/pm-developer/SKILL.md +0 -73
- package/.agents/skills/pm-developer/references/COMMAND_PLAYBOOK.md +0 -48
- package/.agents/skills/pm-developer/references/PROMPTS.md +0 -17
- package/.agents/skills/pm-extensions/SKILL.md +0 -57
- package/.agents/skills/pm-extensions/references/LIFECYCLE.md +0 -40
- package/.agents/skills/pm-extensions/references/TROUBLESHOOTING.md +0 -25
- package/.agents/skills/pm-sdk/SKILL.md +0 -50
- package/.agents/skills/pm-sdk/references/INTEGRATION_CHECKLIST.md +0 -31
- package/.agents/skills/pm-sdk/references/PROMPTS.md +0 -13
- package/.agents/skills/pm-user/SKILL.md +0 -59
- package/.agents/skills/pm-user/references/PROMPTS.md +0 -17
- package/.agents/skills/pm-user/references/WORKFLOWS.md +0 -35
- package/.pi/README.md +0 -26
- package/.pi/extensions/pm-cli/index.js +0 -147
- package/.pi/prompts/pm-workflow.md +0 -5
- package/.pi/skills/pm-native/SKILL.md +0 -40
- package/.pi/skills/pm-release/SKILL.md +0 -35
- package/dist/pi/native.d.ts +0 -5
- package/dist/pi/native.js +0 -183
- package/dist/pi/native.js.map +0 -1
- package/docs/PI_PACKAGE.md +0 -56
- /package/{.agents/pm → packages/pm-beads}/extensions/beads/manifest.json +0 -0
- /package/{.agents/pm → packages/pm-beads}/extensions/beads/runtime.js +0 -0
- /package/{.agents/pm → packages/pm-beads}/extensions/beads/runtime.ts +0 -0
- /package/{.agents/pm → packages/pm-todos}/extensions/todos/manifest.json +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { pathToFileURL } from "node:url";
|
|
2
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
3
|
|
|
4
4
|
const PM_PACKAGE_ROOT_ENV = "PM_CLI_PACKAGE_ROOT";
|
|
5
|
+
const CURRENT_EXTENSION_ROOT = path.dirname(fileURLToPath(import.meta.url));
|
|
5
6
|
|
|
6
7
|
export const manifest = {
|
|
7
8
|
name: "builtin-beads-import",
|
|
@@ -48,17 +49,31 @@ function resolvePackageRootCandidates() {
|
|
|
48
49
|
async function loadRuntimeModule() {
|
|
49
50
|
const attempted = [];
|
|
50
51
|
for (const packageRoot of resolvePackageRootCandidates()) {
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
const modulePaths = [
|
|
53
|
+
path.join(packageRoot, ".agents", "pm", "extensions", "beads", "runtime.js"),
|
|
54
|
+
path.join(packageRoot, "packages", "pm-beads", "extensions", "beads", "runtime.js"),
|
|
55
|
+
];
|
|
56
|
+
for (const modulePath of modulePaths) {
|
|
57
|
+
attempted.push(modulePath);
|
|
58
|
+
try {
|
|
59
|
+
return await import(pathToFileURL(modulePath).href);
|
|
60
|
+
} catch {
|
|
61
|
+
// Try the next package-root candidate.
|
|
62
|
+
}
|
|
57
63
|
}
|
|
58
64
|
}
|
|
65
|
+
|
|
66
|
+
const localRuntimePath = path.join(CURRENT_EXTENSION_ROOT, "runtime.js");
|
|
67
|
+
attempted.push(localRuntimePath);
|
|
68
|
+
try {
|
|
69
|
+
return await import(pathToFileURL(localRuntimePath).href);
|
|
70
|
+
} catch {
|
|
71
|
+
// Fall through to the diagnostic below.
|
|
72
|
+
}
|
|
73
|
+
|
|
59
74
|
throw new Error(
|
|
60
|
-
"Unable to resolve
|
|
61
|
-
`Tried: ${attempted.join(", ")}. Ensure PM_CLI_PACKAGE_ROOT points to an installed pm package root.`,
|
|
75
|
+
"Unable to resolve packaged beads extension runtime module. " +
|
|
76
|
+
`Tried: ${attempted.join(", ")}. Ensure the installed extension includes runtime.js or PM_CLI_PACKAGE_ROOT points to an installed pm package root.`,
|
|
62
77
|
);
|
|
63
78
|
}
|
|
64
79
|
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
|
+
import type { CommandDefinition, ExtensionApi } from "../../../../src/core/extensions/loader.js";
|
|
4
|
+
import type { GlobalOptions } from "../../../../src/core/shared/command-types.js";
|
|
5
|
+
import type { BeadsImportOptions, BeadsImportResult } from "./runtime.js";
|
|
6
|
+
|
|
7
|
+
const PM_PACKAGE_ROOT_ENV = "PM_CLI_PACKAGE_ROOT";
|
|
8
|
+
const CURRENT_EXTENSION_ROOT = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
|
|
10
|
+
export const manifest = {
|
|
11
|
+
name: "builtin-beads-import",
|
|
12
|
+
version: "0.1.0",
|
|
13
|
+
entry: "./index.js",
|
|
14
|
+
priority: 0,
|
|
15
|
+
capabilities: ["commands", "schema"],
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type RuntimeModule = {
|
|
19
|
+
runBeadsImport?: (options: BeadsImportOptions, global: GlobalOptions) => Promise<BeadsImportResult>;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function asOptionalString(value: unknown): string | undefined {
|
|
23
|
+
return typeof value === "string" ? value : undefined;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function asBoolean(value: unknown): boolean | undefined {
|
|
27
|
+
return typeof value === "boolean" ? value : undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function toBeadsImportOptions(options: Record<string, unknown>): BeadsImportOptions {
|
|
31
|
+
return {
|
|
32
|
+
file: asOptionalString(options.file),
|
|
33
|
+
author: asOptionalString(options.author),
|
|
34
|
+
message: asOptionalString(options.message),
|
|
35
|
+
preserveSourceIds: asBoolean(options.preserveSourceIds),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function resolvePackageRootCandidates(): string[] {
|
|
40
|
+
const candidates: string[] = [];
|
|
41
|
+
const envRoot = process.env[PM_PACKAGE_ROOT_ENV];
|
|
42
|
+
if (typeof envRoot === "string" && envRoot.trim().length > 0) {
|
|
43
|
+
candidates.push(path.resolve(envRoot.trim()));
|
|
44
|
+
}
|
|
45
|
+
const argvEntry = typeof process.argv[1] === "string" ? process.argv[1].trim() : "";
|
|
46
|
+
if (argvEntry.length > 0) {
|
|
47
|
+
const resolvedEntry = path.resolve(argvEntry);
|
|
48
|
+
const entryDir = path.dirname(resolvedEntry);
|
|
49
|
+
candidates.push(path.resolve(entryDir, ".."));
|
|
50
|
+
candidates.push(path.resolve(entryDir, "../.."));
|
|
51
|
+
candidates.push(path.resolve(entryDir, "../../.."));
|
|
52
|
+
}
|
|
53
|
+
return [...new Set(candidates)];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function loadRuntimeModule(): Promise<RuntimeModule> {
|
|
57
|
+
const attempted: string[] = [];
|
|
58
|
+
for (const packageRoot of resolvePackageRootCandidates()) {
|
|
59
|
+
const modulePaths = [
|
|
60
|
+
path.join(packageRoot, ".agents", "pm", "extensions", "beads", "runtime.js"),
|
|
61
|
+
path.join(packageRoot, "packages", "pm-beads", "extensions", "beads", "runtime.js"),
|
|
62
|
+
];
|
|
63
|
+
for (const modulePath of modulePaths) {
|
|
64
|
+
attempted.push(modulePath);
|
|
65
|
+
try {
|
|
66
|
+
return await import(pathToFileURL(modulePath).href) as RuntimeModule;
|
|
67
|
+
} catch {
|
|
68
|
+
// Try the next package-root candidate.
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const localRuntimePath = path.join(CURRENT_EXTENSION_ROOT, "runtime.js");
|
|
74
|
+
attempted.push(localRuntimePath);
|
|
75
|
+
try {
|
|
76
|
+
return await import(pathToFileURL(localRuntimePath).href) as RuntimeModule;
|
|
77
|
+
} catch {
|
|
78
|
+
// Fall through to the diagnostic below.
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
throw new Error(
|
|
82
|
+
"Unable to resolve packaged beads extension runtime module. " +
|
|
83
|
+
`Tried: ${attempted.join(", ")}. Ensure the installed extension includes runtime.js or PM_CLI_PACKAGE_ROOT points to an installed pm package root.`,
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function runBeadsImportFromRuntime(options: BeadsImportOptions, global: GlobalOptions): Promise<BeadsImportResult> {
|
|
88
|
+
const runtime = await loadRuntimeModule();
|
|
89
|
+
if (typeof runtime.runBeadsImport !== "function") {
|
|
90
|
+
throw new Error("Bundled beads runtime module is missing runBeadsImport().");
|
|
91
|
+
}
|
|
92
|
+
return runtime.runBeadsImport(options, global);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function activate(api: ExtensionApi): void {
|
|
96
|
+
api.registerCommand({
|
|
97
|
+
name: "beads import",
|
|
98
|
+
description: "Import Beads JSONL records into pm items.",
|
|
99
|
+
flags: [
|
|
100
|
+
{
|
|
101
|
+
long: "--file",
|
|
102
|
+
value_name: "path",
|
|
103
|
+
value_type: "string",
|
|
104
|
+
description: "Path to the Beads JSONL source file.",
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
long: "--author",
|
|
108
|
+
value_name: "author",
|
|
109
|
+
value_type: "string",
|
|
110
|
+
description: "Override import mutation author.",
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
long: "--message",
|
|
114
|
+
value_name: "text",
|
|
115
|
+
value_type: "string",
|
|
116
|
+
description: "Override import history message.",
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
long: "--preserve-source-ids",
|
|
120
|
+
value_type: "boolean",
|
|
121
|
+
description: "Preserve source IDs from Beads payload records when possible.",
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
run: async (context) => runBeadsImportFromRuntime(toBeadsImportOptions(context.options), context.global),
|
|
125
|
+
} satisfies CommandDefinition);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export default {
|
|
129
|
+
manifest,
|
|
130
|
+
activate,
|
|
131
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@unbrained/pm-package-beads",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "First-party pm package for importing Beads JSONL records.",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"pm-package",
|
|
9
|
+
"project-management",
|
|
10
|
+
"beads"
|
|
11
|
+
],
|
|
12
|
+
"pm": {
|
|
13
|
+
"extensions": [
|
|
14
|
+
"extensions/beads"
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# pm Todos Package
|
|
2
|
+
|
|
3
|
+
First-party pm package for Todo markdown import and export.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pm install ./packages/pm-todos --project
|
|
7
|
+
pm todos import --folder .pm/todos
|
|
8
|
+
pm todos export --folder .pm/todos
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The package exposes the `todos import` and `todos export` extension commands through the `pm.extensions` package manifest. Runtime sources are authored in TypeScript and shipped with JavaScript entry artifacts for Node extension loading.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { pathToFileURL } from "node:url";
|
|
2
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
3
|
|
|
4
4
|
const PM_PACKAGE_ROOT_ENV = "PM_CLI_PACKAGE_ROOT";
|
|
5
|
+
const CURRENT_EXTENSION_ROOT = path.dirname(fileURLToPath(import.meta.url));
|
|
5
6
|
|
|
6
7
|
export const manifest = {
|
|
7
8
|
name: "builtin-todos-import-export",
|
|
@@ -49,17 +50,31 @@ function resolvePackageRootCandidates() {
|
|
|
49
50
|
async function loadRuntimeModule() {
|
|
50
51
|
const attempted = [];
|
|
51
52
|
for (const packageRoot of resolvePackageRootCandidates()) {
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
const modulePaths = [
|
|
54
|
+
path.join(packageRoot, ".agents", "pm", "extensions", "todos", "runtime.js"),
|
|
55
|
+
path.join(packageRoot, "packages", "pm-todos", "extensions", "todos", "runtime.js"),
|
|
56
|
+
];
|
|
57
|
+
for (const modulePath of modulePaths) {
|
|
58
|
+
attempted.push(modulePath);
|
|
59
|
+
try {
|
|
60
|
+
return await import(pathToFileURL(modulePath).href);
|
|
61
|
+
} catch {
|
|
62
|
+
// Try the next package-root candidate.
|
|
63
|
+
}
|
|
58
64
|
}
|
|
59
65
|
}
|
|
66
|
+
|
|
67
|
+
const localRuntimePath = path.join(CURRENT_EXTENSION_ROOT, "runtime.js");
|
|
68
|
+
attempted.push(localRuntimePath);
|
|
69
|
+
try {
|
|
70
|
+
return await import(pathToFileURL(localRuntimePath).href);
|
|
71
|
+
} catch {
|
|
72
|
+
// Fall through to the diagnostic below.
|
|
73
|
+
}
|
|
74
|
+
|
|
60
75
|
throw new Error(
|
|
61
|
-
"Unable to resolve
|
|
62
|
-
`Tried: ${attempted.join(", ")}. Ensure PM_CLI_PACKAGE_ROOT points to an installed pm package root.`,
|
|
76
|
+
"Unable to resolve packaged todos extension runtime module. " +
|
|
77
|
+
`Tried: ${attempted.join(", ")}. Ensure the installed extension includes runtime.js or PM_CLI_PACKAGE_ROOT points to an installed pm package root.`,
|
|
63
78
|
);
|
|
64
79
|
}
|
|
65
80
|
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
|
+
import type { CommandDefinition, ExtensionApi } from "../../../../src/core/extensions/loader.js";
|
|
4
|
+
import type { GlobalOptions } from "../../../../src/core/shared/command-types.js";
|
|
5
|
+
import type { TodosExportOptions, TodosExportResult, TodosImportOptions, TodosImportResult } from "./runtime.js";
|
|
6
|
+
|
|
7
|
+
const PM_PACKAGE_ROOT_ENV = "PM_CLI_PACKAGE_ROOT";
|
|
8
|
+
const CURRENT_EXTENSION_ROOT = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
|
|
10
|
+
export const manifest = {
|
|
11
|
+
name: "builtin-todos-import-export",
|
|
12
|
+
version: "0.1.0",
|
|
13
|
+
entry: "./index.js",
|
|
14
|
+
priority: 0,
|
|
15
|
+
capabilities: ["commands", "schema"],
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type RuntimeModule = {
|
|
19
|
+
runTodosImport?: (options: TodosImportOptions, global: GlobalOptions) => Promise<TodosImportResult>;
|
|
20
|
+
runTodosExport?: (options: TodosExportOptions, global: GlobalOptions) => Promise<TodosExportResult>;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
function asOptionalString(value: unknown): string | undefined {
|
|
24
|
+
return typeof value === "string" ? value : undefined;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function toImportOptions(options: Record<string, unknown>): TodosImportOptions {
|
|
28
|
+
return {
|
|
29
|
+
folder: asOptionalString(options.folder),
|
|
30
|
+
author: asOptionalString(options.author),
|
|
31
|
+
message: asOptionalString(options.message),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function toExportOptions(options: Record<string, unknown>): TodosExportOptions {
|
|
36
|
+
return {
|
|
37
|
+
folder: asOptionalString(options.folder),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function resolvePackageRootCandidates(): string[] {
|
|
42
|
+
const candidates: string[] = [];
|
|
43
|
+
const envRoot = process.env[PM_PACKAGE_ROOT_ENV];
|
|
44
|
+
if (typeof envRoot === "string" && envRoot.trim().length > 0) {
|
|
45
|
+
candidates.push(path.resolve(envRoot.trim()));
|
|
46
|
+
}
|
|
47
|
+
const argvEntry = typeof process.argv[1] === "string" ? process.argv[1].trim() : "";
|
|
48
|
+
if (argvEntry.length > 0) {
|
|
49
|
+
const resolvedEntry = path.resolve(argvEntry);
|
|
50
|
+
const entryDir = path.dirname(resolvedEntry);
|
|
51
|
+
candidates.push(path.resolve(entryDir, ".."));
|
|
52
|
+
candidates.push(path.resolve(entryDir, "../.."));
|
|
53
|
+
candidates.push(path.resolve(entryDir, "../../.."));
|
|
54
|
+
}
|
|
55
|
+
return [...new Set(candidates)];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function loadRuntimeModule(): Promise<RuntimeModule> {
|
|
59
|
+
const attempted: string[] = [];
|
|
60
|
+
for (const packageRoot of resolvePackageRootCandidates()) {
|
|
61
|
+
const modulePaths = [
|
|
62
|
+
path.join(packageRoot, ".agents", "pm", "extensions", "todos", "runtime.js"),
|
|
63
|
+
path.join(packageRoot, "packages", "pm-todos", "extensions", "todos", "runtime.js"),
|
|
64
|
+
];
|
|
65
|
+
for (const modulePath of modulePaths) {
|
|
66
|
+
attempted.push(modulePath);
|
|
67
|
+
try {
|
|
68
|
+
return await import(pathToFileURL(modulePath).href) as RuntimeModule;
|
|
69
|
+
} catch {
|
|
70
|
+
// Try the next package-root candidate.
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const localRuntimePath = path.join(CURRENT_EXTENSION_ROOT, "runtime.js");
|
|
76
|
+
attempted.push(localRuntimePath);
|
|
77
|
+
try {
|
|
78
|
+
return await import(pathToFileURL(localRuntimePath).href) as RuntimeModule;
|
|
79
|
+
} catch {
|
|
80
|
+
// Fall through to the diagnostic below.
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
throw new Error(
|
|
84
|
+
"Unable to resolve packaged todos extension runtime module. " +
|
|
85
|
+
`Tried: ${attempted.join(", ")}. Ensure the installed extension includes runtime.js or PM_CLI_PACKAGE_ROOT points to an installed pm package root.`,
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function runTodosImportFromRuntime(options: TodosImportOptions, global: GlobalOptions): Promise<TodosImportResult> {
|
|
90
|
+
const runtime = await loadRuntimeModule();
|
|
91
|
+
if (typeof runtime.runTodosImport !== "function") {
|
|
92
|
+
throw new Error("Bundled todos runtime module is missing runTodosImport().");
|
|
93
|
+
}
|
|
94
|
+
return runtime.runTodosImport(options, global);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function runTodosExportFromRuntime(options: TodosExportOptions, global: GlobalOptions): Promise<TodosExportResult> {
|
|
98
|
+
const runtime = await loadRuntimeModule();
|
|
99
|
+
if (typeof runtime.runTodosExport !== "function") {
|
|
100
|
+
throw new Error("Bundled todos runtime module is missing runTodosExport().");
|
|
101
|
+
}
|
|
102
|
+
return runtime.runTodosExport(options, global);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function activate(api: ExtensionApi): void {
|
|
106
|
+
api.registerCommand({
|
|
107
|
+
name: "todos import",
|
|
108
|
+
description: "Import Todo markdown files into pm items.",
|
|
109
|
+
flags: [
|
|
110
|
+
{
|
|
111
|
+
long: "--folder",
|
|
112
|
+
value_name: "path",
|
|
113
|
+
value_type: "string",
|
|
114
|
+
description: "Source folder containing Todo markdown files.",
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
long: "--author",
|
|
118
|
+
value_name: "author",
|
|
119
|
+
value_type: "string",
|
|
120
|
+
description: "Override import mutation author.",
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
long: "--message",
|
|
124
|
+
value_name: "text",
|
|
125
|
+
value_type: "string",
|
|
126
|
+
description: "Override import history message.",
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
run: async (context) => runTodosImportFromRuntime(toImportOptions(context.options), context.global),
|
|
130
|
+
} satisfies CommandDefinition);
|
|
131
|
+
api.registerCommand({
|
|
132
|
+
name: "todos export",
|
|
133
|
+
description: "Export pm items into Todo markdown files.",
|
|
134
|
+
flags: [
|
|
135
|
+
{
|
|
136
|
+
long: "--folder",
|
|
137
|
+
value_name: "path",
|
|
138
|
+
value_type: "string",
|
|
139
|
+
description: "Destination folder for exported Todo markdown files.",
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
run: async (context) => runTodosExportFromRuntime(toExportOptions(context.options), context.global),
|
|
143
|
+
} satisfies CommandDefinition);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export default {
|
|
147
|
+
manifest,
|
|
148
|
+
activate,
|
|
149
|
+
};
|
|
@@ -16,7 +16,7 @@ import { listAllFrontMatter, locateItem, readLocatedItem } from "../../../../dis
|
|
|
16
16
|
import { getHistoryPath, getItemPath, getSettingsPath, resolvePmRoot } from "../../../../dist/core/store/paths.js";
|
|
17
17
|
import { readSettings } from "../../../../dist/core/store/settings.js";
|
|
18
18
|
import { CONFIDENCE_TEXT_VALUES, ISSUE_SEVERITY_VALUES, RISK_VALUES } from "../../../../dist/types/index.js";
|
|
19
|
-
const DEFAULT_TODOS_FOLDER = ".
|
|
19
|
+
const DEFAULT_TODOS_FOLDER = ".pm/todos";
|
|
20
20
|
function isRecord(value) {
|
|
21
21
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22
22
|
}
|
|
@@ -20,7 +20,7 @@ import { readSettings } from "../../../../src/core/store/settings.js";
|
|
|
20
20
|
import { CONFIDENCE_TEXT_VALUES, ISSUE_SEVERITY_VALUES, RISK_VALUES } from "../../../../src/types/index.js";
|
|
21
21
|
import type { ItemDocument, ItemMetadata, ItemStatus, ItemType, PmSettings } from "../../../../src/types/index.js";
|
|
22
22
|
|
|
23
|
-
const DEFAULT_TODOS_FOLDER = ".
|
|
23
|
+
const DEFAULT_TODOS_FOLDER = ".pm/todos";
|
|
24
24
|
|
|
25
25
|
export interface TodosImportOptions {
|
|
26
26
|
folder?: string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@unbrained/pm-package-todos",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "First-party pm package for Todo markdown import and export.",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"pm-package",
|
|
9
|
+
"project-management",
|
|
10
|
+
"todos"
|
|
11
|
+
],
|
|
12
|
+
"pm": {
|
|
13
|
+
"extensions": [
|
|
14
|
+
"extensions/todos"
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pm-cli",
|
|
3
|
-
"description": "Native pm CLI integration for Claude Code — 18 MCP tools, 5 workflow skills, 14 slash commands, hybrid TUI task tracking (pm as persistent store + Claude Code task panel as live view), session context injection, and
|
|
4
|
-
"version": "1.
|
|
3
|
+
"description": "Native pm CLI integration for Claude Code — 18 MCP tools, 5 workflow skills, 14 slash commands, 3 subagents (coordinator, triage, verification), hybrid TUI task tracking (pm as persistent store + Claude Code task panel as live view), session context injection, and full git-based project management without leaving Claude Code.",
|
|
4
|
+
"version": "1.3.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "unbrained",
|
|
7
7
|
"url": "https://github.com/unbraind/pm-cli"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# pm CLI — Claude Code Plugin
|
|
2
2
|
|
|
3
|
-
Native pm CLI integration for Claude Code. Use pm project management tools directly through Claude Code's MCP protocol — no shell invocations, no context switching.
|
|
3
|
+
Native pm CLI integration for Claude Code. Use pm project management tools directly through Claude Code's MCP protocol — no shell invocations, no context switching, no `pm` CLI required.
|
|
4
4
|
|
|
5
5
|
## What's Included
|
|
6
6
|
|
|
@@ -9,29 +9,37 @@ Native pm CLI integration for Claude Code. Use pm project management tools direc
|
|
|
9
9
|
| **18 MCP tools** | Full pm surface: context, search, list, get, create, update, claim, release, close, comments, files, docs, test, validate, health, contracts, guide + `pm_run` for everything else |
|
|
10
10
|
| **5 skills** | `pm-workflow`, `pm-developer`, `pm-release`, `pm-audit`, `pm-planner` — auto-loaded as Claude Code skills |
|
|
11
11
|
| **14 slash commands** | Full lifecycle coverage — status, start, close, triage, audit, search, new, list, calendar, developer, planner, release, workflow, init |
|
|
12
|
+
| **3 subagents** | `pm-coordinator` (batch/multi-item), `pm-triage-agent` (duplicate-safe item creation), `pm-verification-agent` (evidence + close readiness), and a `pm-delivery-chain` orchestrator |
|
|
12
13
|
| **Hybrid TUI tracking** | pm items sync to Claude Code's task panel — pm is the persistent store, the task panel is the live session view |
|
|
13
|
-
| **Session hook** | Injects active pm item summary at session start when pm is initialized |
|
|
14
|
-
| **pm-coordinator agent** | Subagent for coordinating multi-item and batch operations |
|
|
14
|
+
| **Session hook** | Injects active pm item summary at session start when pm is initialized (uses native modules, no CLI required) |
|
|
15
15
|
|
|
16
16
|
## Installation
|
|
17
17
|
|
|
18
|
-
### Option A: Plugin marketplace (recommended)
|
|
18
|
+
### Option A: Plugin marketplace — canonical install (recommended)
|
|
19
19
|
|
|
20
20
|
```
|
|
21
|
-
/plugin install pm-cli@pm
|
|
21
|
+
/plugin install pm-cli@pm
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
To add the marketplace first (if not already configured):
|
|
24
|
+
First time: add the marketplace if it's not configured yet:
|
|
27
25
|
|
|
28
26
|
```bash
|
|
29
27
|
claude plugin marketplace add /path/to/pm-cli
|
|
30
|
-
# or
|
|
28
|
+
# or after npm publish:
|
|
31
29
|
# claude plugin marketplace add unbraind/pm-cli
|
|
32
30
|
```
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
This installs all 18 MCP tools, 5 skills, 14 slash commands, 3 subagents, hybrid TUI tracking, and the session hook in one step.
|
|
33
|
+
|
|
34
|
+
### Option B: Legacy marketplace alias (also works)
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
/plugin install pm-cli@pm-cli
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Both `pm` and `pm-cli` marketplace IDs resolve to the same plugin.
|
|
41
|
+
|
|
42
|
+
### Option C: Global MCP server via Claude Code CLI (MCP tools only)
|
|
35
43
|
|
|
36
44
|
```bash
|
|
37
45
|
claude mcp add --transport stdio pm-cli-native -- npx -y @unbrained/pm-cli pm-mcp
|
|
@@ -39,9 +47,9 @@ claude mcp add --transport stdio pm-cli-native -- npx -y @unbrained/pm-cli pm-mc
|
|
|
39
47
|
|
|
40
48
|
This gives you the 18 MCP tools but not the skills, slash commands, or session hook.
|
|
41
49
|
|
|
42
|
-
### Option
|
|
50
|
+
### Option D: Direct `.mcp.json` (project-scoped MCP only)
|
|
43
51
|
|
|
44
|
-
Add to your project's `.mcp.json
|
|
52
|
+
Add to your project's `.mcp.json`:
|
|
45
53
|
|
|
46
54
|
```json
|
|
47
55
|
{
|
|
@@ -70,6 +78,9 @@ Start working on the authentication bug.
|
|
|
70
78
|
|
|
71
79
|
Close pm-xxxx — the fix is complete.
|
|
72
80
|
→ Claude runs /pm-close-task pm-xxxx with evidence linking, closes pm item, marks task panel entry completed
|
|
81
|
+
|
|
82
|
+
Triage this request: add dark mode toggle to settings screen
|
|
83
|
+
→ Claude spawns pm-triage-agent, checks duplicates, creates pm item with AC, hands off to /pm-developer
|
|
73
84
|
```
|
|
74
85
|
|
|
75
86
|
## Hybrid TUI Task Tracking
|
|
@@ -116,6 +127,20 @@ This means you get full history in pm (survives restarts, visible in `pm list`)
|
|
|
116
127
|
| `pm-audit` | Repository health audits — validate, dedupe, aggregate |
|
|
117
128
|
| `pm-planner` | Planning — decompose epics, prioritize backlog, triage |
|
|
118
129
|
|
|
130
|
+
## Subagents
|
|
131
|
+
|
|
132
|
+
| Agent | Role |
|
|
133
|
+
|-------|------|
|
|
134
|
+
| `pm-coordinator` | Multi-item and batch coordination — batch updates, audit workflows, release gate sequences |
|
|
135
|
+
| `pm-triage-agent` | Duplicate-safe item creation — orient, search, establish lineage, produce implementation-ready item |
|
|
136
|
+
| `pm-verification-agent` | Closure evidence — read item, check AC, run tests, validate, produce structured close recommendation |
|
|
137
|
+
| `pm-delivery-chain` | End-to-end orchestrator — runs triage → implement → verify as a single tracked loop |
|
|
138
|
+
|
|
139
|
+
Use subagents via Claude Code's built-in `Agent` tool:
|
|
140
|
+
```
|
|
141
|
+
Spawn pm-triage-agent to set up the pm item for: add OAuth2 login support
|
|
142
|
+
```
|
|
143
|
+
|
|
119
144
|
## MCP Tools Reference
|
|
120
145
|
|
|
121
146
|
### Narrow tools (prefer these)
|
|
@@ -163,6 +188,21 @@ All skills and commands implement this pattern for every claimed item:
|
|
|
163
188
|
→ [✔ appears in Claude Code task panel]
|
|
164
189
|
```
|
|
165
190
|
|
|
191
|
+
## Session Context Injection
|
|
192
|
+
|
|
193
|
+
At session start, the hook runs natively (no `pm` CLI required):
|
|
194
|
+
- Uses `npx @unbrained/pm-cli` without requiring a global install
|
|
195
|
+
- Injects a compact summary of in-progress/open/blocked items
|
|
196
|
+
|
|
197
|
+
Example output:
|
|
198
|
+
```
|
|
199
|
+
pm tracker: 2 in_progress, 1 open
|
|
200
|
+
• [pm-abc1] Add OAuth2 login (in_progress)
|
|
201
|
+
• [pm-abc2] Fix test flakiness (in_progress)
|
|
202
|
+
• [pm-abc3] Update docs (open)
|
|
203
|
+
Use pm_context tool or /pm-status for full details.
|
|
204
|
+
```
|
|
205
|
+
|
|
166
206
|
## Safety
|
|
167
207
|
|
|
168
208
|
- Never pass `path` during real repository tracking — only use it for sandbox/test runs.
|
|
@@ -173,12 +213,12 @@ All skills and commands implement this pattern for every claimed item:
|
|
|
173
213
|
## Requirements
|
|
174
214
|
|
|
175
215
|
- Node.js ≥ 20
|
|
176
|
-
- pm CLI
|
|
216
|
+
- pm CLI resolved automatically via local dist (in repo) or `npx @unbrained/pm-cli` (no global install needed)
|
|
177
217
|
- Project initialized with `pm init` (or use `/pm-init`)
|
|
178
218
|
|
|
179
219
|
## Links
|
|
180
220
|
|
|
181
221
|
- [pm CLI docs](https://github.com/unbraind/pm-cli/tree/main/docs)
|
|
182
|
-
- [Command reference](https://github.com/unbraind/pm-cli/blob/main/docs/COMMANDS.md)
|
|
183
222
|
- [Architecture guide](https://github.com/unbraind/pm-cli/blob/main/docs/ARCHITECTURE.md)
|
|
223
|
+
- [Extension guide](https://github.com/unbraind/pm-cli/blob/main/docs/EXTENSIONS.md)
|
|
184
224
|
- [CHANGELOG](https://github.com/unbraind/pm-cli/blob/main/CHANGELOG.md)
|