@tekmidian/pai 1.0.0 → 1.0.3

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 (219) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +67 -5
  3. package/dist/aibroker-client-BxzeEHPF.mjs +3 -0
  4. package/dist/{aibroker-client-CXEYBzbf.mjs → aibroker-client-CQPGqLxL.mjs} +1 -1
  5. package/dist/atomic-file-BorMa4T3.mjs +21 -0
  6. package/dist/{auto-route-D5SXrMpB.mjs → auto-route-B7Yu6Uam.mjs} +3 -3
  7. package/dist/auto-route-CjjQqU1o.mjs +11 -0
  8. package/dist/budget-Dod6rnA9.mjs +15 -0
  9. package/dist/{caller-identity-CVTuiLSs.mjs → caller-identity-yLFb7CKq.mjs} +6 -5
  10. package/dist/{capacity-DaXrVj3J.mjs → capacity-DEveQdFV.mjs} +3 -3
  11. package/dist/{chain-BcQlIlEd.mjs → chain-7n9Gx56r.mjs} +5 -5
  12. package/dist/cli/index.mjs +1628 -370
  13. package/dist/{cockpit-actions-ODmt8yF9.mjs → cockpit-actions-BBHeyEZI.mjs} +84 -42
  14. package/dist/cockpit-actions-DR9X514g.mjs +20 -0
  15. package/dist/cockpit-memory--dnShXBA.mjs +20 -0
  16. package/dist/{config-BSXKyeJ1.mjs → config-Bu1_vbY8.mjs} +42 -3
  17. package/dist/{config-B955yYmo.mjs → config-Cxi-aBf4.mjs} +2 -2
  18. package/dist/{config-TaWmdTLx.mjs → config-DtENJ6cL.mjs} +1 -1
  19. package/dist/{config-D5chi2LO.mjs → config-XpZWOYOG.mjs} +2 -2
  20. package/dist/{controls-BGkK_Bdi.mjs → controls-CPoeudou.mjs} +37 -22
  21. package/dist/daemon/index.mjs +43 -42
  22. package/dist/daemon-DKdBNKfa.mjs +45 -0
  23. package/dist/{daemon-CorGh6Ub.mjs → daemon-DPAo6WTa.mjs} +103 -55
  24. package/dist/daemon-mcp/index.mjs +40 -39
  25. package/dist/{define-DGFu-sCf.mjs → define-CjJsmq-6.mjs} +1 -1
  26. package/dist/{detect-C1d5cUkT.mjs → detect-9CZNO0yf.mjs} +2 -2
  27. package/dist/detect-D1ziFFfA.mjs +10 -0
  28. package/dist/{embed-pass-CeQD8kRE.mjs → embed-pass-DIWjA68P.mjs} +5 -5
  29. package/dist/{embedding-gate-BHuBsgHD.mjs → embedding-gate-6rZrWRXa.mjs} +5 -5
  30. package/dist/{embedding-gate-Z7CJSOJk.mjs → embedding-gate-Cnk4YCyX.mjs} +3 -3
  31. package/dist/{embeddings-D4t6L-EH.mjs → embeddings-BVq3esBF.mjs} +1 -1
  32. package/dist/{embeddings-OF9Pt4by.mjs → embeddings-CIkJBKd-.mjs} +1 -1
  33. package/dist/{endreason-x1KOSrcO.mjs → endreason-C577xIQz.mjs} +7 -6
  34. package/dist/{env-DArqGq-Z.mjs → env-BE8mrsxr.mjs} +1 -1
  35. package/dist/factory-Bsib-qDG.mjs +9 -0
  36. package/dist/{factory-BtjbQ0np.mjs → factory-DjAAsqr_.mjs} +15 -13
  37. package/dist/{fallback-BIyEpPsQ.mjs → fallback-DFlItw1Z.mjs} +5 -5
  38. package/dist/{fmt-age-BiSHrTKN.mjs → fmt-age-ByDkvkoU.mjs} +1 -1
  39. package/dist/{health-C6jZWvRG.mjs → health-Dnym-qcT.mjs} +4 -4
  40. package/dist/{helpers-DFmYRCOa.mjs → helpers-BD6V-p9w.mjs} +2 -2
  41. package/dist/helpers-CMGjy_0N.mjs +10 -0
  42. package/dist/{helpers-CJpb_MNB.mjs → helpers-CRuBUas3.mjs} +87 -38
  43. package/dist/hooks/capture-all-events.mjs +52 -11
  44. package/dist/hooks/capture-session-summary.mjs +64 -47
  45. package/dist/hooks/capture-tool-output.mjs +49 -8
  46. package/dist/hooks/context-compression-hook.mjs +30 -10
  47. package/dist/hooks/initialize-session.mjs +1 -0
  48. package/dist/hooks/load-core-context.mjs +1 -1
  49. package/dist/hooks/load-project-context.mjs +32 -29
  50. package/dist/hooks/security-validator.mjs +45 -13
  51. package/dist/hooks/stop-hook.mjs +54 -16
  52. package/dist/hooks/supervision-banner.mjs +9 -0
  53. package/dist/hooks/sync-todo-to-md.mjs +147 -113
  54. package/dist/hooks/worker-edit-repair.mjs +2 -1
  55. package/dist/hooks/worker-guard.mjs +40 -16
  56. package/dist/hooks/worker-note.mjs +12 -5
  57. package/dist/hooks/worker-path-repair.mjs +1 -1
  58. package/dist/hooks/worker-pool-host.mjs +329 -231
  59. package/dist/hooks/worker-status-line.mjs +195 -114
  60. package/dist/index.d.mts +18 -0
  61. package/dist/index.mjs +12 -12
  62. package/dist/{indexer-backend-BM2CUSu8.mjs → indexer-backend-Cll7le4P.mjs} +149 -96
  63. package/dist/{ipc-client-BMqWw_gv.mjs → ipc-client-CaiGJnSM.mjs} +1 -1
  64. package/dist/{ipc-client-YYDD6zzU.mjs → ipc-client-ZRmDKd5Z.mjs} +1 -1
  65. package/dist/kill-tree-BG7dRVtp.mjs +10 -0
  66. package/dist/{kill-tree-BjYz5BxK.mjs → kill-tree-EWYaEk5v.mjs} +8 -8
  67. package/dist/{launch-CLp0OJxV.mjs → launch-CXVlZjHt.mjs} +8 -8
  68. package/dist/{launch-DgqQdAjI.mjs → launch-Jh5NVeNe.mjs} +3 -3
  69. package/dist/local-candidate-DLdwQt0s.mjs +112 -0
  70. package/dist/local-instances-DOxSgT_L.mjs +210 -0
  71. package/dist/local-instances-ZeRkkuS5.mjs +6 -0
  72. package/dist/{local-tiers-DPZYqv9m.mjs → local-tiers-BE4jGaMa.mjs} +2 -2
  73. package/dist/{local-tiers-DnBIAkbK.mjs → local-tiers-DNMI5W86.mjs} +3 -3
  74. package/dist/{main-config-ops-C0SflOWk.mjs → main-config-ops-BEMpuhDz.mjs} +3 -3
  75. package/dist/{main-resolver-DVPpSWVy.mjs → main-resolver-3Ns1HPmS.mjs} +18 -17
  76. package/dist/{migrate-BUJHadA8.mjs → migrate-DrA_OwlZ.mjs} +45 -14
  77. package/dist/min-max-DrSRUaWQ.mjs +16 -0
  78. package/dist/{model-inventory-Dasber3S.mjs → model-inventory-BFVSNFT3.mjs} +13 -12
  79. package/dist/{models-add-Bt7aUHDs.mjs → models-add-C1QIc1DA.mjs} +39 -38
  80. package/dist/operator-BTqvTIc8.mjs +7 -0
  81. package/dist/{operator-DZxcP-g8.mjs → operator-CyuB3aVw.mjs} +3 -3
  82. package/dist/{pai-marker-kIYuNt3c.mjs → pai-marker-BcZyJguM.mjs} +7 -6
  83. package/dist/{pane-audit-OGYrOAik.mjs → pane-audit-DKQt71s4.mjs} +7 -7
  84. package/dist/{paths-DoRuFc60.mjs → paths-CFHTloSe.mjs} +3 -3
  85. package/dist/{paths-DoIyRnhx.mjs → paths-CHifubDh.mjs} +3 -3
  86. package/dist/{planner-DLGOYlVb.mjs → planner-BmFACdLa.mjs} +31 -30
  87. package/dist/{pool-CZ5MZaXg.mjs → pool-Dh-q3iJi.mjs} +45 -6
  88. package/dist/{pool-cli-BxNSPzzY.mjs → pool-cli-BggU8GRp.mjs} +5 -5
  89. package/dist/{pool-cli-CbJfl37y.mjs → pool-cli-DQ6OzRy2.mjs} +6 -6
  90. package/dist/postgres-BdBNkL_l.mjs +7 -0
  91. package/dist/{postgres-CDnd_k5f.mjs → postgres-C6ti4haA.mjs} +55 -34
  92. package/dist/{project-setup-DM4npnL3.mjs → project-setup-jvfONJTQ.mjs} +131 -74
  93. package/dist/providers-BeDiVEb-.mjs +16 -0
  94. package/dist/{providers-UsKtLcUR.mjs → providers-CblTFrhz.mjs} +6 -6
  95. package/dist/{query-feedback-I-txSnld.mjs → query-feedback-BRfPtqki.mjs} +2 -2
  96. package/dist/registrable-BzH4TObg.mjs +9 -0
  97. package/dist/{registrable-LrRIVYQc.mjs → registrable-DpyTtajg.mjs} +4 -4
  98. package/dist/{render-BDbb4CF-.mjs → render-BYmQkuLd.mjs} +8 -8
  99. package/dist/render-CoMvwMPs.mjs +13 -0
  100. package/dist/{reranker-B4r4vykM.mjs → reranker-8g6xMwP7.mjs} +1 -1
  101. package/dist/{reranker-DxxMCtA0.mjs → reranker-CqCbpGnX.mjs} +1 -1
  102. package/dist/root-FtJsxYnm.mjs +36 -0
  103. package/dist/{root-BMeJuHOb.mjs → root-Xglu0OPD.mjs} +11 -11
  104. package/dist/route-table-B7zpoypi.mjs +15 -0
  105. package/dist/{router-L8Nu-OHF.mjs → router-CQSc3lk3.mjs} +17 -7
  106. package/dist/{router-D6Ec6Fid.mjs → router-DwHJRgG9.mjs} +1 -1
  107. package/dist/{routing-CUyiglfu.mjs → routing-BAAST9vT.mjs} +27 -308
  108. package/dist/{routing-ZuGlc0ge.mjs → routing-CENt4HH1.mjs} +13 -12
  109. package/dist/{run-ulAi5dFD.mjs → run-CSC7mgPf.mjs} +35 -33
  110. package/dist/{scan-B7I0gPe-.mjs → scan-C_Y5W9py.mjs} +6 -6
  111. package/dist/{local-candidate-jOjTNlOL.mjs → scheduler-CtUyWJ3O.mjs} +7 -109
  112. package/dist/scheduler-dmHXoRvm.mjs +3 -0
  113. package/dist/{scope-D5VSQxe4.mjs → scope-D-h6F6DN.mjs} +4 -4
  114. package/dist/{search-CPoE0830.mjs → search-RSyeQqj1.mjs} +18 -18
  115. package/dist/{session-CNXF6DLP.mjs → session-8iqQDkqb.mjs} +55 -31
  116. package/dist/session-BeqAbNPd.mjs +35 -0
  117. package/dist/session-scan-BJI_ZO8M.mjs +9 -0
  118. package/dist/{session-scan-BDLEc4w1.mjs → session-scan-W-gbwJHM.mjs} +6 -6
  119. package/dist/{sources-CjhUKKtO.mjs → sources-ESUkZaWv.mjs} +1 -1
  120. package/dist/{status-DYydKQUI.mjs → status-Dm4dYciN.mjs} +4 -4
  121. package/dist/{status-CvVi9cDf.mjs → status-ggJ7lgVg.mjs} +17 -9
  122. package/dist/{stop-words-SdSL1WKH.mjs → stop-words-DSEYQdNe.mjs} +1 -1
  123. package/dist/{test-isolation-CoDeOVXb.mjs → test-isolation-lqSmYxr0.mjs} +1 -1
  124. package/dist/{timeouts-OwEONmc8.mjs → timeouts-1MLooEBB.mjs} +1 -1
  125. package/dist/{tool-errors-AeRQuG3Y.mjs → tool-errors-7E13StWd.mjs} +4 -3
  126. package/dist/{tool-errors-R5E0fCgf.mjs → tool-errors-CJWODvlo.mjs} +6 -6
  127. package/dist/viewer-CqozWW39.mjs +22 -0
  128. package/dist/{viewer-DtWj5Vti.mjs → viewer-mDXUNHNy.mjs} +15 -15
  129. package/dist/{wait-BMUR-U-U.mjs → wait-ByV0OyMZ.mjs} +3 -3
  130. package/dist/{worker-config-BLqa1yiD.mjs → worker-config-CJhEMk19.mjs} +294 -92
  131. package/dist/worker-config-DESkIjMF.mjs +41 -0
  132. package/dist/{workers-config-DEI9lrV4.mjs → workers-config-f8KrkY4L.mjs} +2 -2
  133. package/dist/{worktree-zmRf556h.mjs → worktree-CRs2gyg0.mjs} +37 -7
  134. package/dist/{zettelkasten-nigq7fqs.mjs → zettelkasten-B_rRRRvD.mjs} +5 -5
  135. package/dist/{zettelkasten-Cr_Xj0mG.mjs → zettelkasten-BzMm8REH.mjs} +29 -19
  136. package/docs/README.md +2 -0
  137. package/docs/cockpit.md +10 -4
  138. package/docs/commands/README.md +4 -4
  139. package/docs/commands/backup.md +2 -0
  140. package/docs/commands/install.md +29 -4
  141. package/docs/commands/providers.md +1 -1
  142. package/docs/commands/restore.md +4 -0
  143. package/docs/commands/setup.md +29 -4
  144. package/docs/commands/worker.md +1 -1
  145. package/docs/config.md +2 -0
  146. package/docs/features.md +299 -0
  147. package/docs/images/architecture.drawio +51 -0
  148. package/docs/images/architecture.png +0 -0
  149. package/docs/images/architecture.svg +3 -0
  150. package/docs/images/cockpit-01-system-tokens.jpg +0 -0
  151. package/docs/images/cockpit-02-totals-cache.jpg +0 -0
  152. package/docs/images/cockpit-03-local-servers-models-pool.jpg +0 -0
  153. package/docs/images/cockpit-04-workers-memory.jpg +0 -0
  154. package/docs/images/cockpit-05-performance.jpg +0 -0
  155. package/docs/images/cockpit-06-runs-speed-routing.jpg +0 -0
  156. package/docs/images/cockpit-07-settings-registry.jpg +0 -0
  157. package/docs/install/index.md +29 -0
  158. package/docs/three-tier-coding.md +1 -1
  159. package/gemini-extension.json +1 -1
  160. package/package.json +1 -5
  161. package/pai-plugin.json +1 -1
  162. package/plugins/context-preservation/plugin.json +1 -1
  163. package/plugins/core/plugin.json +1 -1
  164. package/plugins/core/skills/setup/SKILL.md +41 -9
  165. package/plugins/creative/plugin.json +1 -1
  166. package/plugins/observability/plugin.json +1 -1
  167. package/plugins/productivity/plugin.json +1 -1
  168. package/plugins/semantic-search/plugin.json +1 -1
  169. package/plugins/ui/plugin.json +1 -1
  170. package/plugins/zettelkasten/plugin.json +1 -1
  171. package/src/hooks/session-autosave.sh +8 -1
  172. package/src/hooks/session-stop.sh +8 -1
  173. package/src/hooks/ts/capture-all-events.ts +7 -12
  174. package/src/hooks/ts/lib/context-fill.ts +2 -1
  175. package/src/hooks/ts/lib/path-repair.ts +1 -1
  176. package/src/hooks/ts/lib/project-utils/notify.ts +1 -0
  177. package/src/hooks/ts/lib/project-utils/session-notes.ts +23 -6
  178. package/src/hooks/ts/lib/raw-capture.ts +36 -0
  179. package/src/hooks/ts/lib/session-summary.ts +129 -0
  180. package/src/hooks/ts/lib/todo-sync.ts +120 -0
  181. package/src/hooks/ts/lib/worker-git-guard.ts +1 -1
  182. package/src/hooks/ts/post-tool-use/capture-tool-output.ts +6 -10
  183. package/src/hooks/ts/post-tool-use/sync-todo-to-md.ts +5 -105
  184. package/src/hooks/ts/pre-compact/context-compression-hook.ts +1 -1
  185. package/src/hooks/ts/pre-tool-use/security-validator.ts +35 -14
  186. package/src/hooks/ts/session-end/capture-session-summary.ts +20 -128
  187. package/src/hooks/ts/session-start/load-core-context.ts +3 -3
  188. package/src/hooks/ts/session-start/load-project-context.ts +18 -22
  189. package/src/hooks/ts/stop/stop-hook.ts +13 -5
  190. package/src/hooks/ztk-auto.sh +7 -2
  191. package/dist/aibroker-client-JjE74jo0.mjs +0 -3
  192. package/dist/auto-route-BRk8NEFv.mjs +0 -11
  193. package/dist/budget-DuhQ2zzG.mjs +0 -14
  194. package/dist/cockpit-actions-DcQ-ucU8.mjs +0 -19
  195. package/dist/cockpit-memory-KV45PPO2.mjs +0 -19
  196. package/dist/daemon-C7yt_ptC.mjs +0 -44
  197. package/dist/detect-DRUkmHnb.mjs +0 -10
  198. package/dist/factory-DAGG9_n8.mjs +0 -9
  199. package/dist/helpers-DPJEHPq6.mjs +0 -10
  200. package/dist/kill-tree-LV0Q7Mte.mjs +0 -10
  201. package/dist/operator-CfL0HiBK.mjs +0 -7
  202. package/dist/postgres-DgqWyqhN.mjs +0 -7
  203. package/dist/providers-CTu2s1z2.mjs +0 -15
  204. package/dist/registrable-D9aNZOTh.mjs +0 -9
  205. package/dist/render-BSfVlYHj.mjs +0 -13
  206. package/dist/root-xI9DqVIe.mjs +0 -35
  207. package/dist/route-table-HjvnLVEU.mjs +0 -14
  208. package/dist/session-BJHzmUg2.mjs +0 -34
  209. package/dist/session-scan-YORKE1NO.mjs +0 -9
  210. package/dist/viewer-B8709jDN.mjs +0 -22
  211. package/dist/worker-config-D8tRuvo7.mjs +0 -40
  212. package/docs/images/cockpit-limits-routing.jpg +0 -0
  213. package/docs/images/cockpit-models.jpg +0 -0
  214. package/docs/images/cockpit-usage.jpg +0 -0
  215. package/docs/images/cockpit-workers-system.jpg +0 -0
  216. package/scripts/build-docs.mjs +0 -41
  217. package/scripts/build-hooks.mjs +0 -311
  218. package/scripts/build-skill-stubs.mjs +0 -216
  219. package/scripts/copy-defaults.mjs +0 -46
@@ -0,0 +1,41 @@
1
+ import "./utils-J2b9y8PC.mjs";
2
+ import "./config-XpZWOYOG.mjs";
3
+ import "./config-Bu1_vbY8.mjs";
4
+ import "./paths-CHifubDh.mjs";
5
+ import "./worktree-CRs2gyg0.mjs";
6
+ import "./status-ggJ7lgVg.mjs";
7
+ import "./pool-Dh-q3iJi.mjs";
8
+ import "./helpers-CRuBUas3.mjs";
9
+ import "./scope-D-h6F6DN.mjs";
10
+ import "./routing-BAAST9vT.mjs";
11
+ import "./tool-errors-7E13StWd.mjs";
12
+ import "./wait-ByV0OyMZ.mjs";
13
+ import "./local-tiers-BE4jGaMa.mjs";
14
+ import "./caller-identity-yLFb7CKq.mjs";
15
+ import "./capacity-DEveQdFV.mjs";
16
+ import "./local-instances-DOxSgT_L.mjs";
17
+ import "./local-candidate-DLdwQt0s.mjs";
18
+ import "./factory-DjAAsqr_.mjs";
19
+ import "./postgres-C6ti4haA.mjs";
20
+ import "./embedding-gate-6rZrWRXa.mjs";
21
+ import "./embeddings-BVq3esBF.mjs";
22
+ import "./router-CQSc3lk3.mjs";
23
+ import "./launch-Jh5NVeNe.mjs";
24
+ import "./health-Dnym-qcT.mjs";
25
+ import "./run-CSC7mgPf.mjs";
26
+ import "./controls-CPoeudou.mjs";
27
+ import "./endreason-C577xIQz.mjs";
28
+ import "./render-BYmQkuLd.mjs";
29
+ import "./operator-CyuB3aVw.mjs";
30
+ import "./kill-tree-EWYaEk5v.mjs";
31
+ import "./pool-cli-BggU8GRp.mjs";
32
+ import "./pane-audit-DKQt71s4.mjs";
33
+ import "./providers-CblTFrhz.mjs";
34
+ import { A as workerMcpCommand, C as workerBenchCommand, D as workerFallbackCommand, E as workerControlsCommand, F as workerProvidersCommand, I as workerProxyCommand, L as workerRolesCommand, M as workerOnCommand, N as workerPolicyCommand, O as workerInstallCommand, P as workerPoolCommand, R as workerRouteCommand, S as stopInstance, T as workerConfigCommand, _ as portOpen, a as collectEnv, b as startTier, c as currentInstances, d as isUp, f as killInstance, g as portListeners, h as parseCostTier, i as cliInflight, j as workerOffCommand, k as workerLocalCommand, l as fail, m as listServers, n as WORKER_CONFIG_COMMANDS, o as collectTags, p as launchDetached, r as buildClassTarget, s as controlsArgv, t as PROVIDER_EDIT_COMMANDS, u as healthOk, v as serverLine, w as workerClassesCommand, x as stopAll, y as startInstance } from "./worker-config-CJhEMk19.mjs";
35
+ import "./main-config-ops-BEMpuhDz.mjs";
36
+ import "./cockpit-actions-BBHeyEZI.mjs";
37
+ import "./ipc-client-CaiGJnSM.mjs";
38
+ import "./embed-pass-DIWjA68P.mjs";
39
+ import "./fallback-DFlItw1Z.mjs";
40
+
41
+ export { currentInstances, startInstance, startTier, stopAll, stopInstance };
@@ -1,4 +1,4 @@
1
- import { $ as starterWorkersYamlText, B as WORKERS_YAML_FILENAME, G as inlineWorkersYamlKeys, H as defaultWorkersYamlPath, J as parseBuiltinAnthropic, K as migrateWorkersToYaml, Q as relocateWorkersYaml, U as effectiveWorkersYamlData, V as buildWorkersYamlText, W as initWorkersYaml, X as readMergeVerify, Y as parseWorkersYamlDocument, Z as readWorkersYaml, et as workersYamlLegacyNotice, it as yamlProviderToRaw, nt as writeWorkersYaml, q as needsWorkersYamlRelocation, rt as writeWorkersYamlText, tt as workersYamlPath } from "./config-D5chi2LO.mjs";
2
- import "./config-BSXKyeJ1.mjs";
1
+ import { $ as starterWorkersYamlText, B as WORKERS_YAML_FILENAME, G as inlineWorkersYamlKeys, H as defaultWorkersYamlPath, J as parseBuiltinAnthropic, K as migrateWorkersToYaml, Q as relocateWorkersYaml, U as effectiveWorkersYamlData, V as buildWorkersYamlText, W as initWorkersYaml, X as readMergeVerify, Y as parseWorkersYamlDocument, Z as readWorkersYaml, et as workersYamlLegacyNotice, it as yamlProviderToRaw, nt as writeWorkersYaml, q as needsWorkersYamlRelocation, rt as writeWorkersYamlText, tt as workersYamlPath } from "./config-XpZWOYOG.mjs";
2
+ import "./config-Bu1_vbY8.mjs";
3
3
 
4
4
  export { workersYamlPath };
@@ -1,8 +1,9 @@
1
- import { wt as appendLedger } from "./config-D5chi2LO.mjs";
2
- import { i as ledgerPath, l as statusPath } from "./paths-DoIyRnhx.mjs";
3
- import { a as UNLABELED, g as isLive, k as saveStatus, v as loadStatus, y as loadStatuses } from "./status-CvVi9cDf.mjs";
4
- import { t as fmtAge } from "./fmt-age-BiSHrTKN.mjs";
5
- import { v as readPoolState } from "./pool-CZ5MZaXg.mjs";
1
+ import { t as writeFileAtomic } from "./atomic-file-BorMa4T3.mjs";
2
+ import { wt as appendLedger } from "./config-XpZWOYOG.mjs";
3
+ import { i as ledgerPath, l as statusPath } from "./paths-CHifubDh.mjs";
4
+ import { a as UNLABELED, g as isLive, k as saveStatus, v as loadStatus, y as loadStatuses } from "./status-ggJ7lgVg.mjs";
5
+ import { t as fmtAge } from "./fmt-age-ByDkvkoU.mjs";
6
+ import { v as readPoolState } from "./pool-Dh-q3iJi.mjs";
6
7
  import { existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, readlinkSync, realpathSync, rmSync, statSync, writeFileSync } from "node:fs";
7
8
  import { basename, dirname, isAbsolute, join, resolve, sep } from "node:path";
8
9
  import { platform, tmpdir } from "node:os";
@@ -138,7 +139,7 @@ function invalidatePendingCache(logDir, repoRoot) {
138
139
  }
139
140
  if (!changed) return;
140
141
  try {
141
- writeFileSync(file, JSON.stringify(cache));
142
+ writeFileAtomic(file, JSON.stringify(cache));
142
143
  } catch {}
143
144
  }
144
145
 
@@ -2148,6 +2149,24 @@ function leftoverWorktrees(logDir) {
2148
2149
  }
2149
2150
  return n;
2150
2151
  }
2152
+ /**
2153
+ * True only for a directory that is itself a git worktree: its toplevel is the directory
2154
+ * and its repository lists it. A leftover without .git (say, only node_modules) resolves
2155
+ * git to an enclosing repository, which must never be status'ed, stashed or archived.
2156
+ */
2157
+ function isRealWorktree(dir) {
2158
+ try {
2159
+ const real = realpathSync(dir);
2160
+ if (realpathSync(git(dir, ["rev-parse", "--show-toplevel"])) !== real) return false;
2161
+ return git(dir, [
2162
+ "worktree",
2163
+ "list",
2164
+ "--porcelain"
2165
+ ]).split("\n").some((l) => l.startsWith("worktree ") && realpathOr(l.slice(9)) === real);
2166
+ } catch {
2167
+ return false;
2168
+ }
2169
+ }
2151
2170
  const GC_STAMP = "gc-last";
2152
2171
  /**
2153
2172
  * Pid of a live process whose cwd is `dir` or below (shell drivers parked in a
@@ -2470,6 +2489,10 @@ function gcWorktrees(logDir, olderThanHours = 24, dryRun = false, now = Date.now
2470
2489
  const owned = new Set(statuses.map((s) => ownedTree(s)?.dir).filter((d) => !!d).map((d) => resolve(d)));
2471
2490
  const archive = (id, dir, branch, st) => {
2472
2491
  const target = `refs/pai-archive/${id}`;
2492
+ if (!isRealWorktree(dir)) return void out.push({
2493
+ id,
2494
+ skipped: "not a worktree"
2495
+ });
2473
2496
  const pid = busyPid(dir);
2474
2497
  if (pid) {
2475
2498
  if (!dryRun) appendLedger(ledgerPath(logDir), "WORKER-GC-SKIP", {
@@ -2621,6 +2644,13 @@ function gcPoolWorktrees(logDir, dryRun = false) {
2621
2644
  list(join(logDir, "slots"), () => true, (n) => `slot-${n}`);
2622
2645
  for (const { id, dir } of cands) {
2623
2646
  if (owned.has(resolve(dir))) continue;
2647
+ if (!isRealWorktree(dir)) {
2648
+ out.push({
2649
+ id,
2650
+ skipped: "not a worktree"
2651
+ });
2652
+ continue;
2653
+ }
2624
2654
  const pid = busyPid(dir);
2625
2655
  if (pid) {
2626
2656
  out.push({
@@ -2680,4 +2710,4 @@ function gcWorktreesThrottled(logDir, everyMin = 60, now = Date.now(), opts = {}
2680
2710
 
2681
2711
  //#endregion
2682
2712
  export { applyScratchEnv as A, worktreeWanted as C, formatPending as D, worktreesStatsCached as E, pendingGate as O, worktreeSystemPrompt as S, worktreesStats as T, ownedTree as _, archiveEmptyResult as a, verifyWorker as b, formatKnowledge as c, gcWorktrees as d, gcWorktreesThrottled as f, mergeWorker as g, markResumed as h, adoptTree as i, scratchPromptLine as j, pendingResults as k, formatWorktreesStats as l, leftoverWorktrees as m, MergeConflictError as n, commitLines as o, inPlaceSystemPrompt as p, addWorktree as r, discardWorker as s, GATE_MARK as t, gcPoolWorktrees as u, recordWorktree as v, worktreesDir as w, worktreeRefusesStart as x, salvageOnExit as y };
2683
- //# sourceMappingURL=worktree-zmRf556h.mjs.map
2713
+ //# sourceMappingURL=worktree-CRs2gyg0.mjs.map
@@ -1,7 +1,7 @@
1
- import "./config-BSXKyeJ1.mjs";
2
- import "./embedding-gate-BHuBsgHD.mjs";
3
- import "./embeddings-D4t6L-EH.mjs";
4
- import { r as saveQueryResult } from "./query-feedback-I-txSnld.mjs";
5
- import { a as zettelThemes, c as zettelExplore, i as zettelHealth, n as zettelGodNotes, o as zettelConverse, r as zettelSuggest, s as zettelSurprise, t as zettelCommunities } from "./zettelkasten-Cr_Xj0mG.mjs";
1
+ import "./config-Bu1_vbY8.mjs";
2
+ import "./embedding-gate-6rZrWRXa.mjs";
3
+ import "./embeddings-BVq3esBF.mjs";
4
+ import { r as saveQueryResult } from "./query-feedback-BRfPtqki.mjs";
5
+ import { a as zettelThemes, c as zettelExplore, i as zettelHealth, n as zettelGodNotes, o as zettelConverse, r as zettelSuggest, s as zettelSurprise, t as zettelCommunities } from "./zettelkasten-BzMm8REH.mjs";
6
6
 
7
7
  export { zettelConverse, zettelExplore, zettelHealth, zettelSuggest, zettelSurprise, zettelThemes };
@@ -1,6 +1,6 @@
1
- import { t as STOP_WORDS$1 } from "./stop-words-SdSL1WKH.mjs";
2
- import { a as requireQueryEmbedding } from "./embedding-gate-BHuBsgHD.mjs";
3
- import { i as deserializeEmbedding, r as cosineSimilarity } from "./embeddings-D4t6L-EH.mjs";
1
+ import { t as STOP_WORDS$1 } from "./stop-words-DSEYQdNe.mjs";
2
+ import { a as requireQueryEmbedding } from "./embedding-gate-6rZrWRXa.mjs";
3
+ import { i as deserializeEmbedding, r as cosineSimilarity } from "./embeddings-BVq3esBF.mjs";
4
4
  import { basename, dirname } from "node:path";
5
5
 
6
6
  //#region src/zettelkasten/explore.ts
@@ -250,14 +250,24 @@ function extractDomain(vaultPath) {
250
250
  const slash = vaultPath.indexOf("/");
251
251
  return slash === -1 ? vaultPath : vaultPath.slice(0, slash);
252
252
  }
253
+ /** Hard caps so a hub-heavy vault cannot fan out into thousands of queries. */
254
+ const MAX_DEPTH = 3;
255
+ const MAX_FRONTIER = 200;
256
+ const LOOKUP_BATCH = 20;
257
+ /** Map `items` through `fn`, at most LOOKUP_BATCH calls in flight at once. */
258
+ async function mapInBatches(items, fn) {
259
+ const out = [];
260
+ for (let i = 0; i < items.length; i += LOOKUP_BATCH) out.push(...await Promise.all(items.slice(i, i + LOOKUP_BATCH).map(fn)));
261
+ return out;
262
+ }
253
263
  /**
254
264
  * Expand one level of graph neighbors for a set of paths.
255
265
  * Returns all outbound and inbound neighbor paths (excluding already-visited).
256
266
  */
257
267
  async function expandNeighbors(backend, paths) {
258
268
  if (paths.size === 0) return [];
259
- const pathList = Array.from(paths);
260
- const [forwardLinks, backwardLinks] = await Promise.all([backend.getVaultLinksFromPaths(pathList), Promise.all(pathList.map((p) => backend.getLinksToTarget(p)))]);
269
+ const pathList = Array.from(paths).slice(0, MAX_FRONTIER);
270
+ const [forwardLinks, backwardLinks] = await Promise.all([backend.getVaultLinksFromPaths(pathList), mapInBatches(pathList, (p) => backend.getLinksToTarget(p))]);
261
271
  const neighbors = [];
262
272
  for (const link of forwardLinks) if (link.targetPath) neighbors.push(link.targetPath);
263
273
  for (const linkList of backwardLinks) for (const link of linkList) neighbors.push(link.sourcePath);
@@ -335,7 +345,7 @@ async function zettelConverse(backend, opts) {
335
345
  }
336
346
  const allPaths = new Set(searchHits.keys());
337
347
  let frontier = new Set(searchHits.keys());
338
- for (let d = 0; d < depth; d++) {
348
+ for (let d = 0; d < Math.min(depth, MAX_DEPTH); d++) {
339
349
  const neighbors = await expandNeighbors(backend, frontier);
340
350
  const newFrontier = /* @__PURE__ */ new Set();
341
351
  for (const n of neighbors) if (!allPaths.has(n)) {
@@ -351,7 +361,7 @@ async function zettelConverse(backend, opts) {
351
361
  isSearchResult: true
352
362
  }));
353
363
  const neighborPaths = Array.from(allPaths).filter((p) => !searchHits.has(p));
354
- const neighborHealthRows = await Promise.all(neighborPaths.map((p) => backend.getVaultHealth(p)));
364
+ const neighborHealthRows = await mapInBatches(neighborPaths, (p) => backend.getVaultHealth(p));
355
365
  const neighborRanked = neighborPaths.map((path, idx) => ({
356
366
  path,
357
367
  score: 0,
@@ -491,8 +501,9 @@ function averageEmbeddings(embeddings) {
491
501
  return avg;
492
502
  }
493
503
  /**
494
- * Detect emerging themes in recently-modified notes using agglomerative single-linkage
495
- * clustering of note-level embeddings.
504
+ * Detect emerging themes in recently-modified notes using agglomerative average-linkage
505
+ * clustering of note-level embeddings: the closest pair of clusters (cosine similarity
506
+ * of their centroids) is merged repeatedly while it stays above the threshold.
496
507
  */
497
508
  async function zettelThemes(backend, opts) {
498
509
  const lookbackDays = opts.lookbackDays ?? 30;
@@ -989,12 +1000,8 @@ function louvainPhase1(graph, community, resolution) {
989
1000
  }
990
1001
  for (const [c, w] of communityInternalWeight) communityInternalWeight.set(c, w / 2);
991
1002
  let improved = false;
992
- const shuffled = [...graph.nodes];
993
- for (let i = shuffled.length - 1; i > 0; i--) {
994
- const j = Math.floor(Math.random() * (i + 1));
995
- [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
996
- }
997
- for (const node of shuffled) {
1003
+ const ordered = [...graph.nodes].sort();
1004
+ for (const node of ordered) {
998
1005
  const currentComm = community.get(node);
999
1006
  const ki = graph.degree.get(node) ?? 0;
1000
1007
  const neighbors = graph.adj.get(node) ?? /* @__PURE__ */ new Map();
@@ -1156,7 +1163,6 @@ async function zettelCommunities(backend, opts) {
1156
1163
  const titleMap = /* @__PURE__ */ new Map();
1157
1164
  for (const f of allFiles) titleMap.set(f.vaultPath, f.title);
1158
1165
  const communities = [];
1159
- let commId = 0;
1160
1166
  for (const [, members] of groups) {
1161
1167
  if (members.length < minSize) continue;
1162
1168
  const memberSet = new Set(members);
@@ -1184,7 +1190,7 @@ async function zettelCommunities(backend, opts) {
1184
1190
  }
1185
1191
  const topFolders = [...folderCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([f]) => f);
1186
1192
  communities.push({
1187
- id: commId++,
1193
+ id: 0,
1188
1194
  label,
1189
1195
  nodes,
1190
1196
  size: members.length,
@@ -1192,7 +1198,11 @@ async function zettelCommunities(backend, opts) {
1192
1198
  topFolders
1193
1199
  });
1194
1200
  }
1195
- communities.sort((a, b) => b.size - a.size);
1201
+ const minPath = (c) => c.nodes.map((n) => n.path).sort()[0];
1202
+ communities.sort((a, b) => b.size - a.size || minPath(a).localeCompare(minPath(b)));
1203
+ communities.forEach((c, i) => {
1204
+ c.id = i;
1205
+ });
1196
1206
  return {
1197
1207
  communities: communities.slice(0, maxCommunities),
1198
1208
  totalNodes: graph.nodes.length,
@@ -1203,4 +1213,4 @@ async function zettelCommunities(backend, opts) {
1203
1213
 
1204
1214
  //#endregion
1205
1215
  export { zettelThemes as a, zettelExplore as c, zettelHealth as i, zettelGodNotes as n, zettelConverse as o, zettelSuggest as r, zettelSurprise as s, zettelCommunities as t };
1206
- //# sourceMappingURL=zettelkasten-Cr_Xj0mG.mjs.map
1216
+ //# sourceMappingURL=zettelkasten-BzMm8REH.mjs.map
package/docs/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # PAI documentation
2
2
 
3
+ **Start here: [everything PAI does](features.md)**: every capability by family, with the command or phrase to use.
4
+
3
5
  ## Words used in these docs
4
6
 
5
7
  - **PAI home**: the directory where PAI keeps its files (`config.yaml`, `workers.yaml`, keys, logs, state). It is `~/.pai`; installs from before the move use `~/.claude/pai` until `pai home migrate` is run. `pai home path` prints the one in use, `pai worker config path` prints the path of `workers.yaml`. Details: [PAI home](pai-home.md). Where a page writes `<PAI home>`, read this directory.
package/docs/cockpit.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  The cockpit is one web page served by the [router](concepts/router.md). It answers four questions in one place: how full are my provider limits, where do delegated workers go and what are they doing, what are the local model servers and the machine doing, and where do my tokens and cache hits go. It is mostly read-only. The few controls it has start and stop local models and name them.
4
4
 
5
- ![The cockpit's top: Limits and local servers with the local server tiles and the cloud provider gauges, then Routing with one line per delegation tier](images/cockpit-limits-routing.jpg)
5
+ ![Worker runs, speed per model, and Routing with one line per delegation tier](images/cockpit-06-runs-speed-routing.jpg)
6
6
 
7
7
  ## Open it
8
8
 
@@ -61,7 +61,7 @@ A runtime's note (`models.runtimes.<name>.note`) is the tooltip of the runtime c
61
61
 
62
62
  A card folds by clicking its header. By default a running coding runtime is open and the rest are folded.
63
63
 
64
- ![Models: the local engine card with speed, memory, workers and conversation cache tiles and the local model switch, then one card per consumer on the shared runtimes](images/cockpit-models.jpg)
64
+ ![Local servers with their instances, the Models cards with start and stop per model, and the Worker pool](images/cockpit-03-local-servers-models-pool.jpg)
65
65
 
66
66
  ### Memory (`memory`)
67
67
 
@@ -76,7 +76,9 @@ Answers: is the machine under pressure. Metric tiles for memory, load, temperatu
76
76
 
77
77
  Tile grids never leave a partial last row: in wide mode the grid has 12 tracks, and when the last row is short its tiles widen to fill it, so there is no 3+1.
78
78
 
79
- ![Workers and the worker pool, the Models cards, System tiles and Totals in this window](images/cockpit-workers-system.jpg)
79
+ ![Workers running and waiting, and the Memory section with backend, passes, embedding and index progress](images/cockpit-04-workers-memory.jpg)
80
+
81
+ ![System tiles for memory, load, temperature and power, the local model servers, and Tokens per bucket and per day per model](images/cockpit-01-system-tokens.jpg)
80
82
 
81
83
  ### Totals in this window (`kpis`)
82
84
 
@@ -90,7 +92,7 @@ Answers: when were tokens spent and of what kind. Stacked bars per time bucket i
90
92
 
91
93
  Answers: is the cache earning its keep. **Cache hit ratio** is `cache_read / (read + write + fresh input)`, one ring per provider and model; models under `lowRequestMin` requests are folded into a chip instead. A local server that reports no cache fields per request shows its own prefix-cache counter instead, marked `*` (it covers the time since that server started, so its window differs from the router log). **Providers** is one tile per provider; the tiles fill their row. Each has requests, tokens, average latency and time to first token.
92
94
 
93
- ![Cache hit ratio and Providers, Tokens per day per model and Tokens per bucket by kind](images/cockpit-usage.jpg)
95
+ ![Totals in this window, Cache hit ratio per model, the local prefix cache and Providers](images/cockpit-02-totals-cache.jpg)
94
96
 
95
97
  ### Speed per model (`speed`)
96
98
 
@@ -104,6 +106,8 @@ Answers: did the cache expire between turns. Per model, hits grouped by the paus
104
106
 
105
107
  Answers: which sessions cost the most. The top `sessionsRows` sessions with models, requests, tokens, fresh input, output, hit percentage, cache busts, errors and last activity. A worker session carries its verdict.
106
108
 
109
+ ![Performance details: Cache verdict by pause and Sessions by tokens](images/cockpit-05-performance.jpg)
110
+
107
111
  ### Worker runs (`runs`)
108
112
 
109
113
  Answers: how did delegated workers end. The latest `workerRows` workers as label, verdict and tokens; the label takes two lines at most, with the provider and run id small beneath, and the full label is in the tooltip. The verdict is a short word and its full text is in the tooltip. Verdicts: **ok** and **done** in green, **report flagged** in amber (the worker finished but its report needs a look), **failed** in red; anything else is dim.
@@ -137,6 +141,8 @@ Nothing about your arrangement is sent to the server, so a different browser sta
137
141
 
138
142
  ## Configuration
139
143
 
144
+ ![Settings: the model registry (workers.yaml) in the editor with validate, save and duplicate, and its backups with diff, name, restore and delete](images/cockpit-07-settings-registry.jpg)
145
+
140
146
  ### Choosing sections
141
147
 
142
148
  `router.cockpit.sections` is a list of section ids; only those are shown, in that order. A single page load can override it:
@@ -24,7 +24,7 @@ Generated reference for every `pai` command. Read any page in the terminal with
24
24
  | [`pai home`](home.md) | Where PAI keeps its files; move them out of ~/.claude |
25
25
  | [`pai hooks-db`](hooks-db.md) | Registry updates for the stop and pre-compact hooks |
26
26
  | [`pai identity`](identity.md) | Say who you are, so mail to you can be told from mail to others |
27
- | [`pai install`](install.md) | First-time setup: storage, search, hooks, daemon |
27
+ | [`pai install`](install.md) | First-time setup: storage, search, hooks, daemon, router |
28
28
  | [`pai issue`](issue.md) | Claim and release forge issues for this project |
29
29
  | [`pai kg`](kg.md) | Facts extracted from your notes, with the time they were true |
30
30
  | [`pai launch`](launch.md) | Start Claude Code on a chosen provider (for scripts) |
@@ -55,7 +55,7 @@ Generated reference for every `pai` command. Read any page in the terminal with
55
55
  | [`pai router`](router.md) | Local model router: start, stop, restart, status, run, stats |
56
56
  | [`pai session`](session.md) | Work with sessions: list, open, new, rename |
57
57
  | [`pai sessions`](sessions.md) | Old plural session commands (use `ls` and `session`) |
58
- | [`pai setup`](setup.md) | First-time setup: storage, search, hooks, daemon |
58
+ | [`pai setup`](setup.md) | First-time setup: storage, search, hooks, daemon, router |
59
59
  | [`pai setups`](setups.md) | Orchestrator + worker combinations (save your own) |
60
60
  | [`pai shell-init`](shell-init.md) | Print the shell integration code |
61
61
  | [`pai skill`](skill.md) | How your skills are used |
@@ -137,7 +137,7 @@ Generated reference for every `pai` command. Read any page in the terminal with
137
137
  | `pai identity remove` | Stop treating an address as yours |
138
138
  | `pai identity set-delivery` | Choose where digests and "mail me" messages go |
139
139
  | `pai identity show` | Show your addresses and where mail is delivered |
140
- | `pai install` | First-time setup: storage, search, hooks, daemon |
140
+ | `pai install` | First-time setup: storage, search, hooks, daemon, router |
141
141
  | `pai issue` | Claim and release forge issues for this project |
142
142
  | `pai issue claim` | Mark issue N as yours (assignee and in-progress label) |
143
143
  | `pai issue claims` | List the issues of this project marked in-progress |
@@ -326,7 +326,7 @@ Generated reference for every `pai` command. Read any page in the terminal with
326
326
  | `pai sessions route` | Link a session note to another project |
327
327
  | `pai sessions slug` | Suggest a short name for a session note from its transcript |
328
328
  | `pai sessions tag` | Show or set the tags of a session note |
329
- | `pai setup` | First-time setup: storage, search, hooks, daemon |
329
+ | `pai setup` | First-time setup: storage, search, hooks, daemon, router |
330
330
  | `pai setups` | Orchestrator + worker combinations (save your own) |
331
331
  | `pai setups save` | Save the current combination under a name |
332
332
  | `pai shell-init` | Print the shell integration code |
@@ -13,10 +13,12 @@ Copies the registry database and config into a dated folder under PAI_HOME/backu
13
13
  | Flag | Type | Default | Description |
14
14
  |---|---|---|---|
15
15
  | `--no-postgres` | flag | — | Skip the Postgres dump (faster; registry and config only) |
16
+ | `--dry-run` | flag | — | Print the database that would be dumped, write nothing |
16
17
 
17
18
  ```sh
18
19
  pai backup
19
20
  pai backup --no-postgres
21
+ pai backup --dry-run
20
22
  ```
21
23
 
22
24
  See also: `pai restore`
@@ -2,25 +2,50 @@
2
2
 
3
3
  # pai install
4
4
 
5
- First-time setup: storage, search, hooks, daemon
5
+ First-time setup: storage, search, hooks, daemon, router
6
6
 
7
7
  ```
8
8
  pai install [options]
9
9
  ```
10
10
 
11
- Walks through everything PAI needs: where data is stored, search embeddings, Claude Code hooks and settings, the background daemon and the first index.
12
- Safe to run again. With --yes it takes every default and asks nothing.
11
+ Walks through everything PAI needs: where data is stored, search embeddings, Claude Code hooks and settings, the background daemon, the router and cockpit (port, reach), AIBroker (messaging; installed automatically) and the first index.
12
+ Safe to run again. With --yes it takes every default and asks nothing; every question has a flag, so `pai setup --yes <flags>` can express any answer. `pai setup --questions [--json]` lists the questions with their flags, defaults and current values (for callers without a terminal).
13
13
 
14
14
  Shortcut for `pai setup`.
15
15
 
16
16
  | Flag | Type | Default | Description |
17
17
  |---|---|---|---|
18
- | `-y, --yes` | flag | — | Take every default and read no input |
18
+ | `-y, --yes` | flag | — | Take every default (or the flag given) and read no input |
19
+ | `--questions` | flag | — | Print every question with its flag, default and allowed values; change nothing |
20
+ | `--json` | flag | — | With --questions: machine-readable JSON |
19
21
  | `--storage BACKEND` | string | — | Where to store data: sqlite or postgres (with --yes: sqlite unless a local Postgres answers) |
22
+ | `--pg-url URL` | string | — | PostgreSQL connection string (implies --storage postgres) |
23
+ | `--embedding MODEL` | string | — | Embeddings: snowflake, bge, nomic, ollama (Arctic on Ollama) or none |
24
+ | `--da-name NAME` | string | — | What the assistant is called (default PAI) |
25
+ | `--router` | flag | — | Enable the router and cockpit (default) |
26
+ | `--no-router` | flag | — | Do not enable the router and cockpit |
27
+ | `--router-port PORT` | number | — | Cockpit port (default: config router.port, 8790) |
28
+ | `--router-bind SCOPE` | string | — | Who reaches the cockpit: loopback (default), tailscale or an IPv4 address |
29
+ | `--no-aibroker` | flag | — | Do not install AIBroker (the messaging layer) |
30
+ | `--no-claude-md` | flag | — | Skip: Write ~/.claude/CLAUDE.md from the PAI template? |
31
+ | `--no-skill` | flag | — | Skip: Install the PAI skill? |
32
+ | `--no-steering-rules` | flag | — | Skip: Install the AI steering rules? |
33
+ | `--no-skill-stubs` | flag | — | Skip: Symlink the PAI skill stubs into ~/.claude/skills/? |
34
+ | `--no-hooks` | flag | — | Skip: Install the lifecycle hooks (session stop, pre-compact, statusline)? |
35
+ | `--no-ts-hooks` | flag | — | Skip: Install the TypeScript hooks to ~/.claude/Hooks/? |
36
+ | `--no-settings` | flag | — | Skip: Patch ~/.claude/settings.json with PAI hooks, env vars and settings? |
37
+ | `--no-daemon` | flag | — | Skip: Install the daemon as a login service? |
38
+ | `--no-mcp` | flag | — | Skip: Register the PAI MCP server in ~/.claude.json? |
39
+ | `--registry-scan` | flag | — | Do: Run `pai registry scan` after setup? |
40
+ | `--task-bus` | flag | — | Do: Enable the task bus (needs a Todoist account)? |
41
+ | `--no-workers` | flag | — | Skip: Turn workers on with the built-in anthropic provider? |
42
+ | `--dry-run` | flag | — | Validate the flags, print the AIBroker install commands and change nothing (other steps are not previewed) |
20
43
 
21
44
  ```sh
22
45
  pai setup
23
46
  pai setup --yes --storage sqlite
47
+ pai setup --questions --json
48
+ pai setup --yes --storage sqlite --embedding none --router-port 9000 --router-bind tailscale --no-hooks
24
49
  ```
25
50
 
26
51
  See also: `pai update`, `pai daemon status`
@@ -70,7 +70,7 @@ ChatGPT plan through the Codex CLI: --engine codex. Image generation: --engine i
70
70
  | `--base-url URL` | string | — | Anthropic-compatible API base URL (required unless --protocol openai) |
71
71
  | `--url URL` | string | — | Same as --base-url |
72
72
  | `--model ID` | string | — | Default model id for this provider (required) |
73
- | `--key TOKEN` | string | — | API token, written into workers.yaml; use instead of --key-file |
73
+ | `--key TOKEN` | string | — | API token, written into workers.yaml; visible in ps and shell history, prefer --key-file |
74
74
  | `--key-file PATH` | string | — | File holding the API token (kept private); leave out for a local server |
75
75
  | `--fast-model ID` | string | — | Cheaper model for quick checks and routing |
76
76
  | `--env NAME=VALUE` | string | — | Extra environment variable for runs (repeat for several) |
@@ -18,9 +18,13 @@ Overwrites the current registry, config and (unless skipped) the Postgres databa
18
18
  |---|---|---|---|
19
19
  | `--no-postgres` | flag | — | Do not restore the Postgres database |
20
20
  | `--yes` | flag | — | Do not ask for confirmation |
21
+ | `--into DB` | string | — | Restore into this Postgres database instead of the daemon's (required when the backup came from another database) |
22
+ | `--no-safety-dump` | flag | — | Do not dump the live database before replacing it (a failed safety dump otherwise aborts the restore) |
23
+ | `--dry-run` | flag | — | Print the target and source databases, change nothing |
21
24
 
22
25
  ```sh
23
26
  pai restore
27
+ pai restore --dry-run
24
28
  pai restore ~/.pai/backups/20260101-120000 --no-postgres --yes
25
29
  ```
26
30
 
@@ -2,23 +2,48 @@
2
2
 
3
3
  # pai setup
4
4
 
5
- First-time setup: storage, search, hooks, daemon
5
+ First-time setup: storage, search, hooks, daemon, router
6
6
 
7
7
  ```
8
8
  pai setup [options]
9
9
  ```
10
10
 
11
- Walks through everything PAI needs: where data is stored, search embeddings, Claude Code hooks and settings, the background daemon and the first index.
12
- Safe to run again. With --yes it takes every default and asks nothing.
11
+ Walks through everything PAI needs: where data is stored, search embeddings, Claude Code hooks and settings, the background daemon, the router and cockpit (port, reach), AIBroker (messaging; installed automatically) and the first index.
12
+ Safe to run again. With --yes it takes every default and asks nothing; every question has a flag, so `pai setup --yes <flags>` can express any answer. `pai setup --questions [--json]` lists the questions with their flags, defaults and current values (for callers without a terminal).
13
13
 
14
14
  | Flag | Type | Default | Description |
15
15
  |---|---|---|---|
16
- | `-y, --yes` | flag | — | Take every default and read no input |
16
+ | `-y, --yes` | flag | — | Take every default (or the flag given) and read no input |
17
+ | `--questions` | flag | — | Print every question with its flag, default and allowed values; change nothing |
18
+ | `--json` | flag | — | With --questions: machine-readable JSON |
17
19
  | `--storage BACKEND` | string | — | Where to store data: sqlite or postgres (with --yes: sqlite unless a local Postgres answers) |
20
+ | `--pg-url URL` | string | — | PostgreSQL connection string (implies --storage postgres) |
21
+ | `--embedding MODEL` | string | — | Embeddings: snowflake, bge, nomic, ollama (Arctic on Ollama) or none |
22
+ | `--da-name NAME` | string | — | What the assistant is called (default PAI) |
23
+ | `--router` | flag | — | Enable the router and cockpit (default) |
24
+ | `--no-router` | flag | — | Do not enable the router and cockpit |
25
+ | `--router-port PORT` | number | — | Cockpit port (default: config router.port, 8790) |
26
+ | `--router-bind SCOPE` | string | — | Who reaches the cockpit: loopback (default), tailscale or an IPv4 address |
27
+ | `--no-aibroker` | flag | — | Do not install AIBroker (the messaging layer) |
28
+ | `--no-claude-md` | flag | — | Skip: Write ~/.claude/CLAUDE.md from the PAI template? |
29
+ | `--no-skill` | flag | — | Skip: Install the PAI skill? |
30
+ | `--no-steering-rules` | flag | — | Skip: Install the AI steering rules? |
31
+ | `--no-skill-stubs` | flag | — | Skip: Symlink the PAI skill stubs into ~/.claude/skills/? |
32
+ | `--no-hooks` | flag | — | Skip: Install the lifecycle hooks (session stop, pre-compact, statusline)? |
33
+ | `--no-ts-hooks` | flag | — | Skip: Install the TypeScript hooks to ~/.claude/Hooks/? |
34
+ | `--no-settings` | flag | — | Skip: Patch ~/.claude/settings.json with PAI hooks, env vars and settings? |
35
+ | `--no-daemon` | flag | — | Skip: Install the daemon as a login service? |
36
+ | `--no-mcp` | flag | — | Skip: Register the PAI MCP server in ~/.claude.json? |
37
+ | `--registry-scan` | flag | — | Do: Run `pai registry scan` after setup? |
38
+ | `--task-bus` | flag | — | Do: Enable the task bus (needs a Todoist account)? |
39
+ | `--no-workers` | flag | — | Skip: Turn workers on with the built-in anthropic provider? |
40
+ | `--dry-run` | flag | — | Validate the flags, print the AIBroker install commands and change nothing (other steps are not previewed) |
18
41
 
19
42
  ```sh
20
43
  pai setup
21
44
  pai setup --yes --storage sqlite
45
+ pai setup --questions --json
46
+ pai setup --yes --storage sqlite --embedding none --router-port 9000 --router-bind tailscale --no-hooks
22
47
  ```
23
48
 
24
49
  See also: `pai update`, `pai daemon status`
@@ -876,7 +876,7 @@ ChatGPT plan through the Codex CLI: --engine codex. Image generation: --engine i
876
876
  | `--base-url URL` | string | — | Anthropic-compatible API base URL (required unless --protocol openai) |
877
877
  | `--url URL` | string | — | Same as --base-url |
878
878
  | `--model ID` | string | — | Default model id for this provider (required) |
879
- | `--key TOKEN` | string | — | API token, written into workers.yaml; use instead of --key-file |
879
+ | `--key TOKEN` | string | — | API token, written into workers.yaml; visible in ps and shell history, prefer --key-file |
880
880
  | `--key-file PATH` | string | — | File holding the API token (kept private); leave out for a local server |
881
881
  | `--fast-model ID` | string | — | Cheaper model for quick checks and routing |
882
882
  | `--env NAME=VALUE` | string | — | Extra environment variable for runs (repeat for several) |
package/docs/config.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # config.yaml
2
2
 
3
+ The router and cockpit answers (`router.enabled`, `router.port`, `router.bind`) are asked by `pai setup`; the questions and their flags are listed in [Setup questions and flags](install/index.md#setup-questions-and-flags).
4
+
3
5
  The main PAI config: search defaults, storage backend, notifications, task bus, identity, the non-provider `workers` settings, the router and cockpit, plus whatever else a writer has stashed in the file. `pai config list|get|set|unset` and the matching `config_*` MCP tools read and change it whether the file is YAML or JSON; `pai config yaml` converts an old `config.json` to commented YAML; `pai config migrate` moves old per-user files into the PAI home.
4
6
 
5
7
  ## Shipped defaults and precedence