create-walle 0.9.8 → 0.9.10

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 (533) hide show
  1. package/README.md +1 -1
  2. package/bin/create-walle.js +95 -13
  3. package/bin/mcp-inject.js +60 -0
  4. package/package.json +11 -3
  5. package/template/CLAUDE.md +19 -0
  6. package/template/bin/dev.sh +46 -23
  7. package/template/bin/install-service.sh +50 -16
  8. package/template/bin/setup.js +2 -1
  9. package/template/bin/sqlite-snapshot.js +148 -0
  10. package/template/claude-code-skill.md +35 -34
  11. package/template/claude-task-manager/api-prompts.js +1139 -259
  12. package/template/claude-task-manager/api-reviews.js +12 -0
  13. package/template/claude-task-manager/approval-agent.js +517 -88
  14. package/template/claude-task-manager/atomic-write.js +22 -0
  15. package/template/claude-task-manager/bin/capture-pty.js +92 -0
  16. package/template/claude-task-manager/bin/claude-hook.js +42 -0
  17. package/template/claude-task-manager/bin/codex-notify.js +44 -0
  18. package/template/claude-task-manager/bin/ctm-hotkey.swift +118 -0
  19. package/template/claude-task-manager/bin/extract-fixture.js +142 -0
  20. package/template/claude-task-manager/bin/gemini-hook.js +41 -0
  21. package/template/claude-task-manager/bin/install-hotkey.sh +120 -0
  22. package/template/claude-task-manager/bin/restart-ctm.sh +25 -6
  23. package/template/claude-task-manager/db.js +2146 -108
  24. package/template/claude-task-manager/docs/session-management-architecture.md +554 -0
  25. package/template/claude-task-manager/fuzzy-utils.js +455 -0
  26. package/template/claude-task-manager/git-utils.js +761 -1
  27. package/template/claude-task-manager/lib/agent-capabilities.js +108 -0
  28. package/template/claude-task-manager/lib/agent-cli-cache.js +224 -0
  29. package/template/claude-task-manager/lib/agent-hooks-installer.js +416 -0
  30. package/template/claude-task-manager/lib/agent-presets.js +129 -0
  31. package/template/claude-task-manager/lib/auto-approval-verifier.js +199 -0
  32. package/template/claude-task-manager/lib/coding-agent-models.js +219 -0
  33. package/template/claude-task-manager/lib/compact-stitch.js +140 -0
  34. package/template/claude-task-manager/lib/devcontainer-wrapper.js +93 -0
  35. package/template/claude-task-manager/lib/fs-watcher.js +305 -0
  36. package/template/claude-task-manager/lib/git-status.js +130 -0
  37. package/template/claude-task-manager/lib/hook-executor.js +111 -0
  38. package/template/claude-task-manager/lib/launch-presets.js +103 -0
  39. package/template/claude-task-manager/lib/message-export.js +146 -0
  40. package/template/claude-task-manager/lib/message-pagination.js +47 -0
  41. package/template/claude-task-manager/lib/oauth-proxy-supervisor.js +133 -0
  42. package/template/claude-task-manager/lib/perf-tracker.js +58 -0
  43. package/template/claude-task-manager/lib/permission-sync.js +162 -0
  44. package/template/claude-task-manager/lib/project-config.js +122 -0
  45. package/template/claude-task-manager/lib/relink-audit.js +234 -0
  46. package/template/claude-task-manager/lib/sanitize-anthropic-auth.js +46 -0
  47. package/template/claude-task-manager/lib/scheduler.js +408 -0
  48. package/template/claude-task-manager/lib/server-config.js +73 -0
  49. package/template/claude-task-manager/lib/session-history.js +434 -0
  50. package/template/claude-task-manager/lib/session-jobs.js +582 -0
  51. package/template/claude-task-manager/lib/session-lineage.js +291 -0
  52. package/template/claude-task-manager/lib/session-state-bus.js +143 -0
  53. package/template/claude-task-manager/lib/session-stream.js +1189 -0
  54. package/template/claude-task-manager/lib/session-verify.js +215 -0
  55. package/template/claude-task-manager/lib/status-hooks-config.js +101 -0
  56. package/template/claude-task-manager/lib/status-hooks.js +101 -0
  57. package/template/claude-task-manager/lib/telemetry-receiver.js +403 -0
  58. package/template/claude-task-manager/lib/walle-client.js +176 -0
  59. package/template/claude-task-manager/lib/walle-supervisor.js +343 -0
  60. package/template/claude-task-manager/oauth-proxy.js +236 -0
  61. package/template/claude-task-manager/package.json +12 -2
  62. package/template/claude-task-manager/prompt-harvest.js +515 -48
  63. package/template/claude-task-manager/providers/aider.js +63 -0
  64. package/template/claude-task-manager/providers/amazon-q.js +56 -0
  65. package/template/claude-task-manager/providers/claude-code.js +115 -0
  66. package/template/claude-task-manager/providers/cline.js +52 -0
  67. package/template/claude-task-manager/providers/codex.js +186 -0
  68. package/template/claude-task-manager/providers/copilot.js +51 -0
  69. package/template/claude-task-manager/providers/cursor.js +67 -0
  70. package/template/claude-task-manager/providers/gemini.js +58 -0
  71. package/template/claude-task-manager/providers/index.js +65 -0
  72. package/template/claude-task-manager/providers/kimi.js +57 -0
  73. package/template/claude-task-manager/providers/opencode.js +61 -0
  74. package/template/claude-task-manager/public/css/listening.css +1481 -0
  75. package/template/claude-task-manager/public/css/prompts.css +143 -19
  76. package/template/claude-task-manager/public/css/reviews.css +212 -1
  77. package/template/claude-task-manager/public/css/setup.css +216 -0
  78. package/template/claude-task-manager/public/css/walle-session.css +178 -0
  79. package/template/claude-task-manager/public/css/walle.css +346 -0
  80. package/template/claude-task-manager/public/index.html +9421 -1256
  81. package/template/claude-task-manager/public/js/listening.js +1740 -0
  82. package/template/claude-task-manager/public/js/message-renderer.js +780 -0
  83. package/template/claude-task-manager/public/js/prompts.js +1451 -565
  84. package/template/claude-task-manager/public/js/reviewchat.js +498 -0
  85. package/template/claude-task-manager/public/js/reviews.js +152 -11
  86. package/template/claude-task-manager/public/js/session-activity-utils.js +111 -0
  87. package/template/claude-task-manager/public/js/session-search-utils.js +114 -0
  88. package/template/claude-task-manager/public/js/setup.js +2068 -0
  89. package/template/claude-task-manager/public/js/stream-view.js +1066 -0
  90. package/template/claude-task-manager/public/js/walle-core.js +177 -0
  91. package/template/claude-task-manager/public/js/walle-mcp.js +144 -0
  92. package/template/claude-task-manager/public/js/walle-session.js +447 -72
  93. package/template/claude-task-manager/public/js/walle.js +7141 -3695
  94. package/template/claude-task-manager/public/prompts.html +679 -307
  95. package/template/claude-task-manager/public/setup.html +13 -459
  96. package/template/claude-task-manager/public/sr-diagnostic.html +314 -0
  97. package/template/claude-task-manager/queue-engine.js +14 -0
  98. package/template/claude-task-manager/scripts/audit-relink.js +109 -0
  99. package/template/claude-task-manager/scripts/audit-sessions-db.js +294 -0
  100. package/template/claude-task-manager/scripts/repair-crosslinks.js +221 -0
  101. package/template/claude-task-manager/server-state.js +8 -1
  102. package/template/claude-task-manager/server.js +7521 -1643
  103. package/template/claude-task-manager/session-integrity.js +706 -0
  104. package/template/claude-task-manager/session-utils.js +116 -5
  105. package/template/claude-task-manager/workers/approval-blocklist.js +138 -0
  106. package/template/claude-task-manager/workers/approval-patterns.js +20 -0
  107. package/template/claude-task-manager/workers/approval-widget-validator.js +176 -0
  108. package/template/claude-task-manager/workers/conversation-import-worker.js +35 -0
  109. package/template/claude-task-manager/workers/harvest-worker.js +36 -0
  110. package/template/claude-task-manager/workers/headless-term-worker.js +444 -0
  111. package/template/claude-task-manager/workers/scrollback-worker.js +76 -0
  112. package/template/claude-task-manager/workers/session-integrity-worker.js +40 -0
  113. package/template/claude-task-manager/workers/state-detectors/base.js +54 -0
  114. package/template/claude-task-manager/workers/state-detectors/claude-code.js +39 -0
  115. package/template/claude-task-manager/workers/state-detectors/codex.js +62 -0
  116. package/template/claude-task-manager/workers/state-detectors/gemini.js +36 -0
  117. package/template/claude-task-manager/workers/state-detectors/index.js +46 -0
  118. package/template/claude-task-manager/workers/terminal-counters.js +75 -0
  119. package/template/docs/designs/2026-04-18-dictation-focus-redesign.md +358 -0
  120. package/template/package.json +3 -1
  121. package/template/wall-e/_workspace-templates/AGENTS.md +52 -0
  122. package/template/wall-e/_workspace-templates/BOOT.md +34 -0
  123. package/template/wall-e/_workspace-templates/HEARTBEAT.md +42 -0
  124. package/template/wall-e/_workspace-templates/IDENTITY.md +27 -0
  125. package/template/wall-e/_workspace-templates/SOUL.md +53 -0
  126. package/template/wall-e/_workspace-templates/TOOLS.md +34 -0
  127. package/template/wall-e/_workspace-templates/USER.md +37 -0
  128. package/template/wall-e/adapters/chatgpt.js +120 -0
  129. package/template/wall-e/adapters/chatgpt.plugin.json +17 -0
  130. package/template/wall-e/adapters/claude-web.js +75 -0
  131. package/template/wall-e/adapters/claude-web.plugin.json +17 -0
  132. package/template/wall-e/adapters/ctm.plugin.json +19 -0
  133. package/template/wall-e/adapters/plaintext.js +80 -0
  134. package/template/wall-e/adapters/plaintext.plugin.json +17 -0
  135. package/template/wall-e/adapters/registry.js +229 -0
  136. package/template/wall-e/adapters/slack.plugin.json +19 -0
  137. package/template/wall-e/agent-runners/claude-code.js +86 -0
  138. package/template/wall-e/agent-runners/codex.js +116 -0
  139. package/template/wall-e/agent-runners/contract.js +60 -0
  140. package/template/wall-e/agent-runners/gemini.js +96 -0
  141. package/template/wall-e/agent-runners/index.js +62 -0
  142. package/template/wall-e/agent-runners/multi-agent.js +202 -0
  143. package/template/wall-e/agent-runners/utils.js +165 -0
  144. package/template/wall-e/agent.js +684 -211
  145. package/template/wall-e/api-walle.js +2493 -245
  146. package/template/wall-e/auth/cooldown.js +166 -0
  147. package/template/wall-e/auth/key-rotation.js +231 -0
  148. package/template/wall-e/auth/profiles.js +144 -0
  149. package/template/wall-e/brain.js +2062 -111
  150. package/template/wall-e/channels/channel-retry.js +154 -0
  151. package/template/wall-e/channels/idle-poll-backoff.js +141 -0
  152. package/template/wall-e/channels/imessage-channel.plugin.json +21 -0
  153. package/template/wall-e/channels/registry.js +233 -0
  154. package/template/wall-e/channels/slack-channel.plugin.json +20 -0
  155. package/template/wall-e/channels/telegram-channel.plugin.json +20 -0
  156. package/template/wall-e/chat/attachment-storage.js +123 -0
  157. package/template/wall-e/chat/attachments.js +192 -0
  158. package/template/wall-e/chat/capability-resolver.js +92 -0
  159. package/template/wall-e/chat/code-review-context.js +192 -0
  160. package/template/wall-e/chat-fallback.js +174 -0
  161. package/template/wall-e/chat.js +1181 -118
  162. package/template/wall-e/coding-context.js +142 -6
  163. package/template/wall-e/coding-orchestrator.js +1400 -224
  164. package/template/wall-e/coding-prompts.js +223 -0
  165. package/template/wall-e/coding-review.js +95 -51
  166. package/template/wall-e/compat.js +113 -0
  167. package/template/wall-e/context/compaction-hooks.js +117 -0
  168. package/template/wall-e/context/compactor.js +33 -0
  169. package/template/wall-e/context/context-builder.js +439 -80
  170. package/template/wall-e/context/query-sanitizer.js +81 -0
  171. package/template/wall-e/context/topic-matcher.js +67 -18
  172. package/template/wall-e/core-tasks.js +15 -3
  173. package/template/wall-e/db/write-audit.js +81 -0
  174. package/template/wall-e/dispatch/collapse-policy.js +91 -0
  175. package/template/wall-e/dispatch/source-registry.js +154 -0
  176. package/template/wall-e/docs/architecture.md +460 -0
  177. package/template/wall-e/docs/prompt-architecture.md +121 -0
  178. package/template/wall-e/embeddings.js +840 -0
  179. package/template/wall-e/eval/ab-test.js +203 -0
  180. package/template/wall-e/eval/agent-runner.js +629 -0
  181. package/template/wall-e/eval/agent-scorer.js +461 -0
  182. package/template/wall-e/eval/aggregator.js +414 -0
  183. package/template/wall-e/eval/benchmark-generator.js +93 -0
  184. package/template/wall-e/eval/benchmarks/chat-eval.json +1602 -0
  185. package/template/wall-e/eval/benchmarks/chat.json +82 -0
  186. package/template/wall-e/eval/benchmarks/coding-agent-real.json +1 -0
  187. package/template/wall-e/eval/benchmarks/coding-agent.json +2177 -0
  188. package/template/wall-e/eval/benchmarks/coding.json +122 -0
  189. package/template/wall-e/eval/benchmarks/memory-retrieval.json +82 -0
  190. package/template/wall-e/eval/benchmarks/reasoning.json +82 -0
  191. package/template/wall-e/eval/benchmarks/swebench-lite-30.json +212 -0
  192. package/template/wall-e/eval/benchmarks.js +578 -0
  193. package/template/wall-e/eval/cc-replay.js +718 -0
  194. package/template/wall-e/eval/chat-eval.js +525 -0
  195. package/template/wall-e/eval/check-keys.js +15 -0
  196. package/template/wall-e/eval/check-providers.js +42 -0
  197. package/template/wall-e/eval/coding-agent-real.js +568 -0
  198. package/template/wall-e/eval/context-compactor.js +251 -0
  199. package/template/wall-e/eval/debug-agent003.js +67 -0
  200. package/template/wall-e/eval/diagnostics.js +216 -0
  201. package/template/wall-e/eval/eval-orchestrator.js +430 -0
  202. package/template/wall-e/eval/evaluate.js +202 -0
  203. package/template/wall-e/eval/evaluator.js +373 -0
  204. package/template/wall-e/eval/exporter.js +212 -0
  205. package/template/wall-e/eval/fixtures/express-basic/package.json +9 -0
  206. package/template/wall-e/eval/fixtures/express-basic/server.js +115 -0
  207. package/template/wall-e/eval/fixtures/express-basic/test.js +83 -0
  208. package/template/wall-e/eval/fixtures/express-buggy/package.json +9 -0
  209. package/template/wall-e/eval/fixtures/express-buggy/server.js +113 -0
  210. package/template/wall-e/eval/fixtures/express-buggy/test.js +83 -0
  211. package/template/wall-e/eval/fixtures/express-buggy-items/package.json +9 -0
  212. package/template/wall-e/eval/fixtures/express-buggy-items/server.js +112 -0
  213. package/template/wall-e/eval/fixtures/express-buggy-items/test.js +83 -0
  214. package/template/wall-e/eval/fixtures/express-buggy-search/package.json +9 -0
  215. package/template/wall-e/eval/fixtures/express-buggy-search/server.js +121 -0
  216. package/template/wall-e/eval/fixtures/express-buggy-search/test.js +83 -0
  217. package/template/wall-e/eval/fixtures/express-rename-data/data.js +34 -0
  218. package/template/wall-e/eval/fixtures/express-rename-data/package.json +9 -0
  219. package/template/wall-e/eval/fixtures/express-rename-data/server.js +97 -0
  220. package/template/wall-e/eval/fixtures/express-rename-data/test.js +88 -0
  221. package/template/wall-e/eval/fixtures/express-xss/package.json +12 -0
  222. package/template/wall-e/eval/fixtures/express-xss/server.js +90 -0
  223. package/template/wall-e/eval/fixtures/express-xss/test.js +67 -0
  224. package/template/wall-e/eval/fixtures/express-xss/views/profile.ejs +9 -0
  225. package/template/wall-e/eval/fixtures/fullstack-app/config/default.js +9 -0
  226. package/template/wall-e/eval/fixtures/fullstack-app/config/test.js +13 -0
  227. package/template/wall-e/eval/fixtures/fullstack-app/package.json +11 -0
  228. package/template/wall-e/eval/fixtures/fullstack-app/public/css/style.css +137 -0
  229. package/template/wall-e/eval/fixtures/fullstack-app/public/index.html +46 -0
  230. package/template/wall-e/eval/fixtures/fullstack-app/public/js/app.js +121 -0
  231. package/template/wall-e/eval/fixtures/fullstack-app/public/js/auth.js +71 -0
  232. package/template/wall-e/eval/fixtures/fullstack-app/public/js/items.js +80 -0
  233. package/template/wall-e/eval/fixtures/fullstack-app/public/js/users.js +46 -0
  234. package/template/wall-e/eval/fixtures/fullstack-app/public/login.html +45 -0
  235. package/template/wall-e/eval/fixtures/fullstack-app/public/register.html +38 -0
  236. package/template/wall-e/eval/fixtures/fullstack-app/scripts/migrate.js +23 -0
  237. package/template/wall-e/eval/fixtures/fullstack-app/scripts/seed.js +46 -0
  238. package/template/wall-e/eval/fixtures/fullstack-app/server/db.js +99 -0
  239. package/template/wall-e/eval/fixtures/fullstack-app/server/index.js +94 -0
  240. package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/auth.js +19 -0
  241. package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/logger.js +19 -0
  242. package/template/wall-e/eval/fixtures/fullstack-app/server/router.js +50 -0
  243. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/auth.js +69 -0
  244. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/health.js +23 -0
  245. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/items.js +88 -0
  246. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/users.js +75 -0
  247. package/template/wall-e/eval/fixtures/fullstack-app/server/test.js +198 -0
  248. package/template/wall-e/eval/fixtures/fullstack-app/server/utils/response.js +34 -0
  249. package/template/wall-e/eval/fixtures/fullstack-app/server/utils/validate.js +26 -0
  250. package/template/wall-e/eval/fixtures/fullstack-app/server.js +8 -0
  251. package/template/wall-e/eval/fixtures/fullstack-app/test.js +12 -0
  252. package/template/wall-e/eval/fixtures/monorepo-basic/package.json +8 -0
  253. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/data.js +58 -0
  254. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/middleware.js +46 -0
  255. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/package.json +8 -0
  256. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/routes.js +64 -0
  257. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/server.js +56 -0
  258. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/test.js +116 -0
  259. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/commands.js +61 -0
  260. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/index.js +62 -0
  261. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/output.js +43 -0
  262. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/package.json +11 -0
  263. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/test.js +44 -0
  264. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/formatters.js +43 -0
  265. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/index.js +12 -0
  266. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/package.json +5 -0
  267. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/test.js +55 -0
  268. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/validators.js +29 -0
  269. package/template/wall-e/eval/fixtures/monorepo-basic/test.js +46 -0
  270. package/template/wall-e/eval/fixtures/node-cli/index.js +78 -0
  271. package/template/wall-e/eval/fixtures/node-cli/package.json +10 -0
  272. package/template/wall-e/eval/fixtures/node-cli/test.js +57 -0
  273. package/template/wall-e/eval/fixtures/node-typed/package.json +8 -0
  274. package/template/wall-e/eval/fixtures/node-typed/src/handlers.js +31 -0
  275. package/template/wall-e/eval/fixtures/node-typed/src/utils.js +33 -0
  276. package/template/wall-e/eval/fixtures/node-typed/test.js +36 -0
  277. package/template/wall-e/eval/fixtures/python-flask/app.py +14 -0
  278. package/template/wall-e/eval/fixtures/python-flask/requirements.txt +2 -0
  279. package/template/wall-e/eval/fixtures/python-flask/test_app.py +25 -0
  280. package/template/wall-e/eval/fixtures/wall-e-subset/brain.js +105 -0
  281. package/template/wall-e/eval/fixtures/wall-e-subset/eval/aggregator.js +101 -0
  282. package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/chat.json +20 -0
  283. package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/coding.json +32 -0
  284. package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks.js +64 -0
  285. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/package.json +6 -0
  286. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/server.js +31 -0
  287. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/test.js +18 -0
  288. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/utils.js +34 -0
  289. package/template/wall-e/eval/fixtures/wall-e-subset/eval/runner.js +104 -0
  290. package/template/wall-e/eval/fixtures/wall-e-subset/eval/scorer.js +73 -0
  291. package/template/wall-e/eval/fixtures/wall-e-subset/eval/test.js +134 -0
  292. package/template/wall-e/eval/fixtures/wall-e-subset/llm/client.js +99 -0
  293. package/template/wall-e/eval/fixtures/wall-e-subset/llm/providers.js +63 -0
  294. package/template/wall-e/eval/fixtures/wall-e-subset/llm/test.js +70 -0
  295. package/template/wall-e/eval/fixtures/wall-e-subset/package.json +10 -0
  296. package/template/wall-e/eval/fixtures/wall-e-subset/test.js +86 -0
  297. package/template/wall-e/eval/harvester.js +628 -0
  298. package/template/wall-e/eval/head-to-head.js +364 -0
  299. package/template/wall-e/eval/humaneval-adapter.js +296 -0
  300. package/template/wall-e/eval/list-models.js +31 -0
  301. package/template/wall-e/eval/livecodebench-adapter.js +267 -0
  302. package/template/wall-e/eval/mail-integration.js +443 -0
  303. package/template/wall-e/eval/promoter.js +228 -0
  304. package/template/wall-e/eval/replay.js +395 -0
  305. package/template/wall-e/eval/run-agent-benchmarks.js +314 -0
  306. package/template/wall-e/eval/run-coding-agent-real.js +187 -0
  307. package/template/wall-e/eval/run-eval.js +425 -0
  308. package/template/wall-e/eval/run-model-comparison.js +141 -0
  309. package/template/wall-e/eval/session-evaluator.js +187 -0
  310. package/template/wall-e/eval/session-miner.js +207 -0
  311. package/template/wall-e/eval/session-transcripts.js +456 -0
  312. package/template/wall-e/eval/shadow.js +161 -0
  313. package/template/wall-e/eval/swebench-adapter.js +238 -0
  314. package/template/wall-e/eval/swebench-docker.js +192 -0
  315. package/template/wall-e/eval/train.py +320 -0
  316. package/template/wall-e/eval/trainer.js +232 -0
  317. package/template/wall-e/eval/weekly-eval-loop.js +241 -0
  318. package/template/wall-e/evaluation/agent-router.js +76 -0
  319. package/template/wall-e/evaluation/coding-quorum.js +325 -0
  320. package/template/wall-e/evaluation/complexity.js +3 -0
  321. package/template/wall-e/evaluation/index.js +3 -1
  322. package/template/wall-e/evaluation/learner.js +15 -2
  323. package/template/wall-e/evaluation/phase-detector.js +129 -0
  324. package/template/wall-e/evaluation/quorum-evaluator.js +545 -0
  325. package/template/wall-e/evaluation/quorum.js +1 -254
  326. package/template/wall-e/evaluation/router.js +250 -25
  327. package/template/wall-e/evaluation/scorecard.js +81 -2
  328. package/template/wall-e/evaluation/self-critique.js +188 -0
  329. package/template/wall-e/evaluation/tier-selector.js +167 -0
  330. package/template/wall-e/evaluation/user-signals.js +109 -0
  331. package/template/wall-e/extraction/contradiction.js +148 -4
  332. package/template/wall-e/extraction/entity-normalizer.js +488 -0
  333. package/template/wall-e/extraction/exchange-chunker.js +83 -0
  334. package/template/wall-e/extraction/heuristic-extractor.js +184 -0
  335. package/template/wall-e/extraction/i18n/en.json +18 -0
  336. package/template/wall-e/extraction/i18n/zh.json +17 -0
  337. package/template/wall-e/extraction/indexer.js +171 -0
  338. package/template/wall-e/extraction/knowledge-extractor.js +61 -17
  339. package/template/wall-e/extraction/noise-stripper.js +63 -0
  340. package/template/wall-e/http/api-utils.js +100 -0
  341. package/template/wall-e/http/auth.js +45 -0
  342. package/template/wall-e/http/chat-api.js +377 -0
  343. package/template/wall-e/http/listening-api.js +441 -0
  344. package/template/wall-e/http/model-admin.js +586 -0
  345. package/template/wall-e/http/scheduler-api.js +49 -0
  346. package/template/wall-e/lib/activity-log.js +99 -0
  347. package/template/wall-e/lib/coalescer.js +46 -0
  348. package/template/wall-e/lib/config-watcher.js +95 -0
  349. package/template/wall-e/lib/recovery-logger.js +226 -0
  350. package/template/wall-e/lib/scheduler-failure-alert.js +127 -0
  351. package/template/wall-e/lib/scheduler.js +760 -0
  352. package/template/wall-e/listening/calendar.js +282 -0
  353. package/template/wall-e/listening/diarize.js +209 -0
  354. package/template/wall-e/listening/engine.js +299 -0
  355. package/template/wall-e/listening/notes.js +293 -0
  356. package/template/wall-e/listening/refine.js +65 -0
  357. package/template/wall-e/listening/storage.js +80 -0
  358. package/template/wall-e/listening/stt.js +251 -0
  359. package/template/wall-e/llm/anthropic.js +139 -18
  360. package/template/wall-e/llm/anthropic.plugin.json +23 -0
  361. package/template/wall-e/llm/claude-cli.js +208 -0
  362. package/template/wall-e/llm/claude-cli.plugin.json +23 -0
  363. package/template/wall-e/llm/client.js +131 -21
  364. package/template/wall-e/llm/codex-cli.js +210 -0
  365. package/template/wall-e/llm/codex-cli.plugin.json +23 -0
  366. package/template/wall-e/llm/deepseek.js +182 -0
  367. package/template/wall-e/llm/deepseek.plugin.json +22 -0
  368. package/template/wall-e/llm/google.js +104 -4
  369. package/template/wall-e/llm/google.plugin.json +22 -0
  370. package/template/wall-e/llm/index.js +2 -0
  371. package/template/wall-e/llm/lmstudio.js +40 -0
  372. package/template/wall-e/llm/lmstudio.plugin.json +23 -0
  373. package/template/wall-e/llm/mlx.js +220 -0
  374. package/template/wall-e/llm/mlx.plugin.json +24 -0
  375. package/template/wall-e/llm/ollama-setup.js +234 -0
  376. package/template/wall-e/llm/ollama.js +66 -8
  377. package/template/wall-e/llm/ollama.plugin.json +23 -0
  378. package/template/wall-e/llm/openai.js +30 -15
  379. package/template/wall-e/llm/openai.plugin.json +22 -0
  380. package/template/wall-e/llm/provider-availability.js +213 -0
  381. package/template/wall-e/llm/provider-detector.js +270 -0
  382. package/template/wall-e/llm/registry.js +248 -0
  383. package/template/wall-e/llm/retry.js +163 -0
  384. package/template/wall-e/llm/tool-adapter.js +50 -3
  385. package/template/wall-e/loops/backfill.js +485 -0
  386. package/template/wall-e/loops/boot.js +124 -0
  387. package/template/wall-e/loops/conversation-composer.js +129 -0
  388. package/template/wall-e/loops/deterministic-ordering.js +140 -0
  389. package/template/wall-e/loops/ingest.js +37 -0
  390. package/template/wall-e/loops/initiative.js +77 -3
  391. package/template/wall-e/loops/loop-directives.js +128 -0
  392. package/template/wall-e/loops/loop-precheck.js +96 -0
  393. package/template/wall-e/loops/loop-prompt-discipline.js +82 -0
  394. package/template/wall-e/loops/reflect.js +47 -0
  395. package/template/wall-e/loops/silent-reply-tokens.js +109 -0
  396. package/template/wall-e/loops/tasks.js +83 -13
  397. package/template/wall-e/loops/think.js +71 -4
  398. package/template/wall-e/loops/workspace-prompts.js +210 -0
  399. package/template/wall-e/mcp-server.js +381 -0
  400. package/template/wall-e/package.json +11 -2
  401. package/template/wall-e/plugins/activation-planner.js +161 -0
  402. package/template/wall-e/plugins/diagnostics.js +138 -0
  403. package/template/wall-e/plugins/manifest-loader.js +215 -0
  404. package/template/wall-e/plugins/manifest-types.js +66 -0
  405. package/template/wall-e/plugins/manifest-validator.js +241 -0
  406. package/template/wall-e/plugins/npm-scanner.js +191 -0
  407. package/template/wall-e/plugins/registry-base.js +81 -0
  408. package/template/wall-e/prompts/tool-workflows.md +51 -0
  409. package/template/wall-e/qa/README.md +59 -0
  410. package/template/wall-e/qa/scenario-format.md +75 -0
  411. package/template/wall-e/qa/scenarios/agents/instruction-followthrough.md +63 -0
  412. package/template/wall-e/qa/scenarios/channels/handoff-context-preservation.md +74 -0
  413. package/template/wall-e/qa/scenarios/character/persona-consistency.md +61 -0
  414. package/template/wall-e/runtime/devbox-gateway.js +38 -0
  415. package/template/wall-e/scripts/eval-embeddings.js +308 -0
  416. package/template/wall-e/scripts/slack-channel-history.js +1 -1
  417. package/template/wall-e/scripts/smoke-coding-agent-jsonl.js +254 -0
  418. package/template/wall-e/search/bm25.js +97 -0
  419. package/template/wall-e/server.js +55 -6
  420. package/template/wall-e/skills/_bundled/coding-agent/run.js +50 -33
  421. package/template/wall-e/skills/_bundled/email-sync/mail-search.swift +237 -0
  422. package/template/wall-e/skills/_bundled/email-sync/run.js +90 -28
  423. package/template/wall-e/skills/_bundled/file-ingest/run.js +17 -7
  424. package/template/wall-e/skills/_bundled/glean-team-sync/run.js +10 -6
  425. package/template/wall-e/skills/_bundled/google-calendar/run.js +46 -29
  426. package/template/wall-e/skills/_bundled/gws-workspace/SKILL.md +76 -0
  427. package/template/wall-e/skills/_bundled/gws-workspace/run.js +401 -0
  428. package/template/wall-e/skills/_bundled/gws-workspace/setup.js +574 -0
  429. package/template/wall-e/skills/_bundled/listening/SKILL.md +26 -0
  430. package/template/wall-e/skills/_bundled/listening/run.js +80 -0
  431. package/template/wall-e/skills/_bundled/mcp-scan/run.js +9 -4
  432. package/template/wall-e/skills/_bundled/morning-briefing/run.js +82 -6
  433. package/template/wall-e/skills/_bundled/proactive-alerts/run.js +28 -7
  434. package/template/wall-e/skills/_bundled/slack-mentions/run.js +104 -34
  435. package/template/wall-e/skills/_bundled/training-harvester/SKILL.md +43 -0
  436. package/template/wall-e/skills/_bundled/training-harvester/run.js +46 -0
  437. package/template/wall-e/skills/internal-skill-registry.js +229 -0
  438. package/template/wall-e/skills/routing-reason-codes.js +82 -0
  439. package/template/wall-e/skills/sandbox-registry.js +104 -0
  440. package/template/wall-e/skills/skill-dispatch-decision.js +192 -0
  441. package/template/wall-e/skills/skill-executor.js +49 -6
  442. package/template/wall-e/skills/skill-fallback.js +146 -0
  443. package/template/wall-e/skills/skill-harness-registry.js +173 -0
  444. package/template/wall-e/skills/skill-loader.js +151 -220
  445. package/template/wall-e/skills/skill-planner.js +427 -79
  446. package/template/wall-e/skills/skill-snapshot.js +134 -0
  447. package/template/wall-e/skills/skill-validator.js +103 -1
  448. package/template/wall-e/skills/slack-ingest.js +26 -2
  449. package/template/wall-e/skills/trigger-registry.js +120 -0
  450. package/template/wall-e/telemetry.js +60 -1
  451. package/template/wall-e/tools/builtin-middleware.js +167 -0
  452. package/template/wall-e/tools/coding-events.js +68 -0
  453. package/template/wall-e/tools/coding-middleware.js +169 -0
  454. package/template/wall-e/tools/command-registry.js +237 -0
  455. package/template/wall-e/tools/edit-replacers.js +485 -0
  456. package/template/wall-e/tools/env-service.js +148 -0
  457. package/template/wall-e/tools/event-log.js +207 -0
  458. package/template/wall-e/tools/file-tracker.js +72 -0
  459. package/template/wall-e/tools/formatter.js +397 -0
  460. package/template/wall-e/tools/local-tools.js +998 -137
  461. package/template/wall-e/tools/lsp-client.js +701 -0
  462. package/template/wall-e/tools/lsp-language.js +137 -0
  463. package/template/wall-e/tools/lsp-servers.js +869 -0
  464. package/template/wall-e/tools/npm-service.js +180 -0
  465. package/template/wall-e/tools/patch.js +503 -0
  466. package/template/wall-e/tools/permission-checker.js +137 -34
  467. package/template/wall-e/tools/permission-rules.js +476 -0
  468. package/template/wall-e/tools/port-detector.js +81 -0
  469. package/template/wall-e/tools/project-detector.js +290 -0
  470. package/template/wall-e/tools/question-manager.js +213 -0
  471. package/template/wall-e/tools/session-sharing.js +231 -0
  472. package/template/wall-e/tools/shell-analyzer.js +524 -0
  473. package/template/wall-e/tools/slack-mcp.js +21 -16
  474. package/template/wall-e/tools/smart-truncation.js +100 -0
  475. package/template/wall-e/tools/snapshot.js +479 -0
  476. package/template/wall-e/training/aggregator.js +115 -0
  477. package/template/wall-e/training/evaluator.js +373 -0
  478. package/template/wall-e/training/exporter.js +86 -1
  479. package/template/wall-e/training/harvester.js +476 -0
  480. package/template/wall-e/training/promoter.js +146 -0
  481. package/template/wall-e/training/replay.js +381 -0
  482. package/template/wall-e/training/shadow.js +144 -0
  483. package/template/wall-e/training/train.py +78 -32
  484. package/template/wall-e/training/trainer.js +30 -1
  485. package/template/wall-e/utils/dedup.js +165 -0
  486. package/template/wall-e/utils/exporter.js +163 -0
  487. package/template/wall-e/utils/heartbeat-content.js +78 -0
  488. package/template/wall-e/utils/repair.js +145 -0
  489. package/template/website/index.html +2 -3
  490. package/template/wall-e/test/evaluation/complexity.test.js +0 -101
  491. package/template/wall-e/test/evaluation/learner.test.js +0 -271
  492. package/template/wall-e/test/evaluation/quorum.test.js +0 -372
  493. package/template/wall-e/test/evaluation/router.test.js +0 -269
  494. package/template/wall-e/test/evaluation/scorecard.test.js +0 -152
  495. package/template/wall-e/test/llm/anthropic.test.js +0 -172
  496. package/template/wall-e/test/llm/brain-models.test.js +0 -182
  497. package/template/wall-e/test/llm/client.test.js +0 -132
  498. package/template/wall-e/test/llm/google.test.js +0 -37
  499. package/template/wall-e/test/llm/health.test.js +0 -426
  500. package/template/wall-e/test/llm/integration.test.js +0 -285
  501. package/template/wall-e/test/llm/ollama.test.js +0 -50
  502. package/template/wall-e/test/llm/openai.test.js +0 -48
  503. package/template/wall-e/test/llm/tool-adapter.test.js +0 -297
  504. package/template/wall-e/test/training/evaluate.test.js +0 -221
  505. package/template/wall-e/test/training/exporter.test.js +0 -213
  506. package/template/wall-e/test/training/trainer.test.js +0 -241
  507. package/template/wall-e/tests/adapter-base.test.js +0 -20
  508. package/template/wall-e/tests/adapter-ctm.test.js +0 -122
  509. package/template/wall-e/tests/adapter-slack.test.js +0 -98
  510. package/template/wall-e/tests/agent-api.test.js +0 -256
  511. package/template/wall-e/tests/api-walle.test.js +0 -222
  512. package/template/wall-e/tests/brain.test.js +0 -603
  513. package/template/wall-e/tests/channels.test.js +0 -104
  514. package/template/wall-e/tests/chat.test.js +0 -103
  515. package/template/wall-e/tests/coding-agent-integration.test.js +0 -240
  516. package/template/wall-e/tests/coding-context.test.js +0 -212
  517. package/template/wall-e/tests/coding-orchestrator.test.js +0 -303
  518. package/template/wall-e/tests/coding-review.test.js +0 -141
  519. package/template/wall-e/tests/compactor.test.js +0 -321
  520. package/template/wall-e/tests/confidence.test.js +0 -134
  521. package/template/wall-e/tests/context-builder.test.js +0 -215
  522. package/template/wall-e/tests/contradiction.test.js +0 -217
  523. package/template/wall-e/tests/event-bus.test.js +0 -74
  524. package/template/wall-e/tests/ingest.test.js +0 -113
  525. package/template/wall-e/tests/initiative.test.js +0 -354
  526. package/template/wall-e/tests/mcp-client.test.js +0 -71
  527. package/template/wall-e/tests/proactive-alerts.test.js +0 -140
  528. package/template/wall-e/tests/reflect.test.js +0 -103
  529. package/template/wall-e/tests/server.test.js +0 -111
  530. package/template/wall-e/tests/session-persistence.test.js +0 -331
  531. package/template/wall-e/tests/skills.test.js +0 -198
  532. package/template/wall-e/tests/slack-ingest.test.js +0 -103
  533. package/template/wall-e/tests/think.test.js +0 -435
package/README.md CHANGED
@@ -23,7 +23,7 @@ An always-on AI agent that learns from your Slack, email, calendar, and coding s
23
23
  - **Second Brain** — Automatically ingests your digital life into a searchable memory store with full-text search, knowledge extraction, and pattern detection
24
24
  - **Proactive Intelligence** — Surfaces time-sensitive items, suggests actions, and delivers morning briefings and weekly reflections without being asked
25
25
  - **Chat with Tools** — Talk to Wall-E in the browser — it can search your memories, look up people, run skills, and call external tools via MCP (Slack, Glean, etc.)
26
- - **16 Bundled Skills** — Morning briefing, weekly reflection, proactive alerts, Slack monitoring, email sync, calendar integration, coding agent, model training, and more
26
+ - **19 Bundled Skills** — Morning briefing, weekly reflection, proactive alerts, Slack monitoring, email sync, calendar integration, coding agent, model training, model pricing sync, and more
27
27
  - **Multi-Model** — Works with Claude, GPT, Gemini, and local models via Ollama with smart routing
28
28
  - **Skill Management GUI** — Search, filter, create, edit, and monitor skills from the browser with rich cards, config forms, execution history, export/import, and pre-flight validation
29
29
  - **Multi-Device** — Share your brain across machines via Dropbox or iCloud
@@ -13,6 +13,7 @@ const RED = '\x1b[31m';
13
13
  const CYAN = '\x1b[36m';
14
14
  const RESET = '\x1b[0m';
15
15
 
16
+ const { injectMcpConfigs } = require('./mcp-inject');
16
17
  const TEMPLATE_DIR = path.join(__dirname, '..', 'template');
17
18
  const LABEL = 'com.walle.server';
18
19
  const INSTALL_PATH_FILE = path.join(process.env.HOME, '.walle', 'install-path');
@@ -70,6 +71,29 @@ ${BOLD}${CYAN} Wall-E${RESET} — Your personal digital twin
70
71
  `);
71
72
  }
72
73
 
74
+ function printMcpResults(wallePort) {
75
+ try {
76
+ const results = injectMcpConfigs(wallePort);
77
+ const hasAny = results.some(r => r.action !== 'not_installed');
78
+ if (!hasAny) return;
79
+
80
+ console.log(` ${BOLD}MCP Integrations:${RESET}`);
81
+ for (const r of results) {
82
+ if (r.action === 'not_installed') {
83
+ console.log(` ${DIM}- ${r.tool} -- not installed${RESET}`);
84
+ } else if (r.action === 'already_configured') {
85
+ console.log(` ${DIM}= ${r.tool} -- already configured${RESET}`);
86
+ } else if (r.action === 'updated') {
87
+ console.log(` ${GREEN}~ ${r.tool}${RESET} -- updated port in ${DIM}${r.configPath}${RESET}`);
88
+ } else {
89
+ console.log(` ${GREEN}+ ${r.tool}${RESET} -- added Wall-E to ${DIM}${r.configPath}${RESET}`);
90
+ }
91
+ }
92
+ console.log(`\n ${DIM}Your AI coding tools can now access Wall-E's memory and knowledge.`);
93
+ console.log(` To undo: remove the "wall-e" entry from the config files above.${RESET}\n`);
94
+ } catch {}
95
+ }
96
+
73
97
  function install(targetDir) {
74
98
  // If no target dir given, check for existing install
75
99
  if (!targetDir) {
@@ -120,14 +144,20 @@ function install(targetDir) {
120
144
  console.log(` Installing dependencies...\n`);
121
145
  npmInstall(targetDir);
122
146
 
147
+ compileHotkeyDaemon(targetDir);
148
+
123
149
  // .env
124
150
  const envLines = [
125
151
  `# Wall-E configuration — generated ${new Date().toISOString().split('T')[0]}`,
126
152
  `# Finish setup at http://localhost:${port}/setup.html`,
127
153
  '',
128
- `WALLE_OWNER_NAME=${ownerName}`,
154
+ `WALLE_OWNER_NAME="${ownerName.replace(/"/g, '\\"')}"`,
129
155
  '# ANTHROPIC_API_KEY=',
130
156
  '',
157
+ '# AI Provider: anthropic, openai, google, ollama',
158
+ '# WALLE_PROVIDER=anthropic',
159
+ '# WALLE_MODEL=',
160
+ '',
131
161
  `CTM_PORT=${port}`,
132
162
  `WALL_E_PORT=${wallePort}`,
133
163
  '',
@@ -172,6 +202,7 @@ function install(targetDir) {
172
202
  npx create-walle status ${DIM}Check status${RESET}
173
203
  npx create-walle logs ${DIM}View logs${RESET}
174
204
  `);
205
+ printMcpResults(parseInt(wallePort));
175
206
  }
176
207
 
177
208
  function update() {
@@ -218,7 +249,9 @@ function update() {
218
249
  console.log(` Installing dependencies...\n`);
219
250
  npmInstall(dir);
220
251
 
221
- // 6. Start again
252
+ compileHotkeyDaemon(dir);
253
+
254
+ // 7. Start again
222
255
  console.log(`\n Starting Wall-E...`);
223
256
  startForegroundOrService(dir, port);
224
257
 
@@ -227,6 +260,7 @@ function update() {
227
260
 
228
261
  ${DIM}Your .env and config were preserved.${RESET}
229
262
  `);
263
+ printMcpResults(parseInt(readWallePort(dir)));
230
264
  }
231
265
 
232
266
  function start() {
@@ -235,6 +269,7 @@ function start() {
235
269
  console.log(`\n Starting Wall-E from ${DIM}${dir}${RESET} on port ${port}...`);
236
270
  installService(dir, port);
237
271
  console.log(` ${GREEN}Running!${RESET} http://localhost:${port}\n`);
272
+ printMcpResults(parseInt(readWallePort(dir)));
238
273
  }
239
274
 
240
275
  function stop() {
@@ -300,9 +335,8 @@ function stopQuiet(dir, port) {
300
335
  while (Date.now() < deadline) {
301
336
  try {
302
337
  execFileSync('curl', ['-s', '--max-time', '1', `http://localhost:${port}/api/services/status`], { encoding: 'utf8', timeout: 2000 });
303
- // Still running — busy-wait briefly
304
- const waitUntil = Date.now() + 500;
305
- while (Date.now() < waitUntil) { /* spin */ }
338
+ // Still running — sleep briefly (avoid CPU spin)
339
+ try { execFileSync('sleep', ['0.5'], { timeout: 2000 }); } catch {}
306
340
  } catch {
307
341
  break; // Port is free
308
342
  }
@@ -339,15 +373,18 @@ function installService(walleDir, port) {
339
373
  fs.mkdirSync(plistDir, { recursive: true });
340
374
  const plistPath = path.join(plistDir, `${LABEL}.plist`);
341
375
 
342
- let envDict = ` <key>PATH</key>\n <string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>\n`;
343
- envDict += ` <key>HOME</key>\n <string>${process.env.HOME}</string>\n`;
376
+ const xmlEsc = (s) => String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
377
+ const nodeBinDir = path.dirname(nodePath);
378
+ let envDict = ` <key>PATH</key>\n <string>${xmlEsc(nodeBinDir)}:/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>\n`;
379
+ envDict += ` <key>HOME</key>\n <string>${xmlEsc(process.env.HOME)}</string>\n`;
344
380
  envDict += ` <key>CTM_PORT</key>\n <string>${port}</string>\n`;
381
+ envDict += ` <key>CTM_MANAGED_BY_LAUNCHD</key>\n <string>1</string>\n`;
345
382
  try {
346
383
  const envFile = fs.readFileSync(path.join(walleDir, '.env'), 'utf8');
347
384
  for (const line of envFile.split('\n')) {
348
385
  const m = line.match(/^\s*([^#=\s]+)\s*=\s*(.+?)\s*$/);
349
386
  if (m && m[1] !== 'CTM_PORT' && m[1] !== 'PATH' && m[1] !== 'HOME') {
350
- envDict += ` <key>${m[1]}</key>\n <string>${m[2]}</string>\n`;
387
+ envDict += ` <key>${xmlEsc(m[1])}</key>\n <string>${xmlEsc(m[2])}</string>\n`;
351
388
  }
352
389
  }
353
390
  } catch {}
@@ -371,11 +408,16 @@ ${envDict} </dict>
371
408
  <key>RunAtLoad</key>
372
409
  <true/>
373
410
  <key>KeepAlive</key>
374
- <true/>
411
+ <dict>
412
+ <key>SuccessfulExit</key>
413
+ <false/>
414
+ </dict>
415
+ <key>ThrottleInterval</key>
416
+ <integer>5</integer>
375
417
  <key>StandardOutPath</key>
376
- <string>${logDir}/walle.log</string>
418
+ <string>${logDir}/ctm.log</string>
377
419
  <key>StandardErrorPath</key>
378
- <string>${logDir}/walle.err</string>
420
+ <string>${logDir}/ctm.err</string>
379
421
  </dict>
380
422
  </plist>`;
381
423
 
@@ -383,10 +425,34 @@ ${envDict} </dict>
383
425
  try { execFileSync('launchctl', ['unload', plistPath], { stdio: 'ignore' }); } catch {}
384
426
  execFileSync('launchctl', ['load', plistPath]);
385
427
  } else {
386
- const child = spawn(process.execPath, ['claude-task-manager/server.js'], {
428
+ // Linux/other: spawn with a restart-on-crash wrapper shell script
429
+ const watchdogScript = path.join(walleDir, 'bin', 'watchdog.sh');
430
+ const watchdogContent = `#!/bin/bash
431
+ # Auto-restart CTM on crash. Clean exit (code 0) stops the watchdog.
432
+ CRASHES=0
433
+ while true; do
434
+ "${process.execPath}" claude-task-manager/server.js >> "${logDir}/ctm.log" 2>> "${logDir}/ctm.err"
435
+ EXIT_CODE=$?
436
+ if [ $EXIT_CODE -eq 0 ]; then
437
+ echo "[watchdog] Clean exit (code 0), stopping." >> "${logDir}/ctm.log"
438
+ break
439
+ fi
440
+ CRASHES=$((CRASHES + 1))
441
+ echo "[watchdog] CTM exited with code $EXIT_CODE (crash #$CRASHES), restarting in 5s..." >> "${logDir}/ctm.log"
442
+ if [ $CRASHES -ge 5 ]; then
443
+ echo "[watchdog] Too many crashes ($CRASHES), giving up." >> "${logDir}/ctm.log"
444
+ break
445
+ fi
446
+ sleep 5
447
+ done
448
+ `;
449
+ fs.mkdirSync(path.join(walleDir, 'bin'), { recursive: true });
450
+ fs.writeFileSync(watchdogScript, watchdogContent, { mode: 0o755 });
451
+
452
+ const child = spawn('bash', [watchdogScript], {
387
453
  cwd: walleDir,
388
454
  detached: true,
389
- stdio: ['ignore', fs.openSync(path.join(logDir, 'walle.log'), 'a'), fs.openSync(path.join(logDir, 'walle.err'), 'a')],
455
+ stdio: 'ignore',
390
456
  env: { ...process.env, CTM_PORT: port },
391
457
  });
392
458
  child.unref();
@@ -474,6 +540,22 @@ function detectTimezone() {
474
540
  return 'UTC';
475
541
  }
476
542
 
543
+ function compileHotkeyDaemon(walleDir) {
544
+ if (process.platform !== 'darwin') return; // macOS only
545
+ const swiftSource = path.join(walleDir, 'claude-task-manager', 'bin', 'ctm-hotkey.swift');
546
+ if (!fs.existsSync(swiftSource)) return;
547
+ const binary = path.join(process.env.HOME, '.local', 'bin', 'ctm-hotkey');
548
+ try {
549
+ fs.mkdirSync(path.dirname(binary), { recursive: true });
550
+ execFileSync('swiftc', ['-O', '-o', binary, swiftSource, '-framework', 'Cocoa'], { timeout: 120000, stdio: 'pipe' });
551
+ fs.chmodSync(binary, 0o755);
552
+ console.log(` ${GREEN}Compiled hotkey daemon${RESET} ${DIM}(${binary})${RESET}`);
553
+ } catch {
554
+ // swiftc not available or compilation failed — non-fatal
555
+ console.log(` ${DIM}Skipped hotkey daemon (Swift compiler not available)${RESET}`);
556
+ }
557
+ }
558
+
477
559
  function copyRecursive(src, dest) {
478
560
  const stat = fs.statSync(src);
479
561
  if (stat.isDirectory()) {
@@ -0,0 +1,60 @@
1
+ 'use strict';
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+
5
+ const MCP_TARGETS = [
6
+ { tool: 'Claude Code', configPath: '.claude/mcp.json', detectDir: '.claude' },
7
+ { tool: 'Cursor', configPath: '.cursor/mcp.json', detectDir: '.cursor' },
8
+ { tool: 'Windsurf', configPath: '.codeium/windsurf/mcp_config.json', detectDir: '.codeium/windsurf' },
9
+ { tool: 'Claude Desktop', configPath: 'Library/Application Support/Claude/claude_desktop_config.json', detectDir: 'Library/Application Support/Claude' },
10
+ ];
11
+
12
+ /**
13
+ * Inject Wall-E MCP server config into detected AI tool config files.
14
+ * @param {number} wallePort - The Wall-E HTTP port
15
+ * @param {string} [homeDir] - Home directory override for testing
16
+ * @returns {Array<{tool: string, action: string, configPath?: string}>}
17
+ */
18
+ function injectMcpConfigs(wallePort, homeDir) {
19
+ const home = homeDir || process.env.HOME;
20
+ const walleUrl = `http://localhost:${wallePort}/mcp`;
21
+ const results = [];
22
+
23
+ for (const target of MCP_TARGETS) {
24
+ const detectPath = path.join(home, target.detectDir);
25
+ const configPath = path.join(home, target.configPath);
26
+
27
+ if (!fs.existsSync(detectPath)) {
28
+ results.push({ tool: target.tool, action: 'not_installed' });
29
+ continue;
30
+ }
31
+
32
+ let config = {};
33
+ if (fs.existsSync(configPath)) {
34
+ try {
35
+ config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
36
+ } catch {
37
+ config = {};
38
+ }
39
+ }
40
+
41
+ if (!config.mcpServers) config.mcpServers = {};
42
+
43
+ const existing = config.mcpServers['wall-e'];
44
+ if (existing && existing.url === walleUrl) {
45
+ results.push({ tool: target.tool, action: 'already_configured', configPath });
46
+ continue;
47
+ }
48
+
49
+ const action = existing ? 'updated' : 'added';
50
+ config.mcpServers['wall-e'] = { type: 'http', url: walleUrl };
51
+
52
+ fs.mkdirSync(path.dirname(configPath), { recursive: true });
53
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
54
+ results.push({ tool: target.tool, action, configPath });
55
+ }
56
+
57
+ return results;
58
+ }
59
+
60
+ module.exports = { injectMcpConfigs, MCP_TARGETS };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "create-walle",
3
- "version": "0.9.8",
4
- "description": "CTM + Wall-E AI coding dashboard and personal digital twin agent. Multi-agent terminal for Claude Code, Codex, Gemini & Aider, plus prompt editor, task queue, and an agent that learns from Slack, email & calendar.",
3
+ "version": "0.9.10",
4
+ "description": "CTM + Wall-E \u2014 AI coding dashboard and personal digital twin agent. Multi-agent terminal for Claude Code, Codex, Gemini & Aider, plus prompt editor, task queue, and an agent that learns from Slack, email & calendar.",
5
5
  "bin": {
6
6
  "create-walle": "bin/create-walle.js"
7
7
  },
@@ -15,5 +15,13 @@
15
15
  "prepublishOnly": "bash build.sh"
16
16
  },
17
17
  "license": "MIT",
18
- "keywords": ["ctm", "task-manager", "wall-e", "ai", "digital-twin", "claude", "personal-assistant"]
18
+ "keywords": [
19
+ "ctm",
20
+ "task-manager",
21
+ "wall-e",
22
+ "ai",
23
+ "digital-twin",
24
+ "claude",
25
+ "personal-assistant"
26
+ ]
19
27
  }
@@ -24,6 +24,18 @@ When developing CTM or Wall-E code:
24
24
  4. Test ONLY against your dev port, never 3456
25
25
  5. Only restart primary when the user explicitly asks — and ask for confirmation first
26
26
 
27
+ ## Testing
28
+
29
+ Both projects use Node.js built-in test runner with `--test-force-exit` to prevent hangs:
30
+ - **Wall-E**: `cd wall-e && npm test`
31
+ - **CTM**: `cd claude-task-manager && npm test`
32
+
33
+ When writing new tests, follow these rules to avoid handle leaks and cross-test contamination:
34
+ - **Never set `process.env` at module top level** — set in `before()`, restore in `after()`
35
+ - **Close every DB connection you open** — store `readDb` handles in module scope, close in `after()`/teardown
36
+ - **Call `brain.closeDb()` before `brain.initDb()`** in tests that reinitialize the brain singleton
37
+ - **Don't change `journal_mode`** on readonly connections (causes SQLITE_BUSY against WAL dbs)
38
+
27
39
  ## Publishing to npm (create-walle)
28
40
 
29
41
  When publishing with `/publish`:
@@ -32,3 +44,10 @@ When publishing with `/publish`:
32
44
  3. Bump version in both `create-walle/package.json` AND root `package.json`
33
45
  4. Run `bash build.sh` and verify file count
34
46
  5. Ask for confirmation before `npm publish`
47
+
48
+ ## Architecture reference
49
+
50
+ For Wall-E architecture (loops, brain DB, scheduler, skills, channels, anti-patterns):
51
+ read `wall-e/docs/architecture.md` before making non-trivial changes. The
52
+ "Non-goals" section is a guardrail — coordinate via data, not via
53
+ manager-of-managers.
@@ -3,50 +3,64 @@
3
3
  # Primary instance stays untouched. Ctrl+C to stop.
4
4
  #
5
5
  # Usage:
6
- # bash bin/dev.sh # Start dev instance (snapshot DBs on first run)
7
- # bash bin/dev.sh --refresh # Re-copy production DBs before starting
8
- # bash bin/dev.sh --fresh # Start with empty DBs
6
+ # bash bin/dev.sh # Start dev instance with fresh empty DBs
7
+ # bash bin/dev.sh --refresh # Explicitly copy production DBs before starting
8
+ # bash bin/dev.sh --fresh # Reset to empty DBs before starting
9
9
 
10
10
  set -e
11
11
  ROOT="$(cd "$(dirname "$0")/.." && pwd)"
12
12
  DEV_DIR="${WALLE_DEV_DIR:-/tmp/walle-dev}"
13
13
  DEV_CTM_PORT="${DEV_CTM_PORT:-4000}"
14
14
  DEV_WALLE_PORT="${DEV_WALLE_PORT:-4001}"
15
+ DEV_OAUTH_PROXY_PORT="${DEV_OAUTH_PROXY_PORT:-$((DEV_CTM_PORT + 2))}"
15
16
 
16
- # Source production .env to find DB paths
17
- PROD_CTM_DIR="$HOME/.walle/data"
18
- PROD_WALLE_DIR="$HOME/.walle/data"
17
+ # Source production .env to find DB paths. DEV_SOURCE_* lets worktrees without
18
+ # their own .env refresh from the primary repo's configured data directory.
19
+ PROD_CTM_DIR="${DEV_SOURCE_CTM_DATA_DIR:-$HOME/.walle/data}"
20
+ PROD_WALLE_DIR="${DEV_SOURCE_WALL_E_DATA_DIR:-$HOME/.walle/data}"
19
21
  if [[ -f "$ROOT/.env" ]]; then
20
22
  eval "$(grep -E '^(CTM_DATA_DIR|WALL_E_DATA_DIR)=' "$ROOT/.env" 2>/dev/null)" || true
21
- [[ -n "$CTM_DATA_DIR" ]] && PROD_CTM_DIR="$CTM_DATA_DIR"
22
- [[ -n "$WALL_E_DATA_DIR" ]] && PROD_WALLE_DIR="$WALL_E_DATA_DIR"
23
+ [[ -z "$DEV_SOURCE_CTM_DATA_DIR" && -n "$CTM_DATA_DIR" ]] && PROD_CTM_DIR="$CTM_DATA_DIR"
24
+ [[ -z "$DEV_SOURCE_WALL_E_DATA_DIR" && -n "$WALL_E_DATA_DIR" ]] && PROD_WALLE_DIR="$WALL_E_DATA_DIR"
23
25
  fi
24
26
 
25
27
  mkdir -p "$DEV_DIR"
26
28
 
29
+ cleanup_processes() {
30
+ pkill -f "ctm-dev-$DEV_CTM_PORT" 2>/dev/null || true
31
+ pkill -f "walle-dev-$DEV_CTM_PORT" 2>/dev/null || true
32
+ lsof -ti ":$DEV_CTM_PORT" -sTCP:LISTEN 2>/dev/null | xargs kill 2>/dev/null || true
33
+ lsof -ti ":$DEV_WALLE_PORT" -sTCP:LISTEN 2>/dev/null | xargs kill 2>/dev/null || true
34
+ lsof -ti ":$DEV_OAUTH_PROXY_PORT" -sTCP:LISTEN 2>/dev/null | xargs kill 2>/dev/null || true
35
+ }
36
+
37
+ cleanup_dev() {
38
+ cleanup_processes
39
+ # Remove dev data directory to prevent /tmp bloat (each copy is ~2-6 GB)
40
+ if [[ "$DEV_DIR" == /tmp/walle-* && -d "$DEV_DIR" ]]; then
41
+ echo "[dev] Cleaning up $DEV_DIR ..."
42
+ rm -rf "$DEV_DIR"
43
+ fi
44
+ }
45
+
46
+ cleanup_processes
47
+
27
48
  # Handle flags
28
- if [[ "$1" == "--fresh" ]]; then
49
+ if [[ "$1" == "--fresh" || -z "$1" ]]; then
29
50
  echo "[dev] Starting with fresh (empty) databases"
30
51
  rm -f "$DEV_DIR"/*.db "$DEV_DIR"/*.db-wal "$DEV_DIR"/*.db-shm
31
- elif [[ "$1" == "--refresh" || ! -f "$DEV_DIR/task-manager.db" ]]; then
32
- echo "[dev] Copying production databases to $DEV_DIR ..."
33
- # Copy CTM DB
34
- if [[ -f "$PROD_CTM_DIR/task-manager.db" ]]; then
35
- cp "$PROD_CTM_DIR/task-manager.db" "$DEV_DIR/task-manager.db"
36
- echo " CTM: $PROD_CTM_DIR/task-manager.db → $DEV_DIR/"
37
- fi
38
- # Copy Wall-E brain
39
- if [[ -f "$PROD_WALLE_DIR/wall-e-brain.db" ]]; then
40
- cp "$PROD_WALLE_DIR/wall-e-brain.db" "$DEV_DIR/wall-e-brain.db"
41
- echo " Brain: $PROD_WALLE_DIR/wall-e-brain.db → $DEV_DIR/"
42
- fi
43
- # Clean WAL files (they're specific to the source process)
52
+ elif [[ "$1" == "--refresh" ]]; then
53
+ echo "[dev] Snapshotting production databases to $DEV_DIR ..."
54
+ node "$ROOT/bin/sqlite-snapshot.js" "$PROD_CTM_DIR/task-manager.db" "$DEV_DIR/task-manager.db" "CTM"
55
+ node "$ROOT/bin/sqlite-snapshot.js" "$PROD_WALLE_DIR/wall-e-brain.db" "$DEV_DIR/wall-e-brain.db" "Brain"
56
+ # Ensure the dev instance owns its WAL files from first open.
44
57
  rm -f "$DEV_DIR"/*.db-wal "$DEV_DIR"/*.db-shm
45
58
  fi
46
59
 
47
60
  echo ""
48
61
  echo " Dev CTM: http://localhost:$DEV_CTM_PORT"
49
62
  echo " Dev Wall-E: port $DEV_WALLE_PORT"
63
+ echo " Dev OAuth: port $DEV_OAUTH_PROXY_PORT"
50
64
  echo " Dev data: $DEV_DIR"
51
65
  echo " Source: $ROOT"
52
66
  echo ""
@@ -59,14 +73,23 @@ export WALL_E_PORT="$DEV_WALLE_PORT"
59
73
  export CTM_DATA_DIR="$DEV_DIR"
60
74
  export WALL_E_DATA_DIR="$DEV_DIR"
61
75
  export CTM_HOST="127.0.0.1"
76
+ export CTM_INSTANCE_TAG="dev-$DEV_CTM_PORT"
77
+ export OAUTH_PROXY_PORT="$DEV_OAUTH_PROXY_PORT"
62
78
 
63
79
  # Source the rest of .env (API keys, owner name, etc.)
64
80
  if [[ -f "$ROOT/.env" ]]; then
65
81
  set -a
66
- source <(grep -v '^#' "$ROOT/.env" | grep -vE '^(CTM_PORT|WALL_E_PORT|CTM_DATA_DIR|WALL_E_DATA_DIR|CTM_HOST)=' | grep '=')
82
+ source <(grep -v '^#' "$ROOT/.env" | grep -vE '^(CTM_PORT|WALL_E_PORT|CTM_DATA_DIR|WALL_E_DATA_DIR|CTM_HOST|CTM_INSTANCE_TAG|OAUTH_PROXY_PORT)=' | grep '=')
67
83
  set +a
68
84
  fi
69
85
 
86
+ trap cleanup_dev EXIT
87
+
88
+ # Clean up stale dev/e2e data dirs older than 24h (from crashed sessions)
89
+ find /tmp -maxdepth 1 -name "walle-dev-*" -type d -mmin +1440 -exec rm -rf {} + 2>/dev/null || true
90
+ find /tmp -maxdepth 1 -name "walle-e2e-*" -type d -mmin +1440 -exec rm -rf {} + 2>/dev/null || true
91
+ find /tmp -maxdepth 1 -name "ctm-dev-*" -type d -mmin +1440 -exec rm -rf {} + 2>/dev/null || true
92
+
70
93
  # Run in foreground so Ctrl+C stops it cleanly
71
94
  cd "$ROOT"
72
95
  exec node claude-task-manager/server.js
@@ -1,5 +1,6 @@
1
1
  #!/bin/bash
2
- # Install Wall-E as a macOS Launch Agent so it starts automatically on login.
2
+ # Install CTM + Wall-E as a macOS Launch Agent so it starts automatically on login
3
+ # and auto-restarts on crash (but NOT on clean exit).
3
4
  # Usage: bash bin/install-service.sh [--uninstall]
4
5
 
5
6
  set -e
@@ -7,22 +8,40 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
7
8
  ROOT="$(dirname "$SCRIPT_DIR")"
8
9
  LABEL="com.walle.server"
9
10
  PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
10
- PORT="${CTM_PORT:-4567}"
11
+ PORT="${CTM_PORT:-3456}"
11
12
 
12
13
  if [[ "$1" == "--uninstall" ]]; then
13
- launchctl unload "$PLIST" 2>/dev/null || true
14
+ launchctl bootout "gui/$(id -u)/$LABEL" 2>/dev/null || \
15
+ launchctl unload "$PLIST" 2>/dev/null || true
14
16
  rm -f "$PLIST"
15
- echo "Wall-E service uninstalled."
17
+ echo "CTM service uninstalled."
16
18
  exit 0
17
19
  fi
18
20
 
19
- # Source .env to get the port
21
+ # Source .env for port and data dir overrides
22
+ ENV_VARS=""
20
23
  if [[ -f "$ROOT/.env" ]]; then
21
- export $(grep -v '^#' "$ROOT/.env" | grep '=' | xargs)
22
- PORT="${CTM_PORT:-4567}"
24
+ while IFS='' read -r line || [[ -n "$line" ]]; do
25
+ [[ -z "$line" || "$line" == \#* ]] && continue
26
+ key="${line%%=*}"
27
+ value="${line#*=}"
28
+ key=$(echo "$key" | xargs)
29
+ value=$(echo "$value" | xargs | sed 's/^["'"'"']//;s/["'"'"']$//')
30
+ [[ -z "$key" ]] && continue
31
+ case "$key" in
32
+ CTM_PORT) PORT="$value" ;;
33
+ esac
34
+ # XML-escape for plist safety
35
+ esc_key=$(echo "$key" | sed 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g')
36
+ esc_val=$(echo "$value" | sed 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g')
37
+ ENV_VARS="$ENV_VARS
38
+ <key>$esc_key</key>
39
+ <string>$esc_val</string>"
40
+ done < "$ROOT/.env"
23
41
  fi
24
42
 
25
43
  NODE=$(which node)
44
+ NODE_BIN_DIR=$(dirname "$NODE")
26
45
  LOG_DIR="$HOME/.walle/logs"
27
46
  mkdir -p "$LOG_DIR"
28
47
 
@@ -43,30 +62,45 @@ cat > "$PLIST" << EOF
43
62
  <key>EnvironmentVariables</key>
44
63
  <dict>
45
64
  <key>PATH</key>
46
- <string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>
65
+ <string>$NODE_BIN_DIR:/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>
47
66
  <key>HOME</key>
48
67
  <string>$HOME</string>
49
68
  <key>CTM_PORT</key>
50
69
  <string>$PORT</string>
70
+ <key>CTM_MANAGED_BY_LAUNCHD</key>
71
+ <string>1</string>$ENV_VARS
51
72
  </dict>
52
73
  <key>RunAtLoad</key>
53
74
  <true/>
54
75
  <key>KeepAlive</key>
55
- <true/>
76
+ <dict>
77
+ <key>SuccessfulExit</key>
78
+ <false/>
79
+ </dict>
80
+ <key>ThrottleInterval</key>
81
+ <integer>5</integer>
56
82
  <key>StandardOutPath</key>
57
- <string>$LOG_DIR/walle.log</string>
83
+ <string>$LOG_DIR/ctm.log</string>
58
84
  <key>StandardErrorPath</key>
59
- <string>$LOG_DIR/walle.err</string>
85
+ <string>$LOG_DIR/ctm.err</string>
60
86
  </dict>
61
87
  </plist>
62
88
  EOF
63
89
 
64
- launchctl unload "$PLIST" 2>/dev/null || true
65
- launchctl load "$PLIST"
90
+ # Load the service (unload first if previously loaded, wait for clean exit)
91
+ launchctl bootout "gui/$(id -u)/$LABEL" 2>/dev/null || \
92
+ launchctl unload "$PLIST" 2>/dev/null || true
93
+ sleep 1 # Let old process release port before bootstrapping new one
94
+ launchctl bootstrap "gui/$(id -u)" "$PLIST" 2>/dev/null || \
95
+ launchctl load "$PLIST"
66
96
 
67
- echo "Wall-E installed as a macOS service."
97
+ echo "CTM installed as a macOS Launch Agent."
68
98
  echo ""
69
- echo " Status: launchctl list | grep walle"
70
- echo " Logs: tail -f ~/.walle/logs/walle.log"
99
+ echo " Status: launchctl list $LABEL"
100
+ echo " Logs: tail -f ~/.walle/logs/ctm.log"
101
+ echo " Errors: tail -f ~/.walle/logs/ctm.err"
71
102
  echo " Dashboard: http://localhost:$PORT"
72
103
  echo " Uninstall: bash bin/install-service.sh --uninstall"
104
+ echo ""
105
+ echo " Auto-restarts on crash. Clean exit (SIGTERM/SIGINT) stops the service."
106
+ echo " To manually stop: launchctl kill SIGTERM gui/$(id -u)/$LABEL"
@@ -7,6 +7,7 @@
7
7
  const { execFileSync } = require('child_process');
8
8
  const fs = require('fs');
9
9
  const path = require('path');
10
+ const { atomicWriteFileSync } = require('../claude-task-manager/atomic-write');
10
11
 
11
12
  const ROOT = path.resolve(__dirname, '..');
12
13
  const ENV_PATH = path.join(ROOT, '.env');
@@ -41,7 +42,7 @@ function runIfNeeded() {
41
42
  `WALLE_OWNER_NAME=${ownerName}`,
42
43
  '# ANTHROPIC_API_KEY=sk-ant-...',
43
44
  ];
44
- fs.writeFileSync(ENV_PATH, envLines.join('\n') + '\n', { mode: 0o600 });
45
+ atomicWriteFileSync(ENV_PATH, envLines.join('\n') + '\n', { mode: 0o600 });
45
46
 
46
47
  // Set in current process
47
48
  process.env.WALLE_OWNER_NAME = ownerName;