@tekmidian/pai 1.0.0 → 1.0.2

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 (218) 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-B4azPk4l.mjs} +3 -3
  7. package/dist/auto-route-BjoMHKyI.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-D-yvET_y.mjs} +5 -5
  12. package/dist/cli/index.mjs +1621 -357
  13. package/dist/cockpit-actions-BWunx3rY.mjs +20 -0
  14. package/dist/{cockpit-actions-ODmt8yF9.mjs → cockpit-actions-C8GlTzts.mjs} +84 -42
  15. package/dist/cockpit-memory-vTlFWV7F.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-BcKFHeG1.mjs} +37 -22
  21. package/dist/daemon/index.mjs +43 -42
  22. package/dist/{daemon-CorGh6Ub.mjs → daemon-ColVHwGZ.mjs} +103 -55
  23. package/dist/daemon-N7WhYi6I.mjs +45 -0
  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 +214 -116
  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-_a6UNhXJ.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-BtB3Se6f.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-DurzIbw8.mjs} +7 -6
  83. package/dist/{pane-audit-OGYrOAik.mjs → pane-audit-BQytYa60.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-BM27GBfC.mjs} +31 -30
  87. package/dist/{pool-CZ5MZaXg.mjs → pool-BRvoOkv6.mjs} +3 -3
  88. package/dist/{pool-cli-BxNSPzzY.mjs → pool-cli-B_YR8_Gl.mjs} +5 -5
  89. package/dist/{pool-cli-CbJfl37y.mjs → pool-cli-DkZTAlSW.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-CfpApz5o.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-C7b6givx.mjs +9 -0
  97. package/dist/{registrable-LrRIVYQc.mjs → registrable-Uzgmfyhz.mjs} +4 -4
  98. package/dist/render-Cc2j5QG9.mjs +13 -0
  99. package/dist/{render-BDbb4CF-.mjs → render-CwIrgxLi.mjs} +8 -8
  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-BMeJuHOb.mjs → root-BWy0c2Lq.mjs} +11 -11
  103. package/dist/root-wC_6Fx0B.mjs +36 -0
  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-6Q9kCPem.mjs} +35 -33
  110. package/dist/{scan-B7I0gPe-.mjs → scan-ZQWm-_se.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-Bok2PqRS.mjs +35 -0
  116. package/dist/{session-CNXF6DLP.mjs → session-DVUExUnX.mjs} +55 -31
  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-DtWj5Vti.mjs → viewer-DcpJwGKE.mjs} +15 -15
  128. package/dist/viewer-MWBVJP3u.mjs +22 -0
  129. package/dist/{wait-BMUR-U-U.mjs → wait-ByV0OyMZ.mjs} +3 -3
  130. package/dist/{worker-config-BLqa1yiD.mjs → worker-config-BDYNxbYz.mjs} +294 -92
  131. package/dist/worker-config-gmAq_-rI.mjs +41 -0
  132. package/dist/{workers-config-DEI9lrV4.mjs → workers-config-f8KrkY4L.mjs} +2 -2
  133. package/dist/{worktree-zmRf556h.mjs → worktree-CrnOqTBW.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.svg +3 -0
  149. package/docs/images/cockpit-01-system-tokens.jpg +0 -0
  150. package/docs/images/cockpit-02-totals-cache.jpg +0 -0
  151. package/docs/images/cockpit-03-local-servers-models-pool.jpg +0 -0
  152. package/docs/images/cockpit-04-workers-memory.jpg +0 -0
  153. package/docs/images/cockpit-05-performance.jpg +0 -0
  154. package/docs/images/cockpit-06-runs-speed-routing.jpg +0 -0
  155. package/docs/images/cockpit-07-settings-registry.jpg +0 -0
  156. package/docs/install/index.md +29 -0
  157. package/docs/three-tier-coding.md +1 -1
  158. package/gemini-extension.json +1 -1
  159. package/package.json +1 -5
  160. package/pai-plugin.json +1 -1
  161. package/plugins/context-preservation/plugin.json +1 -1
  162. package/plugins/core/plugin.json +1 -1
  163. package/plugins/core/skills/setup/SKILL.md +41 -9
  164. package/plugins/creative/plugin.json +1 -1
  165. package/plugins/observability/plugin.json +1 -1
  166. package/plugins/productivity/plugin.json +1 -1
  167. package/plugins/semantic-search/plugin.json +1 -1
  168. package/plugins/ui/plugin.json +1 -1
  169. package/plugins/zettelkasten/plugin.json +1 -1
  170. package/src/hooks/session-autosave.sh +8 -1
  171. package/src/hooks/session-stop.sh +8 -1
  172. package/src/hooks/ts/capture-all-events.ts +7 -12
  173. package/src/hooks/ts/lib/context-fill.ts +2 -1
  174. package/src/hooks/ts/lib/path-repair.ts +1 -1
  175. package/src/hooks/ts/lib/project-utils/notify.ts +1 -0
  176. package/src/hooks/ts/lib/project-utils/session-notes.ts +23 -6
  177. package/src/hooks/ts/lib/raw-capture.ts +36 -0
  178. package/src/hooks/ts/lib/session-summary.ts +129 -0
  179. package/src/hooks/ts/lib/todo-sync.ts +120 -0
  180. package/src/hooks/ts/lib/worker-git-guard.ts +1 -1
  181. package/src/hooks/ts/post-tool-use/capture-tool-output.ts +6 -10
  182. package/src/hooks/ts/post-tool-use/sync-todo-to-md.ts +5 -105
  183. package/src/hooks/ts/pre-compact/context-compression-hook.ts +1 -1
  184. package/src/hooks/ts/pre-tool-use/security-validator.ts +35 -14
  185. package/src/hooks/ts/session-end/capture-session-summary.ts +20 -128
  186. package/src/hooks/ts/session-start/load-core-context.ts +3 -3
  187. package/src/hooks/ts/session-start/load-project-context.ts +18 -22
  188. package/src/hooks/ts/stop/stop-hook.ts +13 -5
  189. package/src/hooks/ztk-auto.sh +7 -2
  190. package/dist/aibroker-client-JjE74jo0.mjs +0 -3
  191. package/dist/auto-route-BRk8NEFv.mjs +0 -11
  192. package/dist/budget-DuhQ2zzG.mjs +0 -14
  193. package/dist/cockpit-actions-DcQ-ucU8.mjs +0 -19
  194. package/dist/cockpit-memory-KV45PPO2.mjs +0 -19
  195. package/dist/daemon-C7yt_ptC.mjs +0 -44
  196. package/dist/detect-DRUkmHnb.mjs +0 -10
  197. package/dist/factory-DAGG9_n8.mjs +0 -9
  198. package/dist/helpers-DPJEHPq6.mjs +0 -10
  199. package/dist/kill-tree-LV0Q7Mte.mjs +0 -10
  200. package/dist/operator-CfL0HiBK.mjs +0 -7
  201. package/dist/postgres-DgqWyqhN.mjs +0 -7
  202. package/dist/providers-CTu2s1z2.mjs +0 -15
  203. package/dist/registrable-D9aNZOTh.mjs +0 -9
  204. package/dist/render-BSfVlYHj.mjs +0 -13
  205. package/dist/root-xI9DqVIe.mjs +0 -35
  206. package/dist/route-table-HjvnLVEU.mjs +0 -14
  207. package/dist/session-BJHzmUg2.mjs +0 -34
  208. package/dist/session-scan-YORKE1NO.mjs +0 -9
  209. package/dist/viewer-B8709jDN.mjs +0 -22
  210. package/dist/worker-config-D8tRuvo7.mjs +0 -40
  211. package/docs/images/cockpit-limits-routing.jpg +0 -0
  212. package/docs/images/cockpit-models.jpg +0 -0
  213. package/docs/images/cockpit-usage.jpg +0 -0
  214. package/docs/images/cockpit-workers-system.jpg +0 -0
  215. package/scripts/build-docs.mjs +0 -41
  216. package/scripts/build-hooks.mjs +0 -311
  217. package/scripts/build-skill-stubs.mjs +0 -216
  218. package/scripts/copy-defaults.mjs +0 -46
@@ -2,7 +2,7 @@
2
2
  "name": "pai",
3
3
  "displayName": "PAI Knowledge OS",
4
4
  "description": "Personal AI Infrastructure — persistent memory, session continuity, and knowledge graph for Claude Code",
5
- "version": "1.0.0",
5
+ "version": "1.0.2",
6
6
  "author": {
7
7
  "name": "Matthias Nott"
8
8
  },
package/README.md CHANGED
@@ -1,25 +1,87 @@
1
1
  # PAI Knowledge OS
2
2
 
3
- PAI is an operating layer for Claude Code. From the first day it gives every session a memory: notes written in the background, searchable across sessions, projects and vaults, all stored locally. `pai` starts or resumes a Claude Code session in the current project, and `pai pause` and `pai end` save your place.
3
+ ## Local AI used to be hard. Now it is a button.
4
4
 
5
- It can also hand work to cheaper background Claude Code runs (workers) on other providers or a local model, with a router and a cockpit page that show what the models and your token budget are doing. You do not need this to start. Terms are explained in the [glossary](docs/README.md#words-used-in-these-docs).
5
+ I have spent a long time on local AI. Getting a strong model to run on my own machine was the easy part; making it actually useful was not. Which server, which quantization, which port, how to keep it alive, how to send it only the work it can do, and how to fall back to the cloud when it cannot. Every piece worked on its own and none of them worked together.
6
6
 
7
- ![The PAI router cockpit: limits per cloud provider, the local model server, and the routing table with one line per delegation tier](docs/images/cockpit-limits-routing.jpg)
7
+ PAI is what came out of that, and I am giving it to the community. A MacBook can already run a serious model: on mine, [Strata](https://github.com/Niko1221/Strata) serves [Qwen3.8-Flash-Next](https://huggingface.co/Qwen/Qwen3.8-Flash-Next) in its compact [Gyro-M](https://huggingface.co/agentionai/Qwen3.8-Flash-Next-Gyro-GGUF) quantization, and PAI turns that into a worker like any other. Start it from the cockpit, and PAI routes worker jobs to it automatically, shows its speed and cache live, and hands a job to the cloud only when it needs a wider context or deeper reasoning than the local model has. You stop thinking about local AI. It just takes its share of the work.
8
+
9
+ **An AI chat is one vendor, one model, one budget and no memory. PAI turns it into a team: it remembers, it routes every job to the right model, cloud or local, and it shows you all of it live.**
10
+
11
+ You burn your premium tokens on work a local model could do. You hit the weekly limit on a Tuesday. Every new session starts from zero. PAI fixes all three:
12
+
13
+ - **Not bound to Anthropic.** Claude Code is only the front end you type into; the model behind it is your choice. Run a whole session on GLM, Kimi, any other provider you add, or a model on your own machine, with no Anthropic model involved at all. Or mix them: switch on the fly with `/model`, in the middle of a session, without losing your place.
14
+ - **Model routing, cloud and local.** When one provider's budget runs out, the next one takes over by itself, and every request is accounted per provider and per session.
15
+ - **A hierarchy that spends tokens where they matter.** Three tiers: `t0` the session you talk to, `t1` the orchestrator that plans and reviews, `t2` the workers that implement. Workers go local first, because local tokens are free. Cloud comes first only where it earns its price: wide context and real reasoning. And all of it is yours to set: each tier is an ordered list of models, the first available one serves, and you change the order as your default (`pai worker route set t2 local,glm/glm-5.3-flash`, or from the cockpit) or just for one session (`--session <name>`), without touching the others. Every worker runs in its own visible pane and git worktree; you review the diff, PAI merges it.
16
+ - **A live cockpit.** One page shows your token budget per provider, cache hits, every model and local server with start and stop buttons, running workers, routing per tier, and memory and embedding progress. Drag the cards into the layout you want.
17
+ - **Memory underneath it all.** Every session writes its own notes in the background, searchable across sessions, projects and your notes vault, by keyword, meaning or both. Everything stays on your machine.
18
+
19
+ **What's inside**
20
+
21
+ - Sessions: [pick and open](docs/features.md#pick-and-open-a-session) · [pause and end](docs/features.md#pause-and-end-a-session) · [session notes](docs/features.md#session-notes) · [context preservation](docs/features.md#context-preservation-and-auto-compact)
22
+ - Memory and search: [search memory](docs/features.md#search-your-memory) · [knowledge graph](docs/features.md#knowledge-graph) · [embeddings](docs/features.md#index-and-embeddings) · [observations](docs/features.md#observations)
23
+ - Notes and vault: [connect two ideas](docs/features.md#connect-two-ideas) · [find orphans](docs/features.md#find-orphans) · [what is emerging](docs/features.md#what-is-emerging) · [trace an idea](docs/features.md#trace-an-idea)
24
+ - Zettelkasten: [explore links](docs/features.md#explore-links) · [surprising connections](docs/features.md#surprising-connections) · [ask the vault](docs/features.md#ask-the-vault) · [vault health](docs/features.md#vault-health)
25
+ - Journal, review, plan: [journal](docs/features.md#journal) · [review](docs/features.md#review) · [plan](docs/features.md#plan)
26
+ - Tasks and ingress: [Todoist](docs/features.md#todoist-as-an-input-channel) · [GitHub issues](docs/features.md#github-issues-as-an-input-channel) · [PAILot](docs/features.md#pailot-as-an-input-channel) · [WhatsApp](docs/features.md#whatsapp-as-an-input-channel) · [Telegram](docs/features.md#telegram-as-an-input-channel)
27
+ - Workers: [run a worker](docs/features.md#run-a-worker) · [tiers and routing](docs/features.md#tiers-and-routing) · [local models](docs/features.md#local-models) · [plans](docs/features.md#plans) · [queue](docs/features.md#queue)
28
+ - Router and cockpit: [router](docs/features.md#router) · [cockpit](docs/features.md#cockpit) · [where tokens go](docs/features.md#where-tokens-go)
29
+ - Messaging and rules: [AIBroker](docs/features.md#aibroker) · [whisper rules](docs/features.md#whisper-rules) · [budget advisor](docs/features.md#budget-and-advisor-mode)
30
+ - Make and share: [art and diagrams](docs/features.md#art-and-diagrams) · [share](docs/features.md#share) · [research](docs/features.md#research-and-extraction)
31
+ - Care: [setup](docs/features.md#setup-and-update) · [backup](docs/features.md#backup-and-restore)
32
+
33
+ Everything PAI does: [docs/features.md](docs/features.md)
34
+
35
+ `pai` starts or resumes a session in the current project. `pai pause` and `pai end` save your place. Memory works on its own; the router, workers and cockpit join when you want them. Terms are explained in the [glossary](docs/README.md#words-used-in-these-docs).
36
+
37
+ **Install it in one sentence: tell Claude Code "Clone https://github.com/mnott/PAI and set it up for me".** [Jump to install](#install).
38
+
39
+ ![Cockpit: system memory, load, temperature and power, local model server speed, and tokens per bucket and per day per model](docs/images/cockpit-01-system-tokens.jpg)
40
+
41
+ ![Cockpit: totals in the window, cache hit ratio per model, local prefix cache and providers](docs/images/cockpit-02-totals-cache.jpg)
42
+
43
+ ![Cockpit: local servers with their instances, the models with start and stop, and the worker pool](docs/images/cockpit-03-local-servers-models-pool.jpg)
44
+
45
+ ![Cockpit: workers running and waiting, and the memory section with backend, passes, embedding and index progress](docs/images/cockpit-04-workers-memory.jpg)
46
+
47
+ ![Cockpit: performance details with the cache verdict by pause and sessions by tokens](docs/images/cockpit-05-performance.jpg)
48
+
49
+ ![Cockpit: worker runs, speed per model, and routing with one line per delegation tier](docs/images/cockpit-06-runs-speed-routing.jpg)
50
+
51
+ ![Cockpit: settings with the model registry editor and its backups](docs/images/cockpit-07-settings-registry.jpg)
8
52
 
9
53
  *The router cockpit (`http://127.0.0.1:8790/cockpit`). See [the cockpit page](docs/cockpit.md).*
10
54
 
55
+ ## How it fits together
56
+
57
+ <img src="docs/images/architecture.svg" width="100%" alt="PAI architecture: Claude Code sessions with PAI hooks and skills on top; PAI core (CLI, daemon, storage, notes, router on port 8790 with tiers t0, t1, t2 and the cockpit, workers) side by side with AIBroker (messaging hub, session control, inbound channels with prefixes); ingress from Todoist, GitHub issues, PAILot, WhatsApp and Telegram feeding AIBroker; model providers Anthropic, other cloud and local models behind the router; an operating system layer with iTerm2 and tmux for worker panes and session tabs, launchd or systemd services, and git worktrees">
58
+
59
+ *Source: [docs/images/architecture.drawio](docs/images/architecture.drawio), editable in draw.io.*
60
+
11
61
  ## Install
12
62
 
13
63
  Prerequisites: [Claude Code](https://claude.com/claude-code) and Node.js 20 or newer. Docker is only needed for the optional PostgreSQL storage (semantic search); the default sqlite needs nothing.
14
64
 
15
- Inside Claude Code, add this repository as a plugin marketplace and install the `pai` plugin:
65
+ The easy way: tell Claude Code
66
+
67
+ > Clone https://github.com/mnott/PAI and set it up for me
68
+
69
+ Claude reads this repository, finds the setup skill and walks you through it: it checks each phase first, does only what is missing, and ends with a pass/fail list of its checks.
70
+
71
+ Or install it as a plugin, then say **"set up PAI"**:
16
72
 
17
73
  ```
18
74
  /plugin marketplace add mnott/PAI
19
75
  /plugin install pai@pai
20
76
  ```
21
77
 
22
- Then say **"set up PAI"**. `/plugin` lists `pai` once it is installed. The skill checks each phase first and does only what is missing, and ends with a pass/fail list of its checks.
78
+ Setup also installs [AIBroker](https://github.com/mnott/AIBroker), a separate project that is PAI's messaging layer: messages between sessions, worker reports to the session that started them, terminal tab names, and WhatsApp, Telegram and PAILot all go through it. PAI starts without it, but none of that works until it is there. To install it by hand:
79
+
80
+ ```bash
81
+ npm install -g aibroker@^0.62.4
82
+ aibroker setup # service, MCP registration, Claude Code hooks
83
+ aibroker doctor # every check green, or it says exactly what to fix
84
+ ```
23
85
 
24
86
  Without the plugin, from a clone, or for a one-session plugin load: [docs/install/index.md](docs/install/index.md). Memory works as soon as setup is done; workers are optional ([First workers](docs/install/first-workers.md)).
25
87
 
@@ -0,0 +1,3 @@
1
+ import { i as switchToSession, n as fetchLiveSessions, r as sendToSession, t as callAiBroker } from "./aibroker-client-CQPGqLxL.mjs";
2
+
3
+ export { callAiBroker, sendToSession };
@@ -177,4 +177,4 @@ async function switchToSession(target, opts = {}) {
177
177
 
178
178
  //#endregion
179
179
  export { switchToSession as i, fetchLiveSessions as n, sendToSession as r, callAiBroker as t };
180
- //# sourceMappingURL=aibroker-client-CXEYBzbf.mjs.map
180
+ //# sourceMappingURL=aibroker-client-CQPGqLxL.mjs.map
@@ -0,0 +1,21 @@
1
+ import { mkdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
2
+ import { randomBytes } from "node:crypto";
3
+ import { dirname } from "node:path";
4
+
5
+ //#region src/config/atomic-file.ts
6
+ /** Write text to a temp file and rename it over `path`: a crash mid-write leaves the old file intact. */
7
+ function writeFileAtomic(path, text) {
8
+ mkdirSync(dirname(path), { recursive: true });
9
+ const tmp = `${path}.${process.pid}.${randomBytes(4).toString("hex")}.tmp`;
10
+ try {
11
+ writeFileSync(tmp, text, "utf8");
12
+ renameSync(tmp, path);
13
+ } catch (e) {
14
+ rmSync(tmp, { force: true });
15
+ throw e;
16
+ }
17
+ }
18
+
19
+ //#endregion
20
+ export { writeFileAtomic as t };
21
+ //# sourceMappingURL=atomic-file-BorMa4T3.mjs.map
@@ -1,5 +1,5 @@
1
- import { r as readPaiMarker } from "./pai-marker-kIYuNt3c.mjs";
2
- import { i as populateSlugs } from "./search-CPoE0830.mjs";
1
+ import { r as readPaiMarker } from "./pai-marker-DurzIbw8.mjs";
2
+ import { i as populateSlugs } from "./search-RSyeQqj1.mjs";
3
3
  import { existsSync } from "node:fs";
4
4
  import { dirname, resolve } from "node:path";
5
5
 
@@ -158,4 +158,4 @@ function formatAutoRouteJson(result) {
158
158
 
159
159
  //#endregion
160
160
  export { formatAutoRouteJson as n, detectTopicShift as r, autoRoute as t };
161
- //# sourceMappingURL=auto-route-D5SXrMpB.mjs.map
161
+ //# sourceMappingURL=auto-route-B4azPk4l.mjs.map
@@ -0,0 +1,11 @@
1
+ import "./config-XpZWOYOG.mjs";
2
+ import "./config-Bu1_vbY8.mjs";
3
+ import "./paths-CHifubDh.mjs";
4
+ import "./worktree-CrnOqTBW.mjs";
5
+ import "./status-ggJ7lgVg.mjs";
6
+ import "./pool-BRvoOkv6.mjs";
7
+ import "./registrable-Uzgmfyhz.mjs";
8
+ import "./pai-marker-DurzIbw8.mjs";
9
+ import { n as formatAutoRouteJson, t as autoRoute } from "./auto-route-B4azPk4l.mjs";
10
+
11
+ export { autoRoute, formatAutoRouteJson };
@@ -0,0 +1,15 @@
1
+ import "./config-XpZWOYOG.mjs";
2
+ import "./config-Bu1_vbY8.mjs";
3
+ import "./paths-CHifubDh.mjs";
4
+ import "./status-ggJ7lgVg.mjs";
5
+ import "./scope-D-h6F6DN.mjs";
6
+ import { A as budgetSkipReason, D as budgetExceeded, E as budgetCache, M as budgetWall, N as fetchBudgetReading, O as budgetFresh, P as pickBudgetWindow, T as BudgetCache, j as budgetUntilLabel, k as budgetFull, w as BUDGET_TTL_MS } from "./routing-BAAST9vT.mjs";
7
+ import "./tool-errors-7E13StWd.mjs";
8
+ import "./wait-ByV0OyMZ.mjs";
9
+ import "./local-tiers-BE4jGaMa.mjs";
10
+ import "./caller-identity-yLFb7CKq.mjs";
11
+ import "./capacity-DEveQdFV.mjs";
12
+ import "./local-instances-DOxSgT_L.mjs";
13
+ import "./local-candidate-DLdwQt0s.mjs";
14
+
15
+ export { BUDGET_TTL_MS, BudgetCache, budgetCache, budgetExceeded, budgetFresh, budgetFull, budgetSkipReason, budgetUntilLabel, budgetWall, fetchBudgetReading, pickBudgetWindow };
@@ -1,6 +1,7 @@
1
1
  import { g as paiHomePath, l as claudeHomeDir } from "./runtime-paths-WsO9sJFc.mjs";
2
- import { f as readMainConfigRaw } from "./config-BSXKyeJ1.mjs";
3
- import { i as itermUuid } from "./scope-D5VSQxe4.mjs";
2
+ import { f as readMainConfigRaw } from "./config-Bu1_vbY8.mjs";
3
+ import { i as itermUuid } from "./scope-D-h6F6DN.mjs";
4
+ import { n as minOf } from "./min-max-DrSRUaWQ.mjs";
4
5
  import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, rmdirSync, statSync, writeFileSync } from "node:fs";
5
6
  import { join } from "node:path";
6
7
 
@@ -271,7 +272,7 @@ async function buildNext(dir, idOrLabel, d = {}) {
271
272
  const t = all.find((x) => x.id === idOrLabel) ?? all.find((x) => x.label === idOrLabel && x.state === "waiting");
272
273
  if (!t) throw new Error(`no queued build "${idOrLabel}"`);
273
274
  if (t.state !== "waiting") throw new Error(`build ${t.id} is already running`);
274
- const lowest = Math.min(...all.filter((x) => x.state === "waiting").map((x) => x.seq));
275
+ const lowest = minOf(all.filter((x) => x.state === "waiting").map((x) => x.seq));
275
276
  writeTicket(dir, {
276
277
  ...t,
277
278
  seq: lowest - 1
@@ -369,5 +370,5 @@ function callerIdentity(env = process.env, deps = {}) {
369
370
  }
370
371
 
371
372
  //#endregion
372
- export { poolSlots as _, enqueue as a, testSlots as b, listBuildsSync as c, removeTicket as d, renderBuildQueue as f, buildSlots as g, waitReason as h, buildsDir as i, patchTicket as l, tryStart as m, buildLogPath as n, getTicket as o, ticketKind as p, buildNext as r, listBuilds as s, callerIdentity as t, releaseBuildsOf as u, slotsFor as v, stallMinutes as y };
373
- //# sourceMappingURL=caller-identity-CVTuiLSs.mjs.map
373
+ export { buildSlots as _, buildsDir as a, stallMinutes as b, listBuilds as c, releaseBuildsOf as d, removeTicket as f, waitReason as g, tryStart as h, buildNext as i, listBuildsSync as l, ticketKind as m, breakStaleMutex as n, enqueue as o, renderBuildQueue as p, buildLogPath as r, getTicket as s, callerIdentity as t, patchTicket as u, poolSlots as v, testSlots as x, slotsFor as y };
374
+ //# sourceMappingURL=caller-identity-yLFb7CKq.mjs.map
@@ -1,5 +1,5 @@
1
- import { m as isLocalProvider } from "./config-D5chi2LO.mjs";
2
- import { O as reconcileStatuses, g as isLive, s as alive, v as loadStatus, w as ownsPid, y as loadStatuses } from "./status-CvVi9cDf.mjs";
1
+ import { m as isLocalProvider } from "./config-XpZWOYOG.mjs";
2
+ import { O as reconcileStatuses, g as isLive, s as alive, v as loadStatus, w as ownsPid, y as loadStatuses } from "./status-ggJ7lgVg.mjs";
3
3
  import { mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
 
@@ -488,4 +488,4 @@ async function capacityGate(o) {
488
488
 
489
489
  //#endregion
490
490
  export { liveQueue as a, queuedText as c, resolveCap as d, sessionOf as f, staggerGate as h, effectiveCap as i, reorderQueue as l, recordWarmup as m, capacityGate as n, providerCap as o, sessionScopeKey as p, capacityOf as r, queueRows as s, admitCap as t, reorderQueueTo as u };
491
- //# sourceMappingURL=capacity-DaXrVj3J.mjs.map
491
+ //# sourceMappingURL=capacity-DEveQdFV.mjs.map
@@ -1,7 +1,7 @@
1
- import { j as readWorkersSection, wt as appendLedger } from "./config-D5chi2LO.mjs";
2
- import { i as ledgerPath, u as workersLogDir } from "./paths-DoIyRnhx.mjs";
3
- import { $ as isFlagToken, S as newWorkerId, nt as shortText } from "./status-CvVi9cDf.mjs";
4
- import { t as runWorker } from "./run-ulAi5dFD.mjs";
1
+ import { j as readWorkersSection, wt as appendLedger } from "./config-XpZWOYOG.mjs";
2
+ import { i as ledgerPath, u as workersLogDir } from "./paths-CHifubDh.mjs";
3
+ import { $ as isFlagToken, S as newWorkerId, nt as shortText } from "./status-ggJ7lgVg.mjs";
4
+ import { t as runWorker } from "./run-6Q9kCPem.mjs";
5
5
  import { existsSync, mkdirSync, readFileSync } from "node:fs";
6
6
  import { join } from "node:path";
7
7
 
@@ -163,4 +163,4 @@ async function runChain(opts, deps = {}) {
163
163
 
164
164
  //#endregion
165
165
  export { swapPromptArg as n, runChain as t };
166
- //# sourceMappingURL=chain-BcQlIlEd.mjs.map
166
+ //# sourceMappingURL=chain-D-yvET_y.mjs.map