@unbrained/pm-cli 2026.3.9

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.
Files changed (245) hide show
  1. package/.pi/extensions/pm-cli/index.ts +778 -0
  2. package/AGENTS.md +475 -0
  3. package/LICENSE +21 -0
  4. package/PRD.md +1390 -0
  5. package/README.md +655 -0
  6. package/dist/cli/commands/activity.d.ts +14 -0
  7. package/dist/cli/commands/activity.js +80 -0
  8. package/dist/cli/commands/activity.js.map +1 -0
  9. package/dist/cli/commands/append.d.ts +13 -0
  10. package/dist/cli/commands/append.js +46 -0
  11. package/dist/cli/commands/append.js.map +1 -0
  12. package/dist/cli/commands/beads.d.ts +15 -0
  13. package/dist/cli/commands/beads.js +475 -0
  14. package/dist/cli/commands/beads.js.map +1 -0
  15. package/dist/cli/commands/claim.d.ts +19 -0
  16. package/dist/cli/commands/claim.js +79 -0
  17. package/dist/cli/commands/claim.js.map +1 -0
  18. package/dist/cli/commands/close.d.ts +12 -0
  19. package/dist/cli/commands/close.js +58 -0
  20. package/dist/cli/commands/close.js.map +1 -0
  21. package/dist/cli/commands/comments.d.ts +15 -0
  22. package/dist/cli/commands/comments.js +80 -0
  23. package/dist/cli/commands/comments.js.map +1 -0
  24. package/dist/cli/commands/completion.d.ts +10 -0
  25. package/dist/cli/commands/completion.js +469 -0
  26. package/dist/cli/commands/completion.js.map +1 -0
  27. package/dist/cli/commands/config.d.ts +15 -0
  28. package/dist/cli/commands/config.js +72 -0
  29. package/dist/cli/commands/config.js.map +1 -0
  30. package/dist/cli/commands/create.d.ts +60 -0
  31. package/dist/cli/commands/create.js +456 -0
  32. package/dist/cli/commands/create.js.map +1 -0
  33. package/dist/cli/commands/delete.d.ts +12 -0
  34. package/dist/cli/commands/delete.js +33 -0
  35. package/dist/cli/commands/delete.js.map +1 -0
  36. package/dist/cli/commands/docs.d.ts +16 -0
  37. package/dist/cli/commands/docs.js +113 -0
  38. package/dist/cli/commands/docs.js.map +1 -0
  39. package/dist/cli/commands/files.d.ts +17 -0
  40. package/dist/cli/commands/files.js +113 -0
  41. package/dist/cli/commands/files.js.map +1 -0
  42. package/dist/cli/commands/gc.d.ts +9 -0
  43. package/dist/cli/commands/gc.js +80 -0
  44. package/dist/cli/commands/gc.js.map +1 -0
  45. package/dist/cli/commands/get.d.ts +12 -0
  46. package/dist/cli/commands/get.js +28 -0
  47. package/dist/cli/commands/get.js.map +1 -0
  48. package/dist/cli/commands/health.d.ts +15 -0
  49. package/dist/cli/commands/health.js +288 -0
  50. package/dist/cli/commands/health.js.map +1 -0
  51. package/dist/cli/commands/history.d.ts +13 -0
  52. package/dist/cli/commands/history.js +72 -0
  53. package/dist/cli/commands/history.js.map +1 -0
  54. package/dist/cli/commands/index.d.ts +26 -0
  55. package/dist/cli/commands/index.js +27 -0
  56. package/dist/cli/commands/index.js.map +1 -0
  57. package/dist/cli/commands/init.d.ts +10 -0
  58. package/dist/cli/commands/init.js +59 -0
  59. package/dist/cli/commands/init.js.map +1 -0
  60. package/dist/cli/commands/install.d.ts +18 -0
  61. package/dist/cli/commands/install.js +87 -0
  62. package/dist/cli/commands/install.js.map +1 -0
  63. package/dist/cli/commands/list.d.ts +21 -0
  64. package/dist/cli/commands/list.js +137 -0
  65. package/dist/cli/commands/list.js.map +1 -0
  66. package/dist/cli/commands/reindex.d.ts +16 -0
  67. package/dist/cli/commands/reindex.js +154 -0
  68. package/dist/cli/commands/reindex.js.map +1 -0
  69. package/dist/cli/commands/restore.d.ts +20 -0
  70. package/dist/cli/commands/restore.js +208 -0
  71. package/dist/cli/commands/restore.js.map +1 -0
  72. package/dist/cli/commands/search.d.ts +45 -0
  73. package/dist/cli/commands/search.js +531 -0
  74. package/dist/cli/commands/search.js.map +1 -0
  75. package/dist/cli/commands/stats.d.ts +13 -0
  76. package/dist/cli/commands/stats.js +88 -0
  77. package/dist/cli/commands/stats.js.map +1 -0
  78. package/dist/cli/commands/test-all.d.ts +30 -0
  79. package/dist/cli/commands/test-all.js +157 -0
  80. package/dist/cli/commands/test-all.js.map +1 -0
  81. package/dist/cli/commands/test.d.ts +29 -0
  82. package/dist/cli/commands/test.js +492 -0
  83. package/dist/cli/commands/test.js.map +1 -0
  84. package/dist/cli/commands/update.d.ts +52 -0
  85. package/dist/cli/commands/update.js +467 -0
  86. package/dist/cli/commands/update.js.map +1 -0
  87. package/dist/cli/extension-command-options.d.ts +1 -0
  88. package/dist/cli/extension-command-options.js +76 -0
  89. package/dist/cli/extension-command-options.js.map +1 -0
  90. package/dist/cli/main.d.ts +2 -0
  91. package/dist/cli/main.js +1494 -0
  92. package/dist/cli/main.js.map +1 -0
  93. package/dist/cli.d.ts +2 -0
  94. package/dist/cli.js +3 -0
  95. package/dist/cli.js.map +1 -0
  96. package/dist/command-types.d.ts +1 -0
  97. package/dist/command-types.js +2 -0
  98. package/dist/command-types.js.map +1 -0
  99. package/dist/constants.d.ts +1 -0
  100. package/dist/constants.js +2 -0
  101. package/dist/constants.js.map +1 -0
  102. package/dist/core/extensions/builtins.d.ts +3 -0
  103. package/dist/core/extensions/builtins.js +47 -0
  104. package/dist/core/extensions/builtins.js.map +1 -0
  105. package/dist/core/extensions/index.d.ts +13 -0
  106. package/dist/core/extensions/index.js +88 -0
  107. package/dist/core/extensions/index.js.map +1 -0
  108. package/dist/core/extensions/loader.d.ts +301 -0
  109. package/dist/core/extensions/loader.js +917 -0
  110. package/dist/core/extensions/loader.js.map +1 -0
  111. package/dist/core/fs/fs-utils.d.ts +6 -0
  112. package/dist/core/fs/fs-utils.js +58 -0
  113. package/dist/core/fs/fs-utils.js.map +1 -0
  114. package/dist/core/fs/index.d.ts +1 -0
  115. package/dist/core/fs/index.js +2 -0
  116. package/dist/core/fs/index.js.map +1 -0
  117. package/dist/core/history/history.d.ts +12 -0
  118. package/dist/core/history/history.js +44 -0
  119. package/dist/core/history/history.js.map +1 -0
  120. package/dist/core/history/index.d.ts +1 -0
  121. package/dist/core/history/index.js +2 -0
  122. package/dist/core/history/index.js.map +1 -0
  123. package/dist/core/item/id.d.ts +3 -0
  124. package/dist/core/item/id.js +54 -0
  125. package/dist/core/item/id.js.map +1 -0
  126. package/dist/core/item/index.d.ts +3 -0
  127. package/dist/core/item/index.js +4 -0
  128. package/dist/core/item/index.js.map +1 -0
  129. package/dist/core/item/item-format.d.ts +9 -0
  130. package/dist/core/item/item-format.js +363 -0
  131. package/dist/core/item/item-format.js.map +1 -0
  132. package/dist/core/item/parse.d.ts +3 -0
  133. package/dist/core/item/parse.js +72 -0
  134. package/dist/core/item/parse.js.map +1 -0
  135. package/dist/core/lock/index.d.ts +1 -0
  136. package/dist/core/lock/index.js +2 -0
  137. package/dist/core/lock/index.js.map +1 -0
  138. package/dist/core/lock/lock.d.ts +1 -0
  139. package/dist/core/lock/lock.js +100 -0
  140. package/dist/core/lock/lock.js.map +1 -0
  141. package/dist/core/output/output.d.ts +7 -0
  142. package/dist/core/output/output.js +79 -0
  143. package/dist/core/output/output.js.map +1 -0
  144. package/dist/core/search/cache.d.ts +17 -0
  145. package/dist/core/search/cache.js +212 -0
  146. package/dist/core/search/cache.js.map +1 -0
  147. package/dist/core/search/embedding-batches.d.ts +7 -0
  148. package/dist/core/search/embedding-batches.js +54 -0
  149. package/dist/core/search/embedding-batches.js.map +1 -0
  150. package/dist/core/search/providers.d.ts +59 -0
  151. package/dist/core/search/providers.js +265 -0
  152. package/dist/core/search/providers.js.map +1 -0
  153. package/dist/core/search/vector-stores.d.ts +89 -0
  154. package/dist/core/search/vector-stores.js +546 -0
  155. package/dist/core/search/vector-stores.js.map +1 -0
  156. package/dist/core/shared/command-types.d.ts +7 -0
  157. package/dist/core/shared/command-types.js +2 -0
  158. package/dist/core/shared/command-types.js.map +1 -0
  159. package/dist/core/shared/constants.d.ts +19 -0
  160. package/dist/core/shared/constants.js +134 -0
  161. package/dist/core/shared/constants.js.map +1 -0
  162. package/dist/core/shared/errors.d.ts +4 -0
  163. package/dist/core/shared/errors.js +9 -0
  164. package/dist/core/shared/errors.js.map +1 -0
  165. package/dist/core/shared/index.d.ts +3 -0
  166. package/dist/core/shared/index.js +4 -0
  167. package/dist/core/shared/index.js.map +1 -0
  168. package/dist/core/shared/serialization.d.ts +3 -0
  169. package/dist/core/shared/serialization.js +70 -0
  170. package/dist/core/shared/serialization.js.map +1 -0
  171. package/dist/core/shared/time.d.ts +3 -0
  172. package/dist/core/shared/time.js +28 -0
  173. package/dist/core/shared/time.js.map +1 -0
  174. package/dist/core/store/index.d.ts +3 -0
  175. package/dist/core/store/index.js +4 -0
  176. package/dist/core/store/index.js.map +1 -0
  177. package/dist/core/store/item-store.d.ts +42 -0
  178. package/dist/core/store/item-store.js +186 -0
  179. package/dist/core/store/item-store.js.map +1 -0
  180. package/dist/core/store/paths.d.ts +8 -0
  181. package/dist/core/store/paths.js +29 -0
  182. package/dist/core/store/paths.js.map +1 -0
  183. package/dist/core/store/settings.d.ts +4 -0
  184. package/dist/core/store/settings.js +148 -0
  185. package/dist/core/store/settings.js.map +1 -0
  186. package/dist/errors.d.ts +1 -0
  187. package/dist/errors.js +2 -0
  188. package/dist/errors.js.map +1 -0
  189. package/dist/extensions/builtins/beads/index.d.ts +8 -0
  190. package/dist/extensions/builtins/beads/index.js +29 -0
  191. package/dist/extensions/builtins/beads/index.js.map +1 -0
  192. package/dist/extensions/builtins/todos/import-export.d.ts +26 -0
  193. package/dist/extensions/builtins/todos/import-export.js +460 -0
  194. package/dist/extensions/builtins/todos/import-export.js.map +1 -0
  195. package/dist/extensions/builtins/todos/index.d.ts +8 -0
  196. package/dist/extensions/builtins/todos/index.js +38 -0
  197. package/dist/extensions/builtins/todos/index.js.map +1 -0
  198. package/dist/fs-utils.d.ts +1 -0
  199. package/dist/fs-utils.js +2 -0
  200. package/dist/fs-utils.js.map +1 -0
  201. package/dist/history.d.ts +1 -0
  202. package/dist/history.js +2 -0
  203. package/dist/history.js.map +1 -0
  204. package/dist/id.d.ts +1 -0
  205. package/dist/id.js +2 -0
  206. package/dist/id.js.map +1 -0
  207. package/dist/item-format.d.ts +1 -0
  208. package/dist/item-format.js +2 -0
  209. package/dist/item-format.js.map +1 -0
  210. package/dist/item-store.d.ts +1 -0
  211. package/dist/item-store.js +2 -0
  212. package/dist/item-store.js.map +1 -0
  213. package/dist/lock.d.ts +1 -0
  214. package/dist/lock.js +2 -0
  215. package/dist/lock.js.map +1 -0
  216. package/dist/output.d.ts +1 -0
  217. package/dist/output.js +2 -0
  218. package/dist/output.js.map +1 -0
  219. package/dist/parse.d.ts +1 -0
  220. package/dist/parse.js +2 -0
  221. package/dist/parse.js.map +1 -0
  222. package/dist/paths.d.ts +1 -0
  223. package/dist/paths.js +2 -0
  224. package/dist/paths.js.map +1 -0
  225. package/dist/serialization.d.ts +1 -0
  226. package/dist/serialization.js +2 -0
  227. package/dist/serialization.js.map +1 -0
  228. package/dist/settings.d.ts +1 -0
  229. package/dist/settings.js +2 -0
  230. package/dist/settings.js.map +1 -0
  231. package/dist/time.d.ts +1 -0
  232. package/dist/time.js +2 -0
  233. package/dist/time.js.map +1 -0
  234. package/dist/types/index.d.ts +1 -0
  235. package/dist/types/index.js +2 -0
  236. package/dist/types/index.js.map +1 -0
  237. package/dist/types.d.ts +179 -0
  238. package/dist/types.js +21 -0
  239. package/dist/types.js.map +1 -0
  240. package/docs/ARCHITECTURE.md +246 -0
  241. package/docs/EXTENSIONS.md +329 -0
  242. package/docs/RELEASING.md +65 -0
  243. package/package.json +79 -0
  244. package/scripts/install.ps1 +112 -0
  245. package/scripts/install.sh +113 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serialization.js","sourceRoot":"","sources":["../src/serialization.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAC"}
@@ -0,0 +1 @@
1
+ export * from "./core/store/settings.js";
@@ -0,0 +1,2 @@
1
+ export * from "./core/store/settings.js";
2
+ //# sourceMappingURL=settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC"}
package/dist/time.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./core/shared/time.js";
package/dist/time.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./core/shared/time.js";
2
+ //# sourceMappingURL=time.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time.js","sourceRoot":"","sources":["../src/time.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1 @@
1
+ export * from "../types.js";
@@ -0,0 +1,2 @@
1
+ export * from "../types.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
@@ -0,0 +1,179 @@
1
+ export declare const ITEM_TYPE_VALUES: readonly ["Epic", "Feature", "Task", "Chore", "Issue"];
2
+ export type ItemType = (typeof ITEM_TYPE_VALUES)[number];
3
+ export declare const STATUS_VALUES: readonly ["draft", "open", "in_progress", "blocked", "closed", "canceled"];
4
+ export type ItemStatus = (typeof STATUS_VALUES)[number];
5
+ export declare const DEPENDENCY_KIND_VALUES: readonly ["blocks", "parent", "child", "related", "discovered_from"];
6
+ export type DependencyKind = (typeof DEPENDENCY_KIND_VALUES)[number];
7
+ export declare const SCOPE_VALUES: readonly ["project", "global"];
8
+ export type LinkScope = (typeof SCOPE_VALUES)[number];
9
+ export declare const RISK_VALUES: readonly ["low", "medium", "high", "critical"];
10
+ export type RiskLevel = (typeof RISK_VALUES)[number];
11
+ export declare const ISSUE_SEVERITY_VALUES: readonly ["low", "medium", "high", "critical"];
12
+ export type IssueSeverity = (typeof ISSUE_SEVERITY_VALUES)[number];
13
+ export declare const CONFIDENCE_TEXT_VALUES: readonly ["low", "medium", "high"];
14
+ export type ConfidenceTextLevel = (typeof CONFIDENCE_TEXT_VALUES)[number];
15
+ export type ConfidenceValue = number | ConfidenceTextLevel;
16
+ export interface Dependency {
17
+ id: string;
18
+ kind: DependencyKind;
19
+ created_at: string;
20
+ author?: string;
21
+ }
22
+ export interface Comment {
23
+ created_at: string;
24
+ author: string;
25
+ text: string;
26
+ }
27
+ export interface LogNote {
28
+ created_at: string;
29
+ author: string;
30
+ text: string;
31
+ }
32
+ export interface LinkedFile {
33
+ path: string;
34
+ scope: LinkScope;
35
+ note?: string;
36
+ }
37
+ export interface LinkedTest {
38
+ command?: string;
39
+ path?: string;
40
+ scope: LinkScope;
41
+ timeout_seconds?: number;
42
+ note?: string;
43
+ }
44
+ export interface LinkedDoc {
45
+ path: string;
46
+ scope: LinkScope;
47
+ note?: string;
48
+ }
49
+ export interface ItemFrontMatter {
50
+ id: string;
51
+ title: string;
52
+ description: string;
53
+ type: ItemType;
54
+ status: ItemStatus;
55
+ priority: 0 | 1 | 2 | 3 | 4;
56
+ tags: string[];
57
+ created_at: string;
58
+ updated_at: string;
59
+ deadline?: string;
60
+ assignee?: string;
61
+ author?: string;
62
+ estimated_minutes?: number;
63
+ acceptance_criteria?: string;
64
+ definition_of_ready?: string;
65
+ order?: number;
66
+ goal?: string;
67
+ objective?: string;
68
+ value?: string;
69
+ impact?: string;
70
+ outcome?: string;
71
+ why_now?: string;
72
+ parent?: string;
73
+ reviewer?: string;
74
+ risk?: "low" | "medium" | "high" | "critical";
75
+ confidence?: ConfidenceValue;
76
+ sprint?: string;
77
+ release?: string;
78
+ blocked_by?: string;
79
+ blocked_reason?: string;
80
+ unblock_note?: string;
81
+ reporter?: string;
82
+ severity?: IssueSeverity;
83
+ environment?: string;
84
+ repro_steps?: string;
85
+ resolution?: string;
86
+ expected_result?: string;
87
+ actual_result?: string;
88
+ affected_version?: string;
89
+ fixed_version?: string;
90
+ component?: string;
91
+ regression?: boolean;
92
+ customer_impact?: string;
93
+ dependencies?: Dependency[];
94
+ comments?: Comment[];
95
+ notes?: LogNote[];
96
+ learnings?: LogNote[];
97
+ files?: LinkedFile[];
98
+ tests?: LinkedTest[];
99
+ docs?: LinkedDoc[];
100
+ close_reason?: string;
101
+ }
102
+ export interface ItemDocument {
103
+ front_matter: ItemFrontMatter;
104
+ body: string;
105
+ }
106
+ export interface HistoryPatchOp {
107
+ op: "add" | "remove" | "replace" | "move" | "copy" | "test";
108
+ path: string;
109
+ from?: string;
110
+ value?: unknown;
111
+ }
112
+ export interface HistoryEntry {
113
+ ts: string;
114
+ author: string;
115
+ op: string;
116
+ patch: HistoryPatchOp[];
117
+ before_hash: string;
118
+ after_hash: string;
119
+ message?: string;
120
+ }
121
+ export interface PmSettings {
122
+ version: number;
123
+ id_prefix: string;
124
+ author_default: string;
125
+ locks: {
126
+ ttl_seconds: number;
127
+ };
128
+ output: {
129
+ default_format: "toon" | "json";
130
+ };
131
+ workflow: {
132
+ definition_of_done: string[];
133
+ };
134
+ extensions: {
135
+ enabled: string[];
136
+ disabled: string[];
137
+ };
138
+ search: {
139
+ score_threshold: number;
140
+ hybrid_semantic_weight: number;
141
+ max_results: number;
142
+ embedding_model: string;
143
+ embedding_batch_size: number;
144
+ scanner_max_batch_retries: number;
145
+ tuning?: {
146
+ title_exact_bonus?: number;
147
+ title_weight?: number;
148
+ description_weight?: number;
149
+ tags_weight?: number;
150
+ status_weight?: number;
151
+ body_weight?: number;
152
+ comments_weight?: number;
153
+ notes_weight?: number;
154
+ learnings_weight?: number;
155
+ dependencies_weight?: number;
156
+ linked_content_weight?: number;
157
+ };
158
+ };
159
+ providers: {
160
+ openai: {
161
+ base_url: string;
162
+ api_key: string;
163
+ model: string;
164
+ };
165
+ ollama: {
166
+ base_url: string;
167
+ model: string;
168
+ };
169
+ };
170
+ vector_store: {
171
+ qdrant: {
172
+ url: string;
173
+ api_key: string;
174
+ };
175
+ lancedb: {
176
+ path: string;
177
+ };
178
+ };
179
+ }
package/dist/types.js ADDED
@@ -0,0 +1,21 @@
1
+ export const ITEM_TYPE_VALUES = ["Epic", "Feature", "Task", "Chore", "Issue"];
2
+ export const STATUS_VALUES = [
3
+ "draft",
4
+ "open",
5
+ "in_progress",
6
+ "blocked",
7
+ "closed",
8
+ "canceled",
9
+ ];
10
+ export const DEPENDENCY_KIND_VALUES = [
11
+ "blocks",
12
+ "parent",
13
+ "child",
14
+ "related",
15
+ "discovered_from",
16
+ ];
17
+ export const SCOPE_VALUES = ["project", "global"];
18
+ export const RISK_VALUES = ["low", "medium", "high", "critical"];
19
+ export const ISSUE_SEVERITY_VALUES = ["low", "medium", "high", "critical"];
20
+ export const CONFIDENCE_TEXT_VALUES = ["low", "medium", "high"];
21
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAU,CAAC;AAGvF,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,OAAO;IACP,MAAM;IACN,aAAa;IACb,SAAS;IACT,QAAQ;IACR,UAAU;CACF,CAAC;AAGX,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,SAAS;IACT,iBAAiB;CACT,CAAC;AAGX,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAU,CAAC;AAG3D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAU,CAAC;AAG1E,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAU,CAAC;AAGpF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAU,CAAC"}
@@ -0,0 +1,246 @@
1
+ # pm-cli Architecture
2
+
3
+ This document describes the internal architecture of `pm-cli` for contributors and maintainers.
4
+
5
+ ## Overview
6
+
7
+ `pm-cli` is a TypeScript ESM CLI built on Node.js 20+. It follows a clean separation between CLI wiring and domain logic:
8
+
9
+ ```
10
+ src/
11
+ cli/ CLI layer: command registration, option parsing, output rendering
12
+ core/ Domain logic: storage, locking, history, search, extensions
13
+ extensions/ Built-in extension implementations (beads, todos)
14
+ types/ Shared TypeScript type definitions
15
+ ```
16
+
17
+ ## Source Tree
18
+
19
+ ```
20
+ src/
21
+ cli.ts Main CLI entry (shim that imports cli/main.ts)
22
+ cli/
23
+ main.ts Command registration with commander; global option wiring
24
+ commands/
25
+ init.ts pm init
26
+ create.ts pm create (full schema flag surface)
27
+ get.ts pm get
28
+ update.ts pm update
29
+ append.ts pm append
30
+ close.ts pm close
31
+ delete.ts pm delete
32
+ claim.ts pm claim / release
33
+ release.ts (re-exports from claim.ts)
34
+ list.ts pm list (active-only: excludes closed/canceled) / list-all / list-* commands
35
+ comments.ts pm comments
36
+ files.ts pm files
37
+ docs.ts pm docs
38
+ test.ts pm test (add/remove/run linked tests)
39
+ test-all.ts pm test-all (orchestration)
40
+ search.ts pm search (keyword / semantic / hybrid)
41
+ reindex.ts pm reindex
42
+ history.ts pm history
43
+ activity.ts pm activity
44
+ restore.ts pm restore
45
+ stats.ts pm stats
46
+ health.ts pm health
47
+ gc.ts pm gc
48
+ config.ts pm config
49
+ install.ts pm install pi
50
+ completion.ts pm completion
51
+ beads.ts pm beads (subcommand router to built-in extension)
52
+ index.ts barrel re-export
53
+ extension-command-options.ts Loose option parser for dynamic extension commands
54
+ core/
55
+ extensions/
56
+ loader.ts Extension manifest discovery, load, activate
57
+ builtins.ts Built-in extension registrations
58
+ index.ts barrel
59
+ fs/
60
+ fs-utils.ts Atomic write, path existence, mkdirp
61
+ index.ts barrel
62
+ history/
63
+ history.ts RFC6902 patch generation, history append, replay
64
+ index.ts barrel
65
+ item/
66
+ id.ts ID generation (cryptographic random base36) and normalization
67
+ item-format.ts Item front-matter serializer (canonical key order, determinism)
68
+ parse.ts Markdown item file parser (JSON front-matter + body)
69
+ index.ts barrel
70
+ lock/
71
+ lock.ts Exclusive lock acquire/release with TTL and stale detection
72
+ index.ts barrel
73
+ output/
74
+ output.ts TOON / JSON output rendering
75
+ search/
76
+ cache.ts Keyword index artifact read/write (manifest.json + embeddings.jsonl)
77
+ embedding-batches.ts Deterministic batch embedding generation with retry
78
+ providers.ts OpenAI / Ollama embedding provider abstraction
79
+ vector-stores.ts Qdrant / LanceDB vector store abstraction
80
+ shared/
81
+ command-types.ts GlobalOptions, shared command type definitions
82
+ constants.ts Exit codes, required directory names
83
+ errors.ts PmCliError with exit code
84
+ serialization.ts Deterministic JSON serialization (stable key order)
85
+ time.ts ISO timestamp helpers, relative deadline parsing
86
+ index.ts barrel
87
+ store/
88
+ item-store.ts File-backed item CRUD with lock/atomic write contract
89
+ paths.ts PM root resolution (PM_PATH, --path, cwd)
90
+ settings.ts settings.json read/write
91
+ index.ts barrel
92
+ types/
93
+ index.ts ItemFrontMatter, ItemType, ItemStatus, Dependency, etc.
94
+ extensions/
95
+ builtins/
96
+ beads/
97
+ index.ts Beads JSONL import extension
98
+ todos/
99
+ index.ts todos extension activate()
100
+ import-export.ts todos import/export logic
101
+ command-types.ts (re-export shim)
102
+ constants.ts (re-export shim)
103
+ errors.ts (re-export shim)
104
+ ... (other re-export shims for backward compat)
105
+ ```
106
+
107
+ ## Item Storage
108
+
109
+ Each item is stored as a Markdown file:
110
+
111
+ ```
112
+ .agents/pm/
113
+ <type-plural>/<id>.md e.g. tasks/pm-a1b2.md
114
+ history/<id>.jsonl append-only RFC6902 patch log
115
+ locks/<id>.lock exclusive lock metadata (JSON)
116
+ settings.json project configuration
117
+ index/manifest.json keyword index cache (optional, rebuildable)
118
+ search/embeddings.jsonl keyword corpus records (optional, rebuildable)
119
+ extensions/ project-local extensions
120
+ ```
121
+
122
+ ### Item File Format
123
+
124
+ ```
125
+ {
126
+ "id": "pm-a1b2",
127
+ "title": "...",
128
+ ...
129
+ }
130
+
131
+ Optional markdown body here.
132
+ ```
133
+
134
+ Fields are serialized in canonical key order (defined in `item-format.ts`).
135
+
136
+ ## Mutation Contract
137
+
138
+ Every item mutation follows this sequence:
139
+
140
+ 1. **Acquire lock** — exclusive open on `locks/<id>.lock`; reject if stale and no `--force`
141
+ 2. **Read current item** — parse front-matter + body
142
+ 3. **Compute `before_hash`** — SHA-256 of canonical `{ front_matter, body }` JSON
143
+ 4. **Apply mutation** — in-memory model update
144
+ 5. **Update `updated_at`** — every mutation must change this timestamp
145
+ 6. **Compute patch + `after_hash`** — RFC6902 diff; SHA-256 of new canonical state
146
+ 7. **Atomic write** — write to temp file; `rename` to target (single syscall, OS-atomic)
147
+ 8. **Append history line** — JSONL append to `history/<id>.jsonl`
148
+ 9. **Release lock** — unlink lock file
149
+
150
+ If step 7 or 8 fails, the item file is rolled back (if write succeeded) before returning failure.
151
+
152
+ ## History and Restore
153
+
154
+ Each history entry is a JSONL line:
155
+
156
+ ```json
157
+ {
158
+ "ts": "ISO timestamp",
159
+ "author": "string",
160
+ "op": "create|update|append|...|restore",
161
+ "patch": [ /* RFC6902 ops */ ],
162
+ "before_hash": "sha256-hex",
163
+ "after_hash": "sha256-hex",
164
+ "message": "optional"
165
+ }
166
+ ```
167
+
168
+ `pm restore <ID> <TIMESTAMP|VERSION>` replays patches from `op=create` through the target entry, rebuilding exact canonical state.
169
+
170
+ ## Extension System
171
+
172
+ Extensions are Node.js modules with an `activate(api)` export:
173
+
174
+ ```ts
175
+ export function activate(api: ExtensionApi): void {
176
+ api.registerCommand({ name: "my command", run: async (args, opts, global) => { ... } });
177
+ api.hooks.beforeCommand((ctx) => { ... });
178
+ }
179
+ ```
180
+
181
+ Load order: **core built-ins → global (`~/.pm-cli/extensions/`) → project (`.agents/pm/extensions/`)**.
182
+
183
+ Project-local extensions override global by default. See [EXTENSIONS.md](./EXTENSIONS.md) for the full API reference.
184
+
185
+ ## Search Architecture
186
+
187
+ - **Keyword mode** (always available): multi-factor lexical scoring with configurable field weights
188
+ - **Semantic mode** (requires provider + vector store config): embedding-based vector similarity
189
+ - **Hybrid mode** (default when semantic available): blended lexical + semantic ranking
190
+
191
+ Providers: OpenAI-compatible, Ollama
192
+ Vector stores: Qdrant, LanceDB
193
+
194
+ ### Keyword Scoring
195
+
196
+ Each item is scored across: `title` (8×), `description` (5×), `tags` (6×), `status` (2×), `body` (1×), `comments`/`notes`/`learnings` (1× each), `dependencies` (3×). Exact title token matches add a bonus (10×).
197
+
198
+ Weights are configurable via `settings.json` under `search.tuning`.
199
+
200
+ ## Configuration
201
+
202
+ `settings.json` is read from the PM root at startup. Key sections:
203
+
204
+ | Key | Description |
205
+ |-----|-------------|
206
+ | `id_prefix` | Prefix for generated IDs (default `pm-`) |
207
+ | `author_default` | Default author for mutations |
208
+ | `locks.ttl_seconds` | Lock TTL (default 1800) |
209
+ | `output.default_format` | `toon` or `json` |
210
+ | `search.*` | Search provider and tuning settings |
211
+ | `providers.openai` / `providers.ollama` | Embedding provider config |
212
+ | `vector_store.qdrant` / `vector_store.lancedb` | Vector store config |
213
+
214
+ Precedence: CLI flags > env vars (`PM_PATH`, `PM_AUTHOR`, etc.) > `settings.json` > hard defaults.
215
+
216
+ ## Exit Codes
217
+
218
+ | Code | Meaning |
219
+ |------|---------|
220
+ | 0 | Success |
221
+ | 1 | Generic failure |
222
+ | 2 | Usage / invalid args |
223
+ | 3 | Not found |
224
+ | 4 | Conflict (lock / ownership) |
225
+ | 5 | Dependency failed (test-all) |
226
+
227
+ ## Testing
228
+
229
+ Tests live in `tests/`:
230
+
231
+ ```
232
+ tests/
233
+ unit/ Unit tests (item format, lock, search, commands, extensions, etc.)
234
+ integration/ Integration tests (CLI subprocess spawn, CI contract, README contract)
235
+ ```
236
+
237
+ All tests run in sandboxed temp directories (`PM_PATH` + `PM_GLOBAL_PATH` isolated per suite). Coverage is enforced at 100% for lines, branches, functions, and statements.
238
+
239
+ Run all tests:
240
+
241
+ ```bash
242
+ node scripts/run-tests.mjs test # sandbox-safe, tests only
243
+ node scripts/run-tests.mjs coverage # sandbox-safe, with coverage gate
244
+ ```
245
+
246
+ The `scripts/run-tests.mjs` wrapper creates a temp directory, sets `PM_PATH` and `PM_GLOBAL_PATH`, runs Vitest, then cleans up.