@100xprompt/brain 0.0.0-stage → 0.1.1

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 (260) hide show
  1. package/LICENSE +48 -0
  2. package/README.md +235 -2
  3. package/package.json +48 -4
  4. package/src/adapters/aider/index.ts +8 -0
  5. package/src/adapters/aider/reader.ts +129 -0
  6. package/src/adapters/aider/records.ts +220 -0
  7. package/src/adapters/aider/writer.ts +269 -0
  8. package/src/adapters/amazon-q-cli/index.ts +8 -0
  9. package/src/adapters/amazon-q-cli/reader.ts +84 -0
  10. package/src/adapters/amazon-q-cli/records.ts +191 -0
  11. package/src/adapters/amazon-q-cli/writer.ts +370 -0
  12. package/src/adapters/amazon-q-ide/index.ts +9 -0
  13. package/src/adapters/amazon-q-ide/reader.ts +131 -0
  14. package/src/adapters/amazon-q-ide/records.ts +141 -0
  15. package/src/adapters/amazon-q-ide/writer.ts +325 -0
  16. package/src/adapters/antigravity/index.ts +9 -0
  17. package/src/adapters/antigravity/proto.ts +194 -0
  18. package/src/adapters/antigravity/reader.ts +424 -0
  19. package/src/adapters/antigravity/records.ts +236 -0
  20. package/src/adapters/antigravity/writer.ts +463 -0
  21. package/src/adapters/auggie/index.ts +36 -0
  22. package/src/adapters/claude-code/index.ts +8 -0
  23. package/src/adapters/claude-code/reader.ts +639 -0
  24. package/src/adapters/claude-code/records.ts +88 -0
  25. package/src/adapters/claude-code/writer.ts +329 -0
  26. package/src/adapters/cline/index.ts +12 -0
  27. package/src/adapters/cline/reader.ts +432 -0
  28. package/src/adapters/cline/records.ts +151 -0
  29. package/src/adapters/cline/vscdb.ts +56 -0
  30. package/src/adapters/cline/writer.ts +656 -0
  31. package/src/adapters/cline/xml.ts +177 -0
  32. package/src/adapters/cline4/index.ts +9 -0
  33. package/src/adapters/cline4/reader.ts +179 -0
  34. package/src/adapters/cline4/records.ts +92 -0
  35. package/src/adapters/cline4/writer.ts +361 -0
  36. package/src/adapters/codebuff/index.ts +8 -0
  37. package/src/adapters/codebuff/project.ts +207 -0
  38. package/src/adapters/codebuff/reader.ts +215 -0
  39. package/src/adapters/codebuff/records.ts +173 -0
  40. package/src/adapters/codebuff/writer.ts +383 -0
  41. package/src/adapters/codex/index.ts +8 -0
  42. package/src/adapters/codex/native.ts +239 -0
  43. package/src/adapters/codex/reader.ts +747 -0
  44. package/src/adapters/codex/records.ts +114 -0
  45. package/src/adapters/codex/writer.ts +479 -0
  46. package/src/adapters/continue/index.ts +9 -0
  47. package/src/adapters/continue/reader.ts +68 -0
  48. package/src/adapters/continue/records.ts +418 -0
  49. package/src/adapters/continue/writer.ts +162 -0
  50. package/src/adapters/copilot-cli/index.ts +9 -0
  51. package/src/adapters/copilot-cli/reader.ts +186 -0
  52. package/src/adapters/copilot-cli/records.ts +241 -0
  53. package/src/adapters/copilot-cli/writer.ts +353 -0
  54. package/src/adapters/crush/index.ts +8 -0
  55. package/src/adapters/crush/reader.ts +180 -0
  56. package/src/adapters/crush/records.ts +169 -0
  57. package/src/adapters/crush/writer.ts +333 -0
  58. package/src/adapters/cursor-cli/index.ts +405 -0
  59. package/src/adapters/cursor-ide/agentkv.ts +95 -0
  60. package/src/adapters/cursor-ide/index.ts +501 -0
  61. package/src/adapters/cursor-ide/transcripts.ts +122 -0
  62. package/src/adapters/cursor-ide/workspaces.ts +119 -0
  63. package/src/adapters/cursor-ide/writer.ts +170 -0
  64. package/src/adapters/devin/index.ts +8 -0
  65. package/src/adapters/devin/reader.ts +305 -0
  66. package/src/adapters/devin/records.ts +277 -0
  67. package/src/adapters/devin/writer.ts +523 -0
  68. package/src/adapters/factory-droid/index.ts +12 -0
  69. package/src/adapters/factory-droid/reader.ts +184 -0
  70. package/src/adapters/factory-droid/records.ts +79 -0
  71. package/src/adapters/factory-droid/writer.ts +350 -0
  72. package/src/adapters/gemini-cli/exchanges.ts +228 -0
  73. package/src/adapters/gemini-cli/index.ts +396 -0
  74. package/src/adapters/gemini-cli/records.ts +521 -0
  75. package/src/adapters/gemini-cli/writer.ts +354 -0
  76. package/src/adapters/goose/index.ts +8 -0
  77. package/src/adapters/goose/reader.ts +138 -0
  78. package/src/adapters/goose/records.ts +199 -0
  79. package/src/adapters/goose/writer.ts +340 -0
  80. package/src/adapters/grok-cli/image.ts +44 -0
  81. package/src/adapters/grok-cli/index.ts +8 -0
  82. package/src/adapters/grok-cli/reader.ts +302 -0
  83. package/src/adapters/grok-cli/records.ts +172 -0
  84. package/src/adapters/grok-cli/writer.ts +329 -0
  85. package/src/adapters/hermes/index.ts +8 -0
  86. package/src/adapters/hermes/reader.ts +249 -0
  87. package/src/adapters/hermes/records.ts +285 -0
  88. package/src/adapters/hermes/writer.ts +452 -0
  89. package/src/adapters/iflow-cli/index.ts +72 -0
  90. package/src/adapters/iflow-cli/records.ts +215 -0
  91. package/src/adapters/iflow-cli/writer.ts +204 -0
  92. package/src/adapters/index.ts +112 -0
  93. package/src/adapters/kilo-cli/index.ts +21 -0
  94. package/src/adapters/kilo-code/index.ts +11 -0
  95. package/src/adapters/kilo-code/writer.ts +92 -0
  96. package/src/adapters/kimi/index.ts +9 -0
  97. package/src/adapters/kimi/reader.ts +92 -0
  98. package/src/adapters/kimi/records.ts +221 -0
  99. package/src/adapters/kimi/writer.ts +367 -0
  100. package/src/adapters/kiro-cli/index.ts +8 -0
  101. package/src/adapters/kiro-cli/reader.ts +87 -0
  102. package/src/adapters/kiro-cli/records.ts +260 -0
  103. package/src/adapters/kiro-cli/writer.ts +305 -0
  104. package/src/adapters/kiro-ide/index.ts +8 -0
  105. package/src/adapters/kiro-ide/writer.ts +52 -0
  106. package/src/adapters/letta/index.ts +8 -0
  107. package/src/adapters/letta/reader.ts +177 -0
  108. package/src/adapters/letta/records.ts +119 -0
  109. package/src/adapters/letta/writer.ts +413 -0
  110. package/src/adapters/mastracode/index.ts +8 -0
  111. package/src/adapters/mastracode/reader.ts +323 -0
  112. package/src/adapters/mastracode/records.ts +336 -0
  113. package/src/adapters/mastracode/writer.ts +385 -0
  114. package/src/adapters/mistral-vibe/index.ts +9 -0
  115. package/src/adapters/mistral-vibe/reader.ts +62 -0
  116. package/src/adapters/mistral-vibe/records.ts +104 -0
  117. package/src/adapters/mistral-vibe/writer.ts +359 -0
  118. package/src/adapters/muse/index.ts +10 -0
  119. package/src/adapters/muse/reader.ts +332 -0
  120. package/src/adapters/muse/records.ts +104 -0
  121. package/src/adapters/muse/writer.ts +387 -0
  122. package/src/adapters/omp/index.ts +13 -0
  123. package/src/adapters/omp/reader.ts +314 -0
  124. package/src/adapters/omp/records.ts +153 -0
  125. package/src/adapters/omp/writer.ts +216 -0
  126. package/src/adapters/opencode/ids.ts +52 -0
  127. package/src/adapters/opencode/index.ts +31 -0
  128. package/src/adapters/opencode/note.ts +8 -0
  129. package/src/adapters/opencode/reader.ts +452 -0
  130. package/src/adapters/opencode/tools.ts +174 -0
  131. package/src/adapters/opencode/v2.ts +367 -0
  132. package/src/adapters/opencode/writer.ts +379 -0
  133. package/src/adapters/openhands/index.ts +8 -0
  134. package/src/adapters/openhands/reader.ts +222 -0
  135. package/src/adapters/openhands/records.ts +136 -0
  136. package/src/adapters/openhands/writer.ts +404 -0
  137. package/src/adapters/pearai/index.ts +10 -0
  138. package/src/adapters/pi/index.ts +28 -0
  139. package/src/adapters/pi/reader.ts +261 -0
  140. package/src/adapters/pi/records.ts +99 -0
  141. package/src/adapters/pi/writer.ts +362 -0
  142. package/src/adapters/qoder-cli/index.ts +8 -0
  143. package/src/adapters/qoder-cli/reader.ts +83 -0
  144. package/src/adapters/qoder-cli/records.ts +45 -0
  145. package/src/adapters/qoder-cli/writer.ts +72 -0
  146. package/src/adapters/qwen-code/index.ts +84 -0
  147. package/src/adapters/qwen-code/records.ts +194 -0
  148. package/src/adapters/qwen-code/writer.ts +224 -0
  149. package/src/adapters/tabnine-cli/index.ts +8 -0
  150. package/src/adapters/tabnine-cli/reader.ts +106 -0
  151. package/src/adapters/tabnine-cli/records.ts +33 -0
  152. package/src/adapters/tabnine-cli/writer.ts +156 -0
  153. package/src/adapters/types.ts +73 -0
  154. package/src/adapters/void/index.ts +9 -0
  155. package/src/adapters/void/reader.ts +48 -0
  156. package/src/adapters/void/records.ts +285 -0
  157. package/src/adapters/void/writer.ts +93 -0
  158. package/src/adapters/vscode-copilot/index.ts +9 -0
  159. package/src/adapters/vscode-copilot/reader.ts +212 -0
  160. package/src/adapters/vscode-copilot/records.ts +388 -0
  161. package/src/adapters/vscode-copilot/shared.ts +68 -0
  162. package/src/adapters/vscode-copilot/writer.ts +546 -0
  163. package/src/adapters/zed/index.ts +8 -0
  164. package/src/adapters/zed/reader.ts +198 -0
  165. package/src/adapters/zed/records.ts +87 -0
  166. package/src/adapters/zed/writer.ts +341 -0
  167. package/src/brief-writers.ts +71 -0
  168. package/src/brief.ts +238 -0
  169. package/src/cli.ts +351 -0
  170. package/src/dashboard/cli.ts +148 -0
  171. package/src/dashboard/conversions.ts +170 -0
  172. package/src/dashboard/report.ts +261 -0
  173. package/src/dashboard/send.ts +213 -0
  174. package/src/dashboard/state.ts +95 -0
  175. package/src/fsutil.ts +133 -0
  176. package/src/gateway/common.ts +232 -0
  177. package/src/gateway/connect.ts +847 -0
  178. package/src/gateway/connectors/aider.ts +356 -0
  179. package/src/gateway/connectors/amazon-q-cli.ts +6 -0
  180. package/src/gateway/connectors/amazon-q-ide.ts +6 -0
  181. package/src/gateway/connectors/antigravity.ts +6 -0
  182. package/src/gateway/connectors/auggie.ts +6 -0
  183. package/src/gateway/connectors/cline-sdk.ts +85 -0
  184. package/src/gateway/connectors/cline.ts +34 -0
  185. package/src/gateway/connectors/codebuff.ts +6 -0
  186. package/src/gateway/connectors/continue.ts +579 -0
  187. package/src/gateway/connectors/copilot-cli.ts +138 -0
  188. package/src/gateway/connectors/crush.ts +313 -0
  189. package/src/gateway/connectors/cursor-cli.ts +6 -0
  190. package/src/gateway/connectors/cursor.ts +6 -0
  191. package/src/gateway/connectors/devin.ts +6 -0
  192. package/src/gateway/connectors/factory-droid.ts +308 -0
  193. package/src/gateway/connectors/goose.ts +79 -0
  194. package/src/gateway/connectors/grok-cli.ts +82 -0
  195. package/src/gateway/connectors/hermes.ts +230 -0
  196. package/src/gateway/connectors/iflow-cli.ts +50 -0
  197. package/src/gateway/connectors/index.ts +86 -0
  198. package/src/gateway/connectors/kilo-cli.ts +434 -0
  199. package/src/gateway/connectors/kilo-code.ts +32 -0
  200. package/src/gateway/connectors/kimi-code.ts +241 -0
  201. package/src/gateway/connectors/kiro-cli.ts +6 -0
  202. package/src/gateway/connectors/kiro-ide.ts +6 -0
  203. package/src/gateway/connectors/letta-code.ts +170 -0
  204. package/src/gateway/connectors/mastracode.ts +91 -0
  205. package/src/gateway/connectors/mistral-vibe.ts +495 -0
  206. package/src/gateway/connectors/muse.ts +27 -0
  207. package/src/gateway/connectors/omp.ts +279 -0
  208. package/src/gateway/connectors/openhands.ts +296 -0
  209. package/src/gateway/connectors/pearai.ts +52 -0
  210. package/src/gateway/connectors/pi.ts +357 -0
  211. package/src/gateway/connectors/qoder-cli.ts +6 -0
  212. package/src/gateway/connectors/qwen-code.ts +411 -0
  213. package/src/gateway/connectors/roo.ts +43 -0
  214. package/src/gateway/connectors/tabnine-cli.ts +6 -0
  215. package/src/gateway/connectors/void.ts +6 -0
  216. package/src/gateway/connectors/vscode-copilot.ts +286 -0
  217. package/src/gateway/connectors/windsurf.ts +6 -0
  218. package/src/gateway/connectors/zed.ts +29 -0
  219. package/src/gateway/signin.ts +323 -0
  220. package/src/handoff.ts +104 -0
  221. package/src/hooks.ts +455 -0
  222. package/src/memory/audit.ts +514 -0
  223. package/src/memory/blobs.ts +94 -0
  224. package/src/memory/cli.ts +117 -0
  225. package/src/memory/distill.ts +381 -0
  226. package/src/memory/externalize.ts +435 -0
  227. package/src/memory/lookups.ts +70 -0
  228. package/src/memory/mcp-install.ts +401 -0
  229. package/src/memory/mcp-server.ts +296 -0
  230. package/src/memory/prepare.ts +179 -0
  231. package/src/memory/preview.ts +154 -0
  232. package/src/memory/project.ts +35 -0
  233. package/src/memory/redact.ts +72 -0
  234. package/src/memory/relevance.ts +187 -0
  235. package/src/memory/repomap.ts +516 -0
  236. package/src/memory/store.ts +270 -0
  237. package/src/memory/sync.ts +166 -0
  238. package/src/memory/tidy.ts +193 -0
  239. package/src/memory/types.ts +118 -0
  240. package/src/org/admin-ops.ts +96 -0
  241. package/src/org/auth.ts +112 -0
  242. package/src/org/backup.ts +115 -0
  243. package/src/org/cli.ts +438 -0
  244. package/src/org/client.ts +404 -0
  245. package/src/org/config.ts +44 -0
  246. package/src/org/crypto.ts +537 -0
  247. package/src/org/db.ts +435 -0
  248. package/src/org/graph.ts +318 -0
  249. package/src/org/oidc.ts +435 -0
  250. package/src/org/policy.ts +398 -0
  251. package/src/org/server.ts +920 -0
  252. package/src/org/sso.ts +316 -0
  253. package/src/org/tls.ts +66 -0
  254. package/src/org/types.ts +193 -0
  255. package/src/self.ts +68 -0
  256. package/src/session/attachments.ts +53 -0
  257. package/src/session/peekcache.ts +50 -0
  258. package/src/session/types.ts +104 -0
  259. package/src/session/util.ts +130 -0
  260. package/src/sqlite.ts +48 -0
package/LICENSE ADDED
@@ -0,0 +1,48 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nipurn Agarwal
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ Parts of src/adapters/{antigravity,devin,grok-cli,hermes,kilo-cli,mastracode,muse,omp} are ported from session-migrate
26
+ (https://github.com/xhluca/session-migrate), used under its MIT license:
27
+
28
+ MIT License
29
+
30
+ Copyright (c) 2026 xhluca
31
+
32
+ Permission is hereby granted, free of charge, to any person obtaining a copy
33
+ of this software and associated documentation files (the "Software"), to deal
34
+ in the Software without restriction, including without limitation the rights
35
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
36
+ copies of the Software, and to permit persons to whom the Software is
37
+ furnished to do so, subject to the following conditions:
38
+
39
+ The above copyright notice and this permission notice shall be included in all
40
+ copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
45
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
47
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
48
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,236 @@
1
- # Temporary Holding Version
1
+ # brain
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ One working session, any AI coding tool. Start in Claude Code, carry on in Codex, Cursor or another tool, and switch
4
+ back, with the same session. brain also keeps what each project has learned across tools, trims what a long session
5
+ sends back to the model, and can route your tools through the 100xprompt gateway.
6
+
7
+ Nothing calls a model to do any of this, and nothing changes in your tools until you run a command that says so.
8
+
9
+ Runs on [Bun](https://bun.sh) 1.3 or later. Built and tested on macOS.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ bun add -g @100xprompt/brain
15
+ brain --version
16
+ ```
17
+
18
+ Or run it without installing:
19
+
20
+ ```bash
21
+ bunx @100xprompt/brain session list --here
22
+ ```
23
+
24
+ Hooks and MCP entries installed from a `bunx` run start that same version later, so they keep working after Bun's
25
+ temporary copy is gone. No Bun yet? `curl -fsSL https://bun.sh/install | bash`.
26
+
27
+ ## Quick start
28
+
29
+ ```bash
30
+ brain session list --here # sessions from every tool, for this project, newest first
31
+ brain session continue <id> --in codex --dry-run # what would be written, and what would not carry over
32
+ brain session continue <id> --in codex # a new Codex session that picks up where that one stopped
33
+ brain session handoff --in claude-code # the newest session from another tool in this folder
34
+ ```
35
+
36
+ `<id>` is `<tool>:<session id>` as `list` prints it, or a unique start of the session id.
37
+
38
+ ## Moving a session
39
+
40
+ `continue` writes the session into the target the best way that target allows:
41
+
42
+ - **Native** (a new session in the tool's own storage, opened like any other): Claude Code, Codex, Gemini CLI, Copilot
43
+ Chat in VS Code, the Copilot CLI, Cline (in VS Code, Cursor, Windsurf, and its CLI), Roo Code (in VS Code, Cursor,
44
+ Windsurf), Antigravity, Aider, Amazon Q (CLI and IDE), Auggie, Codebuff, Continue, Crush, Devin CLI, Factory Droid,
45
+ Grok CLI, Hermes Agent, iFlow CLI, Kimi Code, Kiro (CLI and IDE), Letta Code, Mastra Code, Muse Code, Oh My Pi,
46
+ OpenHands CLI, PearAI, Pi, Qoder CLI, Qwen Code, Tabnine CLI, Void and Zed.
47
+ - **Import** (through the tool's own import): 100xprompt, OpenCode, Cursor, Goose, Kilo Code, Kilo CLI and Mistral Vibe.
48
+ - **Brief**: the Cursor CLI, and any other tool (`--in any`: a Markdown file to paste).
49
+
50
+ A native or import writer writes only for the tool versions its format was checked against, and some need the app
51
+ closed (VS Code); otherwise, and whenever the tool is missing, the session goes as a brief. `brain session targets`
52
+ shows what each tool on this machine gets right now, and `brain session list` shows every session brain can read.
53
+
54
+ A **brief** is built without a model call: where the session came from, the goal, where it stands, files changed, the
55
+ last commands, the latest requests, and as many recent turns as fit the target. It is saved as a pending handoff, copied
56
+ to the clipboard where the system has one, and, where the session-start hook is installed (`brain session hooks
57
+ install`, for Claude Code, Codex, Cursor and Gemini CLI), given to the model by the target's next session in the same
58
+ project.
59
+
60
+ ## Saving tokens
61
+
62
+ On real sessions, tool calls and their output are about four fifths of the tokens; what was said is about a tenth.
63
+
64
+ - **Lean sessions.** A big tool call or result becomes a one-line digest with a short preview, and the full text stays on
65
+ disk (`~/.brain/blobs/`). `continue` does this by itself on long sessions (`--lean` / `--full` override; `--budget
66
+ <tokens>` trims in steps until the session fits). The model gets the text back only when it asks, through the
67
+ `brain_expand` tool (or `brain expand <id>`).
68
+ - **Project memory.** What a session settled (decisions, constraints, preferences, files, failed approaches, commands) is
69
+ distilled into small items kept per project, so a session in any tool can recall them with `brain_recall`. Memory needs
70
+ [Chitta](https://www.npmjs.com/package/@100xprompt/chitta) (`bun add -g @100xprompt/chitta`, found next to brain, in a
71
+ global install, or at `$BRAIN_CHITTA`); without it everything else works, except a Teams server.
72
+ - **What every request reloads.** `brain tokens audit` checks, without changing anything, what a project sends with every
73
+ request: instruction files, MCP servers, ignore files.
74
+
75
+ ```bash
76
+ brain mcp install # brain_recall and brain_expand in Claude Code, Codex, Cursor, Gemini CLI, OpenCode, VS Code
77
+ brain memory sync --here # distill this project's earlier sessions (a few per run; nothing is processed twice)
78
+ brain memory search "how do we run the tests"
79
+ brain tokens audit
80
+ ```
81
+
82
+ ## The 100xprompt gateway
83
+
84
+ Point a coding tool at the 100xprompt gateway, and back. Signing in works like `100xprompt auth login`: your browser opens,
85
+ you sign in to 100xprompt and confirm, and the key comes back to brain by itself.
86
+
87
+ ```bash
88
+ brain gateway login # sign in in the browser
89
+ brain gateway connect --tool codex --dry-run # show what would change
90
+ brain gateway connect --tool codex # any tool in the table below (signs in first if needed)
91
+ brain gateway status
92
+ brain gateway disconnect --tool codex # put back exactly what was there
93
+ brain gateway logout
94
+ ```
95
+
96
+ - Connecting changes which model the tool uses: it runs on 100xprompt Pro by default (`--model flash` for 100xprompt
97
+ Flash), billed to your 100xprompt account. Context editing is on by default; `--no-context-edit` turns it off and is
98
+ remembered for later connects until `--context-edit`.
99
+ - Before changing anything, `connect` checks that the gateway accepts your key the way that tool sends it (a free check
100
+ that generates nothing). If your account's quota is used up, it still connects and tells you, in the gateway's words.
101
+ - Only the settings brain owns are written; the value each had before is recorded and put back by `disconnect`. The key
102
+ lives in `~/.brain/gateway.key`, readable only by you, and is never printed.
103
+ - On a machine without a browser (SSH): `brain gateway login --no-browser` prints the address. Open it anywhere, then
104
+ paste the key from the page's Copy key button (input is hidden). For scripts and CI: `--key-env VAR`. To reuse the
105
+ 100xprompt CLI's sign-in: `--from-cli`.
106
+ - Each sign-in makes a new key on your account. Signing in again also updates every copy of the key that a connected tool
107
+ keeps in its own config.
108
+
109
+ | Tool (`--tool`) | How it gets the key | Context editing | Checked with the real tool |
110
+ |---|---|---|---|
111
+ | Claude Code (`claude-code`) | reads brain's key file at start | yes | yes |
112
+ | Codex (`codex`) | copy in its config, made private | yes | yes |
113
+ | OpenCode (`opencode`) | reads brain's key file | yes | yes |
114
+ | Gemini CLI (`gemini-cli`) | copy in `~/.gemini/.env`, private | no | yes (needs the gateway update that accepts `x-goog-api-key`) |
115
+ | Aider (`aider`) | copy in its model settings, private | yes | yes |
116
+ | Cline CLI (`cline-sdk`) | copy in its providers file, private | yes | yes |
117
+ | Continue (`continue`) | copy in `~/.continue/.env`, private | yes | yes (`cn`) |
118
+ | Copilot CLI (`copilot-cli`) | copy in its providers file, private | yes | yes |
119
+ | Copilot Chat in VS Code (`vscode-copilot`) | copy in VS Code's model list, private | yes | from the extension's code; pick "100xprompt Pro" once in the model picker |
120
+ | Crush (`crush`) | reads brain's key file | yes | yes |
121
+ | Factory Droid (`factory-droid`) | reads brain's key file | yes | yes |
122
+ | Goose (`goose`) | reads brain's key file | yes | yes |
123
+ | Grok CLI (`grok-cli`) | copy in its config, private | yes | yes |
124
+ | Hermes Agent (`hermes`) | copy in `~/.hermes/.env`, private | yes | yes |
125
+ | iFlow CLI (`iflow-cli`) | copy in its settings, private | no | yes |
126
+ | Kilo CLI and Kilo Code (`kilo-cli`, `kilo-code`) | reads brain's key file | yes | yes |
127
+ | Kimi Code (`kimi-code`) | copy in its config, private | yes | yes |
128
+ | Letta Code (`letta-code`) | reads brain's key file (a provider mod; local agents only) | yes | from its source |
129
+ | Mastra Code (`mastracode`) | copy in its settings, private | no | from its source |
130
+ | Mistral Vibe (`mistral-vibe`) | copy in `~/.vibe/.env`, private | yes | yes |
131
+ | Oh My Pi (`omp`) | reads brain's key file | yes | from its source |
132
+ | OpenHands (`openhands`) | copy in its settings, private | yes | yes |
133
+ | PearAI (`pearai`) | copy in `~/.pearai/.env`, private | yes | from its source |
134
+ | Pi (`pi`) | reads brain's key file | yes | yes |
135
+ | Qwen Code (`qwen-code`) | copy in `~/.qwen/.env`, private | yes | yes |
136
+
137
+ "Checked with the real tool" means the real program, pointed at a local stand-in gateway, sent its request to the gateway's
138
+ route with the key and the gateway's model, and `disconnect` gave every file back byte for byte (its original mode too).
139
+
140
+ Some tools cannot be pointed at the gateway from a file brain can safely write and cleanly undo, so they have no connector:
141
+ Cursor and the Cursor CLI, Windsurf, Antigravity, Amazon Q, Kiro, Auggie, Tabnine, Devin and Muse Code (their vendor's own
142
+ servers only); Zed (the key only in the keychain or its launch environment); Void (settings encrypted in the app's state);
143
+ Roo Code and the Cline extension (they keep the key in the editor's own storage, so disconnect could not take it back);
144
+ Codebuff and Qoder (custom endpoints only through their own sign-in or the keychain). The reason and its source are in each
145
+ tool's file under `src/gateway/connectors/`.
146
+
147
+ Gemini CLI loads only the first `.env` it finds from the project folder up: in a project with its own `.env`, put the
148
+ gateway lines there or export them. Letta Code uses the gateway for its local agents only (cloud agents call models from
149
+ Letta's servers). Tools that read brain's key file stop working after `logout` until the next `login`; Kilo refuses to start
150
+ without it.
151
+
152
+ ## Dashboard
153
+
154
+ Signed in to the gateway, brain sends a short report of this machine to your 100xprompt account, shown in the console's
155
+ Brain view (https://100xprompt.com/dashboard?view=brain): the coding tools found here, their session counts, which are
156
+ connected to the gateway or have brain's MCP tools and hooks, your gateway settings, memory counts, and every chat brain
157
+ moved from one tool into another (when, from and to which tool, the way, its title and its project folder's name). Never
158
+ chat text, file contents, full paths or keys.
159
+
160
+ ```bash
161
+ brain dashboard # count sessions, send the report now, open the Brain view (--no-open prints the address)
162
+ brain dashboard status # on or off, and when the last report went out
163
+ brain dashboard off # send nothing from this machine (brain dashboard on to start again)
164
+ ```
165
+
166
+ The report goes out in the background, at most every 30 seconds, after a command that changes it (`gateway login`,
167
+ `connect`, `disconnect`, `session continue`, `handoff`, `mcp install`/`uninstall`, `session hooks install`/`uninstall`),
168
+ and never makes that command wait or fail. The first time, brain prints what it sends and how to stop it.
169
+ `BRAIN_NO_REPORT=1` also turns it off. The conversion log is `~/.brain/logs/conversions.jsonl`, readable only by you.
170
+
171
+ ## Teams
172
+
173
+ Memory can live on one shared server instead of each person's machine, with who may see what enforced there.
174
+
175
+ ```bash
176
+ # on the server (it needs Chitta: bun add -g @100xprompt/chitta)
177
+ brain org admin init --db org.db --org-id acme --org-name Acme --admin-id ana --admin-name Ana # once; prints the admin token
178
+ brain org admin serve --db org.db --host 0.0.0.0 --allow-remote --tls-cert cert.pem --tls-key key.pem
179
+
180
+ # on each person's machine
181
+ brain org login --server https://<server>:4500 --token <token>
182
+ brain org promote --source <session> --to team --team backend
183
+ ```
184
+
185
+ Every item has a scope: `private` (the default; only its owner, not even an admin), `project`, `team` or `org`. Sharing
186
+ is an explicit, logged act. Roles are `viewer`, `editor` and `admin`; admins set policy (widest scope, paths and terms that
187
+ are never shared, retention) and read the audit log. Only distilled, secret-filtered memory items cross the wire: never
188
+ full tool output, raw turns or attachments. With no login, brain stays entirely local.
189
+
190
+ `admin serve` listens on 127.0.0.1 unless told otherwise: to reach it from other machines, use `--allow-remote` with TLS
191
+ (`--tls-cert`/`--tls-key`), or keep it local behind a TLS proxy (`--trust-proxy`). An encrypted database (`init
192
+ --encrypt`) also needs `libsql` installed next to Chitta. `brain org help` lists every option.
193
+
194
+ ## Safety
195
+
196
+ - Reading a session never changes a tool's files: SQLite stores are copied (with their write-ahead logs) and the copy is
197
+ read. To see which version is installed, `targets` and `--dry-run` start each installed tool with `--version`.
198
+ - Continuing always writes a **new** session; the source is never changed, so switching back is continuing the original.
199
+ - Writers check the installed tool version against the one their format was verified on, and fall back to the brief otherwise.
200
+ - `--dry-run` shows what would be written. Hooks, MCP entries and gateway settings are merged with your own, backed up
201
+ first, and removed exactly by the matching `uninstall` or `disconnect`.
202
+
203
+ ## Commands
204
+
205
+ ```
206
+ brain session list | show | export | continue | handoff | targets | hooks
207
+ brain memory ingest | search | status | forget | sync
208
+ brain mcp serve | install | uninstall | status
209
+ brain tokens audit | lookups
210
+ brain gateway login | logout | connect | disconnect | status | tools
211
+ brain dashboard [push | on | off | status]
212
+ brain org login | logout | whoami | status | promote | demote | forget | admin ...
213
+ brain expand <id>
214
+ brain --version
215
+ ```
216
+
217
+ `brain --help` lists every command with its main options; `brain gateway`, `brain mcp` and `brain org help` show the rest
218
+ of theirs.
219
+
220
+ ## Known limits
221
+
222
+ - Built and tested on macOS. Linux and Windows are not tested yet.
223
+ - Each writer is checked against specific versions, for example Claude Code 2.1.296 to 2.1.319 (a newer 2.1.x is
224
+ accepted with a note), Codex 0.147.0, Gemini CLI 0.33.1 and 0.67.0, Cursor 3.27 and 3.29, VS Code 1.144 with Copilot
225
+ Chat 0.72, OpenCode 2.2.6, Zed 1.26.2 and 1.27.0, Aider 0.86.2. A tool at another version gets the brief instead.
226
+ - Into Codex: tool names from Claude Code (`Read`, `Grep`, `Agent`, MCP calls) stay as they are, and subagent transcripts
227
+ are not carried. Pasted images are.
228
+ - Into Claude Code: reasoning and subagent transcripts are not written.
229
+ - Cursor is reached through its own import of Claude Code sessions (for the folder it has open), not by writing to
230
+ Cursor's database; the brief opens in Cursor's chat when that is not possible.
231
+ - Session-start hooks were checked against each tool's installed code, not yet inside every live tool. Codex asks you to
232
+ trust a new hook once.
233
+
234
+ ## License
235
+
236
+ MIT
package/package.json CHANGED
@@ -1,6 +1,50 @@
1
1
  {
2
2
  "name": "@100xprompt/brain",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.1",
4
+ "description": "One working session, any AI coding tool: move sessions between Claude Code, Codex, Cursor, Gemini CLI, OpenCode and more, keep what projects learned, spend fewer tokens. Runs on Bun. By 100xprompt.",
5
+ "license": "MIT",
6
+ "author": "Nipurn Agarwal",
7
+ "homepage": "https://www.npmjs.com/package/@100xprompt/brain",
8
+ "keywords": [
9
+ "ai-coding",
10
+ "coding-agent",
11
+ "claude-code",
12
+ "codex",
13
+ "cursor",
14
+ "gemini-cli",
15
+ "opencode",
16
+ "session",
17
+ "handoff",
18
+ "context",
19
+ "memory",
20
+ "mcp",
21
+ "tokens",
22
+ "100xprompt"
23
+ ],
24
+ "type": "module",
25
+ "engines": {
26
+ "bun": ">=1.3.0"
27
+ },
28
+ "bin": {
29
+ "brain": "./src/cli.ts"
30
+ },
31
+ "files": [
32
+ "src",
33
+ "README.md",
34
+ "LICENSE"
35
+ ],
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "scripts": {
40
+ "brain": "bun run src/cli.ts",
41
+ "test": "bun test --timeout 60000",
42
+ "typecheck": "tsc --noEmit -p .",
43
+ "wire": "bun wire/run.ts"
44
+ },
45
+ "devDependencies": {
46
+ "@types/bun": "^1.4.4",
47
+ "oidc-provider": "9.13.3",
48
+ "typescript": "5.8.2"
49
+ }
50
+ }
@@ -0,0 +1,8 @@
1
+ import type { Reader, Writer } from "../types.ts"
2
+ import { aiderReader } from "./reader.ts"
3
+ import { aiderNativeWriter } from "./writer.ts"
4
+
5
+ // Aider: reads each run of a project's .aider.chat.history.md as a session, and continues any session as a
6
+ // new run in that history, which `aider --restore-chat-history` hands to the model.
7
+ export const readers: Reader[] = [aiderReader]
8
+ export const writers: Writer[] = [aiderNativeWriter]
@@ -0,0 +1,129 @@
1
+ import { createHash } from "node:crypto"
2
+ import { readFileSync, statSync } from "node:fs"
3
+ import { dirname } from "node:path"
4
+ import type { Session, Turn } from "../../session/types.ts"
5
+ import { header, lossCounter, noteModel } from "../../session/util.ts"
6
+ import type { Reader, SessionRef } from "../types.ts"
7
+ import { CONTINUED_NOTE, LABEL, SUMMARY_PREFIX, TOOL, type Run, assistantText, findHistories, parseRuns, userText } from "./records.ts"
8
+
9
+ // Aider sessions. Aider has no session list or ids: every project keeps one history file and each launch
10
+ // appends a run to it, so a run ("# aider chat started at ...") is read as one session. That is also what
11
+ // a launch without --restore-chat-history sees: a fresh chat. Ids are made from the file and the run's start.
12
+
13
+ /** "2026-11-08 10:00:00" (local time, as Aider writes it) → ISO. */
14
+ const runTime = (stamp: string | undefined) => {
15
+ if (!stamp) return undefined
16
+ const t = new Date(stamp.replace(" ", "T"))
17
+ return Number.isFinite(t.getTime()) ? t.toISOString() : undefined
18
+ }
19
+
20
+ const fileKey = (path: string) => createHash("sha1").update(path).digest("hex").slice(0, 8)
21
+
22
+ /** The id of a run: the file's key and the run's start (YYYYMMDDhhmmss), with its index when two share a second. */
23
+ export function runId(path: string, run: Run, runs: Run[]): string {
24
+ const stamp = (run.startedAt ?? "00000000000000").replace(/\D/g, "")
25
+ const twin = runs.filter((r) => r.startedAt === run.startedAt).length > 1
26
+ return `${fileKey(path)}-${stamp}${twin || !run.startedAt ? `-${run.index}` : ""}`
27
+ }
28
+
29
+ /** Runs that hold conversation, not only Aider's startup notices. */
30
+ const talked = (run: Run) => run.messages.some((m) => m.role !== "tool")
31
+
32
+ function readText(path: string): string {
33
+ try {
34
+ return readFileSync(path, "utf8")
35
+ } catch (e) {
36
+ throw new Error(`cannot read the Aider history ${path}: ${(e as Error).message}`)
37
+ }
38
+ }
39
+
40
+ /** One run as a portable session. */
41
+ export function runSession(path: string, run: Run, runs: Run[], updatedAt?: string): Session {
42
+ const id = runId(path, run, runs)
43
+ const h = header(TOOL, id, { sourcePath: path, project: { cwd: dirname(path) }, startedAt: runTime(run.startedAt), updatedAt })
44
+ const lost = lossCounter()
45
+ const turns: Turn[] = []
46
+ for (const [i, m] of run.messages.entries()) {
47
+ if (m.role === "tool") {
48
+ // Aider's own notices: never sent to the model. Kept: the model it ran, its version, and the files it edited.
49
+ for (const line of m.content.split("\n")) {
50
+ const model = line.match(/^(?:Main model|Model): (\S+)/)?.[1]
51
+ if (model) noteModel(h, model)
52
+ const version = line.match(/^Aider v(\d+\.\d+\.\d+\S*)/)?.[1]
53
+ if (version) h.toolVersion ??= version
54
+ const edited = line.match(/^Applied edit to (.+?)\s*$/)?.[1]
55
+ if (edited) turns.push({ kind: "file_edit", path: edited })
56
+ }
57
+ continue
58
+ }
59
+ if (m.role === "user") {
60
+ const text = userText(m.content)
61
+ if (!text) continue
62
+ const note = i === run.messages.findIndex((x) => x.role === "user") ? text.match(CONTINUED_NOTE) : null
63
+ if (note) {
64
+ h.parent = { id: note[1]!.replace(/[.,]$/, ""), kind: "continued" }
65
+ continue
66
+ }
67
+ if (text.startsWith(SUMMARY_PREFIX.trim())) {
68
+ turns.push({ kind: "compaction", summary: text.slice(SUMMARY_PREFIX.trim().length).trim() })
69
+ continue
70
+ }
71
+ turns.push({ kind: "user", text })
72
+ continue
73
+ }
74
+ const text = assistantText(m.content)
75
+ if (text) turns.push({ kind: "assistant", text, ...(h.models.length ? { model: h.models[h.models.length - 1] } : {}) })
76
+ }
77
+ if (!turns.some((t) => t.kind === "user" || t.kind === "assistant")) lost.add("runs with only Aider's own notices")
78
+ lost.flush(h)
79
+ const first = turns.find((t) => t.kind === "user") as Extract<Turn, { kind: "user" }> | undefined
80
+ if (first) h.title = first.text.replace(/\s+/g, " ").trim().slice(0, 80)
81
+ return { header: h, turns }
82
+ }
83
+
84
+ export const aiderReader: Reader = {
85
+ tool: TOOL,
86
+ label: LABEL,
87
+
88
+ async list(home: string): Promise<SessionRef[]> {
89
+ const refs: SessionRef[] = []
90
+ for (const path of findHistories(home)) {
91
+ let text: string
92
+ let mtime: string | undefined
93
+ try {
94
+ text = readFileSync(path, "utf8")
95
+ mtime = statSync(path).mtime.toISOString()
96
+ } catch {
97
+ continue
98
+ }
99
+ const runs = parseRuns(text)
100
+ runs.forEach((run, i) => {
101
+ if (!talked(run)) return
102
+ const next = runs.slice(i + 1).find((r) => r.startedAt)
103
+ const first = run.messages.find((m) => m.role === "user" && !CONTINUED_NOTE.test(userText(m.content)))
104
+ refs.push({
105
+ tool: TOOL,
106
+ sourceId: runId(path, run, runs),
107
+ path,
108
+ cwd: dirname(path),
109
+ updatedAt: (next ? runTime(next.startedAt) : mtime) ?? runTime(run.startedAt),
110
+ ...(first ? { title: userText(first.content).replace(/\s+/g, " ").trim().slice(0, 80) } : {}),
111
+ extra: { run: run.index },
112
+ })
113
+ })
114
+ }
115
+ return refs.sort((a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? ""))
116
+ },
117
+
118
+ async read(ref: SessionRef): Promise<Session> {
119
+ const runs = parseRuns(readText(ref.path))
120
+ const run = runs.find((r) => runId(ref.path, r, runs) === ref.sourceId) ?? runs.find((r) => r.index === ref.extra?.run)
121
+ if (!run) throw new Error(`no run ${ref.sourceId} in the Aider history ${ref.path}`)
122
+ let updatedAt: string | undefined
123
+ try {
124
+ updatedAt = statSync(ref.path).mtime.toISOString()
125
+ } catch {}
126
+ const next = runs.slice(run.index + 1).find((r) => r.startedAt)
127
+ return runSession(ref.path, run, runs, next ? runTime(next.startedAt) : updatedAt)
128
+ },
129
+ }