@hoangsonw/forge 0.1.0

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 (598) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +919 -0
  3. package/bin/forge.js +30 -0
  4. package/dist/agents/architect.d.ts +20 -0
  5. package/dist/agents/architect.d.ts.map +1 -0
  6. package/dist/agents/architect.js +75 -0
  7. package/dist/agents/architect.js.map +1 -0
  8. package/dist/agents/base.d.ts +20 -0
  9. package/dist/agents/base.d.ts.map +1 -0
  10. package/dist/agents/base.js +3 -0
  11. package/dist/agents/base.js.map +1 -0
  12. package/dist/agents/debugger.d.ts +16 -0
  13. package/dist/agents/debugger.d.ts.map +1 -0
  14. package/dist/agents/debugger.js +93 -0
  15. package/dist/agents/debugger.js.map +1 -0
  16. package/dist/agents/executor.d.ts +48 -0
  17. package/dist/agents/executor.d.ts.map +1 -0
  18. package/dist/agents/executor.js +402 -0
  19. package/dist/agents/executor.js.map +1 -0
  20. package/dist/agents/memory.d.ts +8 -0
  21. package/dist/agents/memory.d.ts.map +1 -0
  22. package/dist/agents/memory.js +84 -0
  23. package/dist/agents/memory.js.map +1 -0
  24. package/dist/agents/planner.d.ts +5 -0
  25. package/dist/agents/planner.d.ts.map +1 -0
  26. package/dist/agents/planner.js +185 -0
  27. package/dist/agents/planner.js.map +1 -0
  28. package/dist/agents/registry.d.ts +6 -0
  29. package/dist/agents/registry.d.ts.map +1 -0
  30. package/dist/agents/registry.js +32 -0
  31. package/dist/agents/registry.js.map +1 -0
  32. package/dist/agents/reviewer.d.ts +18 -0
  33. package/dist/agents/reviewer.d.ts.map +1 -0
  34. package/dist/agents/reviewer.js +87 -0
  35. package/dist/agents/reviewer.js.map +1 -0
  36. package/dist/classifier/classifier.d.ts +9 -0
  37. package/dist/classifier/classifier.d.ts.map +1 -0
  38. package/dist/classifier/classifier.js +83 -0
  39. package/dist/classifier/classifier.js.map +1 -0
  40. package/dist/classifier/heuristics.d.ts +11 -0
  41. package/dist/classifier/heuristics.d.ts.map +1 -0
  42. package/dist/classifier/heuristics.js +112 -0
  43. package/dist/classifier/heuristics.js.map +1 -0
  44. package/dist/cli/animations.d.ts +27 -0
  45. package/dist/cli/animations.d.ts.map +1 -0
  46. package/dist/cli/animations.js +186 -0
  47. package/dist/cli/animations.js.map +1 -0
  48. package/dist/cli/banners.d.ts +47 -0
  49. package/dist/cli/banners.d.ts.map +1 -0
  50. package/dist/cli/banners.js +211 -0
  51. package/dist/cli/banners.js.map +1 -0
  52. package/dist/cli/bootstrap.d.ts +2 -0
  53. package/dist/cli/bootstrap.d.ts.map +1 -0
  54. package/dist/cli/bootstrap.js +21 -0
  55. package/dist/cli/bootstrap.js.map +1 -0
  56. package/dist/cli/commands/bundle.d.ts +3 -0
  57. package/dist/cli/commands/bundle.d.ts.map +1 -0
  58. package/dist/cli/commands/bundle.js +80 -0
  59. package/dist/cli/commands/bundle.js.map +1 -0
  60. package/dist/cli/commands/changelog.d.ts +3 -0
  61. package/dist/cli/commands/changelog.d.ts.map +1 -0
  62. package/dist/cli/commands/changelog.js +60 -0
  63. package/dist/cli/commands/changelog.js.map +1 -0
  64. package/dist/cli/commands/config.d.ts +3 -0
  65. package/dist/cli/commands/config.d.ts.map +1 -0
  66. package/dist/cli/commands/config.js +91 -0
  67. package/dist/cli/commands/config.js.map +1 -0
  68. package/dist/cli/commands/container.d.ts +3 -0
  69. package/dist/cli/commands/container.d.ts.map +1 -0
  70. package/dist/cli/commands/container.js +149 -0
  71. package/dist/cli/commands/container.js.map +1 -0
  72. package/dist/cli/commands/cost.d.ts +3 -0
  73. package/dist/cli/commands/cost.d.ts.map +1 -0
  74. package/dist/cli/commands/cost.js +38 -0
  75. package/dist/cli/commands/cost.js.map +1 -0
  76. package/dist/cli/commands/daemon.d.ts +3 -0
  77. package/dist/cli/commands/daemon.d.ts.map +1 -0
  78. package/dist/cli/commands/daemon.js +39 -0
  79. package/dist/cli/commands/daemon.js.map +1 -0
  80. package/dist/cli/commands/dev.d.ts +3 -0
  81. package/dist/cli/commands/dev.d.ts.map +1 -0
  82. package/dist/cli/commands/dev.js +73 -0
  83. package/dist/cli/commands/dev.js.map +1 -0
  84. package/dist/cli/commands/doctor.d.ts +3 -0
  85. package/dist/cli/commands/doctor.d.ts.map +1 -0
  86. package/dist/cli/commands/doctor.js +214 -0
  87. package/dist/cli/commands/doctor.js.map +1 -0
  88. package/dist/cli/commands/init.d.ts +3 -0
  89. package/dist/cli/commands/init.d.ts.map +1 -0
  90. package/dist/cli/commands/init.js +148 -0
  91. package/dist/cli/commands/init.js.map +1 -0
  92. package/dist/cli/commands/mcp.d.ts +3 -0
  93. package/dist/cli/commands/mcp.d.ts.map +1 -0
  94. package/dist/cli/commands/mcp.js +227 -0
  95. package/dist/cli/commands/mcp.js.map +1 -0
  96. package/dist/cli/commands/memory.d.ts +3 -0
  97. package/dist/cli/commands/memory.d.ts.map +1 -0
  98. package/dist/cli/commands/memory.js +101 -0
  99. package/dist/cli/commands/memory.js.map +1 -0
  100. package/dist/cli/commands/migrate.d.ts +3 -0
  101. package/dist/cli/commands/migrate.d.ts.map +1 -0
  102. package/dist/cli/commands/migrate.js +18 -0
  103. package/dist/cli/commands/migrate.js.map +1 -0
  104. package/dist/cli/commands/model.d.ts +3 -0
  105. package/dist/cli/commands/model.d.ts.map +1 -0
  106. package/dist/cli/commands/model.js +37 -0
  107. package/dist/cli/commands/model.js.map +1 -0
  108. package/dist/cli/commands/permissions.d.ts +3 -0
  109. package/dist/cli/commands/permissions.d.ts.map +1 -0
  110. package/dist/cli/commands/permissions.js +32 -0
  111. package/dist/cli/commands/permissions.js.map +1 -0
  112. package/dist/cli/commands/resume.d.ts +3 -0
  113. package/dist/cli/commands/resume.d.ts.map +1 -0
  114. package/dist/cli/commands/resume.js +90 -0
  115. package/dist/cli/commands/resume.js.map +1 -0
  116. package/dist/cli/commands/run.d.ts +5 -0
  117. package/dist/cli/commands/run.d.ts.map +1 -0
  118. package/dist/cli/commands/run.js +164 -0
  119. package/dist/cli/commands/run.js.map +1 -0
  120. package/dist/cli/commands/session.d.ts +3 -0
  121. package/dist/cli/commands/session.d.ts.map +1 -0
  122. package/dist/cli/commands/session.js +94 -0
  123. package/dist/cli/commands/session.js.map +1 -0
  124. package/dist/cli/commands/skills.d.ts +4 -0
  125. package/dist/cli/commands/skills.d.ts.map +1 -0
  126. package/dist/cli/commands/skills.js +176 -0
  127. package/dist/cli/commands/skills.js.map +1 -0
  128. package/dist/cli/commands/spec.d.ts +3 -0
  129. package/dist/cli/commands/spec.d.ts.map +1 -0
  130. package/dist/cli/commands/spec.js +58 -0
  131. package/dist/cli/commands/spec.js.map +1 -0
  132. package/dist/cli/commands/status.d.ts +3 -0
  133. package/dist/cli/commands/status.d.ts.map +1 -0
  134. package/dist/cli/commands/status.js +65 -0
  135. package/dist/cli/commands/status.js.map +1 -0
  136. package/dist/cli/commands/task.d.ts +3 -0
  137. package/dist/cli/commands/task.d.ts.map +1 -0
  138. package/dist/cli/commands/task.js +42 -0
  139. package/dist/cli/commands/task.js.map +1 -0
  140. package/dist/cli/commands/ui.d.ts +3 -0
  141. package/dist/cli/commands/ui.d.ts.map +1 -0
  142. package/dist/cli/commands/ui.js +28 -0
  143. package/dist/cli/commands/ui.js.map +1 -0
  144. package/dist/cli/commands/update.d.ts +3 -0
  145. package/dist/cli/commands/update.d.ts.map +1 -0
  146. package/dist/cli/commands/update.js +53 -0
  147. package/dist/cli/commands/update.js.map +1 -0
  148. package/dist/cli/commands/web.d.ts +3 -0
  149. package/dist/cli/commands/web.d.ts.map +1 -0
  150. package/dist/cli/commands/web.js +42 -0
  151. package/dist/cli/commands/web.js.map +1 -0
  152. package/dist/cli/help.d.ts +21 -0
  153. package/dist/cli/help.d.ts.map +1 -0
  154. package/dist/cli/help.js +216 -0
  155. package/dist/cli/help.js.map +1 -0
  156. package/dist/cli/index.d.ts +3 -0
  157. package/dist/cli/index.d.ts.map +1 -0
  158. package/dist/cli/index.js +154 -0
  159. package/dist/cli/index.js.map +1 -0
  160. package/dist/cli/repl-commands.d.ts +47 -0
  161. package/dist/cli/repl-commands.d.ts.map +1 -0
  162. package/dist/cli/repl-commands.js +508 -0
  163. package/dist/cli/repl-commands.js.map +1 -0
  164. package/dist/cli/repl-input.d.ts +87 -0
  165. package/dist/cli/repl-input.d.ts.map +1 -0
  166. package/dist/cli/repl-input.js +764 -0
  167. package/dist/cli/repl-input.js.map +1 -0
  168. package/dist/cli/repl.d.ts +5 -0
  169. package/dist/cli/repl.d.ts.map +1 -0
  170. package/dist/cli/repl.js +1046 -0
  171. package/dist/cli/repl.js.map +1 -0
  172. package/dist/cli/ui.d.ts +19 -0
  173. package/dist/cli/ui.d.ts.map +1 -0
  174. package/dist/cli/ui.js +106 -0
  175. package/dist/cli/ui.js.map +1 -0
  176. package/dist/config/loader.d.ts +11 -0
  177. package/dist/config/loader.d.ts.map +1 -0
  178. package/dist/config/loader.js +132 -0
  179. package/dist/config/loader.js.map +1 -0
  180. package/dist/config/paths.d.ts +35 -0
  181. package/dist/config/paths.d.ts.map +1 -0
  182. package/dist/config/paths.js +114 -0
  183. package/dist/config/paths.js.map +1 -0
  184. package/dist/config/schema.d.ts +372 -0
  185. package/dist/config/schema.d.ts.map +1 -0
  186. package/dist/config/schema.js +161 -0
  187. package/dist/config/schema.js.map +1 -0
  188. package/dist/config/xdg.d.ts +2 -0
  189. package/dist/config/xdg.d.ts.map +1 -0
  190. package/dist/config/xdg.js +55 -0
  191. package/dist/config/xdg.js.map +1 -0
  192. package/dist/core/continuity.d.ts +8 -0
  193. package/dist/core/continuity.d.ts.map +1 -0
  194. package/dist/core/continuity.js +36 -0
  195. package/dist/core/continuity.js.map +1 -0
  196. package/dist/core/conversation.d.ts +152 -0
  197. package/dist/core/conversation.d.ts.map +1 -0
  198. package/dist/core/conversation.js +435 -0
  199. package/dist/core/conversation.js.map +1 -0
  200. package/dist/core/estimation.d.ts +19 -0
  201. package/dist/core/estimation.d.ts.map +1 -0
  202. package/dist/core/estimation.js +53 -0
  203. package/dist/core/estimation.js.map +1 -0
  204. package/dist/core/fork.d.ts +7 -0
  205. package/dist/core/fork.d.ts.map +1 -0
  206. package/dist/core/fork.js +93 -0
  207. package/dist/core/fork.js.map +1 -0
  208. package/dist/core/interactive-host.d.ts +28 -0
  209. package/dist/core/interactive-host.d.ts.map +1 -0
  210. package/dist/core/interactive-host.js +19 -0
  211. package/dist/core/interactive-host.js.map +1 -0
  212. package/dist/core/loop-detection.d.ts +25 -0
  213. package/dist/core/loop-detection.d.ts.map +1 -0
  214. package/dist/core/loop-detection.js +37 -0
  215. package/dist/core/loop-detection.js.map +1 -0
  216. package/dist/core/loop.d.ts +15 -0
  217. package/dist/core/loop.d.ts.map +1 -0
  218. package/dist/core/loop.js +417 -0
  219. package/dist/core/loop.js.map +1 -0
  220. package/dist/core/mode-policy.d.ts +33 -0
  221. package/dist/core/mode-policy.d.ts.map +1 -0
  222. package/dist/core/mode-policy.js +62 -0
  223. package/dist/core/mode-policy.js.map +1 -0
  224. package/dist/core/orchestrator.d.ts +14 -0
  225. package/dist/core/orchestrator.d.ts.map +1 -0
  226. package/dist/core/orchestrator.js +69 -0
  227. package/dist/core/orchestrator.js.map +1 -0
  228. package/dist/core/plan-fixer.d.ts +16 -0
  229. package/dist/core/plan-fixer.d.ts.map +1 -0
  230. package/dist/core/plan-fixer.js +55 -0
  231. package/dist/core/plan-fixer.js.map +1 -0
  232. package/dist/core/signals.d.ts +5 -0
  233. package/dist/core/signals.d.ts.map +1 -0
  234. package/dist/core/signals.js +44 -0
  235. package/dist/core/signals.js.map +1 -0
  236. package/dist/core/spec.d.ts +8 -0
  237. package/dist/core/spec.d.ts.map +1 -0
  238. package/dist/core/spec.js +75 -0
  239. package/dist/core/spec.js.map +1 -0
  240. package/dist/core/validation.d.ts +21 -0
  241. package/dist/core/validation.d.ts.map +1 -0
  242. package/dist/core/validation.js +126 -0
  243. package/dist/core/validation.js.map +1 -0
  244. package/dist/daemon/control.d.ts +9 -0
  245. package/dist/daemon/control.d.ts.map +1 -0
  246. package/dist/daemon/control.js +88 -0
  247. package/dist/daemon/control.js.map +1 -0
  248. package/dist/daemon/server.d.ts +8 -0
  249. package/dist/daemon/server.d.ts.map +1 -0
  250. package/dist/daemon/server.js +129 -0
  251. package/dist/daemon/server.js.map +1 -0
  252. package/dist/daemon/updater.d.ts +21 -0
  253. package/dist/daemon/updater.d.ts.map +1 -0
  254. package/dist/daemon/updater.js +159 -0
  255. package/dist/daemon/updater.js.map +1 -0
  256. package/dist/keychain/index.d.ts +8 -0
  257. package/dist/keychain/index.d.ts.map +1 -0
  258. package/dist/keychain/index.js +243 -0
  259. package/dist/keychain/index.js.map +1 -0
  260. package/dist/keychain/windows.d.ts +5 -0
  261. package/dist/keychain/windows.d.ts.map +1 -0
  262. package/dist/keychain/windows.js +65 -0
  263. package/dist/keychain/windows.js.map +1 -0
  264. package/dist/logging/logger.d.ts +12 -0
  265. package/dist/logging/logger.d.ts.map +1 -0
  266. package/dist/logging/logger.js +127 -0
  267. package/dist/logging/logger.js.map +1 -0
  268. package/dist/logging/rotation.d.ts +9 -0
  269. package/dist/logging/rotation.d.ts.map +1 -0
  270. package/dist/logging/rotation.js +85 -0
  271. package/dist/logging/rotation.js.map +1 -0
  272. package/dist/logging/trace.d.ts +7 -0
  273. package/dist/logging/trace.d.ts.map +1 -0
  274. package/dist/logging/trace.js +50 -0
  275. package/dist/logging/trace.js.map +1 -0
  276. package/dist/mcp/client.d.ts +37 -0
  277. package/dist/mcp/client.d.ts.map +1 -0
  278. package/dist/mcp/client.js +111 -0
  279. package/dist/mcp/client.js.map +1 -0
  280. package/dist/mcp/http-transport.d.ts +30 -0
  281. package/dist/mcp/http-transport.d.ts.map +1 -0
  282. package/dist/mcp/http-transport.js +109 -0
  283. package/dist/mcp/http-transport.js.map +1 -0
  284. package/dist/mcp/oauth.d.ts +23 -0
  285. package/dist/mcp/oauth.d.ts.map +1 -0
  286. package/dist/mcp/oauth.js +235 -0
  287. package/dist/mcp/oauth.js.map +1 -0
  288. package/dist/mcp/registry.d.ts +5 -0
  289. package/dist/mcp/registry.d.ts.map +1 -0
  290. package/dist/mcp/registry.js +35 -0
  291. package/dist/mcp/registry.js.map +1 -0
  292. package/dist/memory/cold.d.ts +16 -0
  293. package/dist/memory/cold.d.ts.map +1 -0
  294. package/dist/memory/cold.js +244 -0
  295. package/dist/memory/cold.js.map +1 -0
  296. package/dist/memory/graph.d.ts +19 -0
  297. package/dist/memory/graph.d.ts.map +1 -0
  298. package/dist/memory/graph.js +102 -0
  299. package/dist/memory/graph.js.map +1 -0
  300. package/dist/memory/hot.d.ts +26 -0
  301. package/dist/memory/hot.d.ts.map +1 -0
  302. package/dist/memory/hot.js +58 -0
  303. package/dist/memory/hot.js.map +1 -0
  304. package/dist/memory/index.d.ts +7 -0
  305. package/dist/memory/index.d.ts.map +1 -0
  306. package/dist/memory/index.js +26 -0
  307. package/dist/memory/index.js.map +1 -0
  308. package/dist/memory/learning.d.ts +18 -0
  309. package/dist/memory/learning.d.ts.map +1 -0
  310. package/dist/memory/learning.js +83 -0
  311. package/dist/memory/learning.js.map +1 -0
  312. package/dist/memory/retrieval.d.ts +21 -0
  313. package/dist/memory/retrieval.d.ts.map +1 -0
  314. package/dist/memory/retrieval.js +114 -0
  315. package/dist/memory/retrieval.js.map +1 -0
  316. package/dist/memory/warm.d.ts +9 -0
  317. package/dist/memory/warm.d.ts.map +1 -0
  318. package/dist/memory/warm.js +150 -0
  319. package/dist/memory/warm.js.map +1 -0
  320. package/dist/migrations/runner.d.ts +18 -0
  321. package/dist/migrations/runner.d.ts.map +1 -0
  322. package/dist/migrations/runner.js +62 -0
  323. package/dist/migrations/runner.js.map +1 -0
  324. package/dist/models/adapter.d.ts +46 -0
  325. package/dist/models/adapter.d.ts.map +1 -0
  326. package/dist/models/adapter.js +85 -0
  327. package/dist/models/adapter.js.map +1 -0
  328. package/dist/models/anthropic.d.ts +17 -0
  329. package/dist/models/anthropic.d.ts.map +1 -0
  330. package/dist/models/anthropic.js +128 -0
  331. package/dist/models/anthropic.js.map +1 -0
  332. package/dist/models/cache.d.ts +5 -0
  333. package/dist/models/cache.d.ts.map +1 -0
  334. package/dist/models/cache.js +135 -0
  335. package/dist/models/cache.js.map +1 -0
  336. package/dist/models/circuit-breaker.d.ts +18 -0
  337. package/dist/models/circuit-breaker.d.ts.map +1 -0
  338. package/dist/models/circuit-breaker.js +63 -0
  339. package/dist/models/circuit-breaker.js.map +1 -0
  340. package/dist/models/cost.d.ts +13 -0
  341. package/dist/models/cost.d.ts.map +1 -0
  342. package/dist/models/cost.js +92 -0
  343. package/dist/models/cost.js.map +1 -0
  344. package/dist/models/llamacpp.d.ts +9 -0
  345. package/dist/models/llamacpp.d.ts.map +1 -0
  346. package/dist/models/llamacpp.js +15 -0
  347. package/dist/models/llamacpp.js.map +1 -0
  348. package/dist/models/lmstudio.d.ts +11 -0
  349. package/dist/models/lmstudio.d.ts.map +1 -0
  350. package/dist/models/lmstudio.js +18 -0
  351. package/dist/models/lmstudio.js.map +1 -0
  352. package/dist/models/local-catalog.d.ts +45 -0
  353. package/dist/models/local-catalog.d.ts.map +1 -0
  354. package/dist/models/local-catalog.js +314 -0
  355. package/dist/models/local-catalog.js.map +1 -0
  356. package/dist/models/ollama.d.ts +10 -0
  357. package/dist/models/ollama.d.ts.map +1 -0
  358. package/dist/models/ollama.js +98 -0
  359. package/dist/models/ollama.js.map +1 -0
  360. package/dist/models/openai.d.ts +16 -0
  361. package/dist/models/openai.d.ts.map +1 -0
  362. package/dist/models/openai.js +139 -0
  363. package/dist/models/openai.js.map +1 -0
  364. package/dist/models/provider.d.ts +7 -0
  365. package/dist/models/provider.d.ts.map +1 -0
  366. package/dist/models/provider.js +39 -0
  367. package/dist/models/provider.js.map +1 -0
  368. package/dist/models/rate-limit.d.ts +13 -0
  369. package/dist/models/rate-limit.d.ts.map +1 -0
  370. package/dist/models/rate-limit.js +37 -0
  371. package/dist/models/rate-limit.js.map +1 -0
  372. package/dist/models/registry.d.ts +2 -0
  373. package/dist/models/registry.d.ts.map +1 -0
  374. package/dist/models/registry.js +69 -0
  375. package/dist/models/registry.js.map +1 -0
  376. package/dist/models/router.d.ts +26 -0
  377. package/dist/models/router.d.ts.map +1 -0
  378. package/dist/models/router.js +185 -0
  379. package/dist/models/router.js.map +1 -0
  380. package/dist/models/vllm.d.ts +13 -0
  381. package/dist/models/vllm.d.ts.map +1 -0
  382. package/dist/models/vllm.js +19 -0
  383. package/dist/models/vllm.js.map +1 -0
  384. package/dist/notifications/manager.d.ts +5 -0
  385. package/dist/notifications/manager.d.ts.map +1 -0
  386. package/dist/notifications/manager.js +65 -0
  387. package/dist/notifications/manager.js.map +1 -0
  388. package/dist/permissions/manager.d.ts +15 -0
  389. package/dist/permissions/manager.d.ts.map +1 -0
  390. package/dist/permissions/manager.js +159 -0
  391. package/dist/permissions/manager.js.map +1 -0
  392. package/dist/permissions/risk.d.ts +13 -0
  393. package/dist/permissions/risk.d.ts.map +1 -0
  394. package/dist/permissions/risk.js +43 -0
  395. package/dist/permissions/risk.js.map +1 -0
  396. package/dist/persistence/compression.d.ts +9 -0
  397. package/dist/persistence/compression.d.ts.map +1 -0
  398. package/dist/persistence/compression.js +126 -0
  399. package/dist/persistence/compression.js.map +1 -0
  400. package/dist/persistence/conversation-store.d.ts +67 -0
  401. package/dist/persistence/conversation-store.d.ts.map +1 -0
  402. package/dist/persistence/conversation-store.js +370 -0
  403. package/dist/persistence/conversation-store.js.map +1 -0
  404. package/dist/persistence/events.d.ts +4 -0
  405. package/dist/persistence/events.d.ts.map +1 -0
  406. package/dist/persistence/events.js +50 -0
  407. package/dist/persistence/events.js.map +1 -0
  408. package/dist/persistence/index-db.d.ts +65 -0
  409. package/dist/persistence/index-db.d.ts.map +1 -0
  410. package/dist/persistence/index-db.js +280 -0
  411. package/dist/persistence/index-db.js.map +1 -0
  412. package/dist/persistence/jsonl.d.ts +8 -0
  413. package/dist/persistence/jsonl.d.ts.map +1 -0
  414. package/dist/persistence/jsonl.js +90 -0
  415. package/dist/persistence/jsonl.js.map +1 -0
  416. package/dist/persistence/sessions.d.ts +5 -0
  417. package/dist/persistence/sessions.d.ts.map +1 -0
  418. package/dist/persistence/sessions.js +54 -0
  419. package/dist/persistence/sessions.js.map +1 -0
  420. package/dist/persistence/tasks.d.ts +7 -0
  421. package/dist/persistence/tasks.d.ts.map +1 -0
  422. package/dist/persistence/tasks.js +162 -0
  423. package/dist/persistence/tasks.js.map +1 -0
  424. package/dist/prompts/assembler.d.ts +29 -0
  425. package/dist/prompts/assembler.d.ts.map +1 -0
  426. package/dist/prompts/assembler.js +136 -0
  427. package/dist/prompts/assembler.js.map +1 -0
  428. package/dist/prompts/layers.d.ts +6 -0
  429. package/dist/prompts/layers.d.ts.map +1 -0
  430. package/dist/prompts/layers.js +60 -0
  431. package/dist/prompts/layers.js.map +1 -0
  432. package/dist/release/download.d.ts +19 -0
  433. package/dist/release/download.d.ts.map +1 -0
  434. package/dist/release/download.js +187 -0
  435. package/dist/release/download.js.map +1 -0
  436. package/dist/release/verify.d.ts +34 -0
  437. package/dist/release/verify.d.ts.map +1 -0
  438. package/dist/release/verify.js +127 -0
  439. package/dist/release/verify.js.map +1 -0
  440. package/dist/sandbox/fs.d.ts +10 -0
  441. package/dist/sandbox/fs.d.ts.map +1 -0
  442. package/dist/sandbox/fs.js +114 -0
  443. package/dist/sandbox/fs.js.map +1 -0
  444. package/dist/sandbox/shell.d.ts +20 -0
  445. package/dist/sandbox/shell.d.ts.map +1 -0
  446. package/dist/sandbox/shell.js +131 -0
  447. package/dist/sandbox/shell.js.map +1 -0
  448. package/dist/scheduler/dag.d.ts +7 -0
  449. package/dist/scheduler/dag.d.ts.map +1 -0
  450. package/dist/scheduler/dag.js +72 -0
  451. package/dist/scheduler/dag.js.map +1 -0
  452. package/dist/scheduler/resource-manager.d.ts +25 -0
  453. package/dist/scheduler/resource-manager.d.ts.map +1 -0
  454. package/dist/scheduler/resource-manager.js +101 -0
  455. package/dist/scheduler/resource-manager.js.map +1 -0
  456. package/dist/security/injection.d.ts +14 -0
  457. package/dist/security/injection.d.ts.map +1 -0
  458. package/dist/security/injection.js +46 -0
  459. package/dist/security/injection.js.map +1 -0
  460. package/dist/security/redact.d.ts +10 -0
  461. package/dist/security/redact.d.ts.map +1 -0
  462. package/dist/security/redact.js +89 -0
  463. package/dist/security/redact.js.map +1 -0
  464. package/dist/skills/loader.d.ts +4 -0
  465. package/dist/skills/loader.d.ts.map +1 -0
  466. package/dist/skills/loader.js +142 -0
  467. package/dist/skills/loader.js.map +1 -0
  468. package/dist/skills/marketplace.d.ts +15 -0
  469. package/dist/skills/marketplace.d.ts.map +1 -0
  470. package/dist/skills/marketplace.js +132 -0
  471. package/dist/skills/marketplace.js.map +1 -0
  472. package/dist/tools/apply-patch.d.ts +20 -0
  473. package/dist/tools/apply-patch.d.ts.map +1 -0
  474. package/dist/tools/apply-patch.js +195 -0
  475. package/dist/tools/apply-patch.js.map +1 -0
  476. package/dist/tools/ask-user.d.ts +12 -0
  477. package/dist/tools/ask-user.d.ts.map +1 -0
  478. package/dist/tools/ask-user.js +86 -0
  479. package/dist/tools/ask-user.js.map +1 -0
  480. package/dist/tools/delete-file.d.ts +10 -0
  481. package/dist/tools/delete-file.d.ts.map +1 -0
  482. package/dist/tools/delete-file.js +94 -0
  483. package/dist/tools/delete-file.js.map +1 -0
  484. package/dist/tools/edit-file.d.ts +20 -0
  485. package/dist/tools/edit-file.d.ts.map +1 -0
  486. package/dist/tools/edit-file.js +128 -0
  487. package/dist/tools/edit-file.js.map +1 -0
  488. package/dist/tools/format.d.ts +5 -0
  489. package/dist/tools/format.d.ts.map +1 -0
  490. package/dist/tools/format.js +131 -0
  491. package/dist/tools/format.js.map +1 -0
  492. package/dist/tools/git.d.ts +24 -0
  493. package/dist/tools/git.d.ts.map +1 -0
  494. package/dist/tools/git.js +122 -0
  495. package/dist/tools/git.js.map +1 -0
  496. package/dist/tools/glob.d.ts +12 -0
  497. package/dist/tools/glob.d.ts.map +1 -0
  498. package/dist/tools/glob.js +55 -0
  499. package/dist/tools/glob.js.map +1 -0
  500. package/dist/tools/grep.d.ts +19 -0
  501. package/dist/tools/grep.d.ts.map +1 -0
  502. package/dist/tools/grep.js +97 -0
  503. package/dist/tools/grep.js.map +1 -0
  504. package/dist/tools/init.d.ts +3 -0
  505. package/dist/tools/init.d.ts.map +1 -0
  506. package/dist/tools/init.js +66 -0
  507. package/dist/tools/init.js.map +1 -0
  508. package/dist/tools/list-dir.d.ts +16 -0
  509. package/dist/tools/list-dir.d.ts.map +1 -0
  510. package/dist/tools/list-dir.js +107 -0
  511. package/dist/tools/list-dir.js.map +1 -0
  512. package/dist/tools/move-file.d.ts +13 -0
  513. package/dist/tools/move-file.d.ts.map +1 -0
  514. package/dist/tools/move-file.js +100 -0
  515. package/dist/tools/move-file.js.map +1 -0
  516. package/dist/tools/read-file.d.ts +14 -0
  517. package/dist/tools/read-file.d.ts.map +1 -0
  518. package/dist/tools/read-file.js +99 -0
  519. package/dist/tools/read-file.js.map +1 -0
  520. package/dist/tools/registry.d.ts +10 -0
  521. package/dist/tools/registry.d.ts.map +1 -0
  522. package/dist/tools/registry.js +30 -0
  523. package/dist/tools/registry.js.map +1 -0
  524. package/dist/tools/run-command.d.ts +17 -0
  525. package/dist/tools/run-command.d.ts.map +1 -0
  526. package/dist/tools/run-command.js +73 -0
  527. package/dist/tools/run-command.js.map +1 -0
  528. package/dist/tools/run-tests.d.ts +16 -0
  529. package/dist/tools/run-tests.d.ts.map +1 -0
  530. package/dist/tools/run-tests.js +140 -0
  531. package/dist/tools/run-tests.js.map +1 -0
  532. package/dist/tools/web-browse.d.ts +10 -0
  533. package/dist/tools/web-browse.d.ts.map +1 -0
  534. package/dist/tools/web-browse.js +45 -0
  535. package/dist/tools/web-browse.js.map +1 -0
  536. package/dist/tools/web-fetch.d.ts +11 -0
  537. package/dist/tools/web-fetch.d.ts.map +1 -0
  538. package/dist/tools/web-fetch.js +43 -0
  539. package/dist/tools/web-fetch.js.map +1 -0
  540. package/dist/tools/web-search.d.ts +12 -0
  541. package/dist/tools/web-search.d.ts.map +1 -0
  542. package/dist/tools/web-search.js +52 -0
  543. package/dist/tools/web-search.js.map +1 -0
  544. package/dist/tools/write-file.d.ts +13 -0
  545. package/dist/tools/write-file.d.ts.map +1 -0
  546. package/dist/tools/write-file.js +100 -0
  547. package/dist/tools/write-file.js.map +1 -0
  548. package/dist/types/errors.d.ts +14 -0
  549. package/dist/types/errors.d.ts.map +1 -0
  550. package/dist/types/errors.js +55 -0
  551. package/dist/types/errors.js.map +1 -0
  552. package/dist/types/index.d.ts +267 -0
  553. package/dist/types/index.d.ts.map +1 -0
  554. package/dist/types/index.js +38 -0
  555. package/dist/types/index.js.map +1 -0
  556. package/dist/ui/chat.d.ts +89 -0
  557. package/dist/ui/chat.d.ts.map +1 -0
  558. package/dist/ui/chat.js +311 -0
  559. package/dist/ui/chat.js.map +1 -0
  560. package/dist/ui/public/app.js +2113 -0
  561. package/dist/ui/public/index.html +78 -0
  562. package/dist/ui/public/styles.css +1703 -0
  563. package/dist/ui/server-errors.d.ts +24 -0
  564. package/dist/ui/server-errors.d.ts.map +1 -0
  565. package/dist/ui/server-errors.js +31 -0
  566. package/dist/ui/server-errors.js.map +1 -0
  567. package/dist/ui/server.d.ts +10 -0
  568. package/dist/ui/server.d.ts.map +1 -0
  569. package/dist/ui/server.js +815 -0
  570. package/dist/ui/server.js.map +1 -0
  571. package/dist/ui/task-runner.d.ts +71 -0
  572. package/dist/ui/task-runner.d.ts.map +1 -0
  573. package/dist/ui/task-runner.js +334 -0
  574. package/dist/ui/task-runner.js.map +1 -0
  575. package/dist/web/browse.d.ts +35 -0
  576. package/dist/web/browse.d.ts.map +1 -0
  577. package/dist/web/browse.js +166 -0
  578. package/dist/web/browse.js.map +1 -0
  579. package/dist/web/fetch.d.ts +18 -0
  580. package/dist/web/fetch.d.ts.map +1 -0
  581. package/dist/web/fetch.js +107 -0
  582. package/dist/web/fetch.js.map +1 -0
  583. package/dist/web/sanitize.d.ts +8 -0
  584. package/dist/web/sanitize.d.ts.map +1 -0
  585. package/dist/web/sanitize.js +58 -0
  586. package/dist/web/sanitize.js.map +1 -0
  587. package/dist/web/search.d.ts +12 -0
  588. package/dist/web/search.d.ts.map +1 -0
  589. package/dist/web/search.js +124 -0
  590. package/dist/web/search.js.map +1 -0
  591. package/install/install.ps1 +46 -0
  592. package/install/install.sh +72 -0
  593. package/package.json +89 -0
  594. package/scripts/bundle.js +26 -0
  595. package/scripts/copy-assets.js +33 -0
  596. package/scripts/link.sh +79 -0
  597. package/scripts/metrics.sh +33 -0
  598. package/scripts/postinstall.js +36 -0
package/README.md ADDED
@@ -0,0 +1,919 @@
1
+ <!-- Comprehensive README. Numbers sourced from docs/metrics.json; regenerate with `bash scripts/metrics.sh`. -->
2
+
3
+ <div align="center">
4
+
5
+ # Forge
6
+
7
+ **A local-first, multi-agent, programmable software-engineering runtime.**
8
+
9
+ *Not an assistant. A runtime.* Forge brings its own scheduler, sandbox,
10
+ permission system, state machine, agentic loop, memory layers, and
11
+ plugin ecosystem. You pick the model. You approve the actions. Everything
12
+ is inspectable, replayable, and yours.
13
+
14
+ **[Install](docs/INSTALL.md) · [Dev setup](docs/SETUP.md) · [Architecture](docs/ARCHITECTURE.md) · [Wiki Page](index.html) · [License](LICENSE)**
15
+
16
+ </div>
17
+
18
+ ---
19
+
20
+ ## Table of contents
21
+
22
+ 1. [At a glance](#at-a-glance)
23
+ 2. [Why Forge](#why-forge)
24
+ 3. [Quick start](#quick-start)
25
+ 4. [The agentic loop (with diagrams)](#the-agentic-loop)
26
+ 5. [Task state machine](#task-state-machine)
27
+ 6. [Executor — iterative tool-use loop](#executor--iterative-tool-use-loop)
28
+ 7. [Memory layers](#memory-layers)
29
+ 8. [Provider routing & auto-adaptation](#provider-routing--auto-adaptation)
30
+ 9. [Safety model](#safety-model-not-optional)
31
+ 10. [Modes](#modes)
32
+ 11. [CLI reference](#cli-reference)
33
+ 12. [Filesystem layout](#filesystem-layout)
34
+ 13. [Skills · Instructions · MCP](#skills--instructions--mcp)
35
+ 14. [Run in a container](#run-in-a-container-docker-or-podman)
36
+ 15. [CI/CD pipeline](#cicd-pipeline)
37
+ 16. [Architecture map](#architecture-map)
38
+ 17. [Development](#development)
39
+ 18. [License](#license)
40
+
41
+ ---
42
+
43
+ ## At a glance
44
+
45
+ Forge is a local-first, multi-agent, programmable software-engineering runtime. Unlike Claude Code or OpenAI Codex, Forge is local-first infrastructure, not a hosted assistant. It brings its own scheduler, sandbox, permission system, state machine, agentic loop, memory layers, and plugin ecosystem. You pick & host the model. You approve the actions. Everything is inspectable, replayable, and yours.
46
+
47
+ <div align="center">
48
+
49
+ | | value | reproducer |
50
+ |---|---|---|
51
+ | ⚡ **`forge doctor` cold-start** | **173 ms** | `time node bin/forge.js doctor --no-banner` |
52
+ | ⚡ **`forge --help` cold-start** | **238 ms** | `time node bin/forge.js --help` |
53
+ | 📦 **UI shell · zero CDN** | **89 KB** uncompressed | `wc -c src/ui/public/app.js` |
54
+ | 🌐 **Provider probe timeout** | **1.5 s** | `src/models/openai.ts#isAvailable` |
55
+ | 🔌 **Model providers** (auto-detected) | **6** | ollama · lmstudio · vllm · llama.cpp · openai-compat · anthropic |
56
+ | 🧠 **Model families** classified | **41** | Llama / Qwen / DeepSeek / Gemma / Phi / Mistral / Codestral / … |
57
+ | 🤖 **Built-in agents** | **6** | planner · architect · executor · reviewer · debugger · memory |
58
+ | 🛠 **Tools** available to agents | **18** | read · write · edit · grep · glob · run_command · git · web · … |
59
+ | 💬 **CLI subcommands · slash commands** | **24 · 55** | `forge --help` · `/help` in REPL |
60
+ | 🎛 **Modes** | **9** | fast · balanced · heavy · plan · execute · audit · debug · architect · offline-safe |
61
+ | ✅ **Tests** | **249 / 43 files** · 100% passing · ~3.3 s wall-clock | `npx vitest run` |
62
+ | 🐳 **CI jobs · release stages** | **9 · 6** | [`.github/workflows/`](.github/workflows) |
63
+ | 📦 **Container image** | ~355 MB · multi-arch · non-root · HEALTHCHECK | `docker pull ghcr.io/hoangsonw/forge-agentic-coding-cli:latest` |
64
+
65
+ </div>
66
+
67
+ **Tech Stack:**
68
+
69
+ ![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?style=for-the-badge&logo=typescript&logoColor=white)
70
+ ![Node.js](https://img.shields.io/badge/Node.js%2020+-339933?style=for-the-badge&logo=node.js&logoColor=white)
71
+ ![JavaScript](https://img.shields.io/badge/JavaScript-F7DF1E?style=for-the-badge&logo=javascript&logoColor=black)
72
+ ![HTML5](https://img.shields.io/badge/HTML5-E34F26?style=for-the-badge&logo=html5&logoColor=white)
73
+ ![CSS3](https://img.shields.io/badge/CSS3-1572B6?style=for-the-badge&logo=css3&logoColor=white)
74
+ ![Bash](https://img.shields.io/badge/Bash-4EAA25?style=for-the-badge&logo=gnubash&logoColor=white)
75
+ ![YAML](https://img.shields.io/badge/YAML-CB171E?style=for-the-badge&logo=yaml&logoColor=white)
76
+ ![JSON](https://img.shields.io/badge/JSON-000000?style=for-the-badge&logo=json&logoColor=white)
77
+ ![Markdown](https://img.shields.io/badge/Markdown-000000?style=for-the-badge&logo=markdown&logoColor=white)
78
+ ![Mermaid](https://img.shields.io/badge/Mermaid-FF3670?style=for-the-badge&logo=mermaid&logoColor=white)
79
+ ![SVG](https://img.shields.io/badge/SVG-FFB13B?style=for-the-badge&logo=svg&logoColor=black)
80
+ ![npm](https://img.shields.io/badge/npm-CB3837?style=for-the-badge&logo=npm&logoColor=white)
81
+ ![Vitest](https://img.shields.io/badge/Vitest-6E9F18?style=for-the-badge&logo=vitest&logoColor=white)
82
+ ![ESLint](https://img.shields.io/badge/ESLint-4B32C3?style=for-the-badge&logo=eslint&logoColor=white)
83
+ ![Prettier](https://img.shields.io/badge/Prettier-F7B93E?style=for-the-badge&logo=prettier&logoColor=black)
84
+ ![ts-node](https://img.shields.io/badge/ts--node-3178C6?style=for-the-badge&logo=tsnode&logoColor=white)
85
+ ![Commander](https://img.shields.io/badge/Commander.js-333?style=for-the-badge)
86
+ ![Zod](https://img.shields.io/badge/Zod-3068B7?style=for-the-badge&logo=zod&logoColor=white)
87
+ ![Chalk](https://img.shields.io/badge/Chalk-FF6B6B?style=for-the-badge)
88
+ ![Ora](https://img.shields.io/badge/Ora-55ACEE?style=for-the-badge)
89
+ ![Prompts](https://img.shields.io/badge/Prompts-9b59b6?style=for-the-badge)
90
+ ![Undici](https://img.shields.io/badge/undici-1f6feb?style=for-the-badge)
91
+ ![ws](https://img.shields.io/badge/ws-010101?style=for-the-badge&logo=socket.io&logoColor=white)
92
+ ![dotenv](https://img.shields.io/badge/dotenv-ECD53F?style=for-the-badge&logo=dotenv&logoColor=black)
93
+ ![semver](https://img.shields.io/badge/semver-CB3837?style=for-the-badge)
94
+ ![SQLite](https://img.shields.io/badge/SQLite-003B57?style=for-the-badge&logo=sqlite&logoColor=white)
95
+ ![better-sqlite3](https://img.shields.io/badge/better--sqlite3-044a64?style=for-the-badge)
96
+ ![FTS5](https://img.shields.io/badge/SQLite%20FTS5-003B57?style=for-the-badge&logo=sqlite&logoColor=white)
97
+ ![JSONL](https://img.shields.io/badge/JSONL-000?style=for-the-badge)
98
+ ![WebSockets](https://img.shields.io/badge/WebSockets-010101?style=for-the-badge&logo=socket.io&logoColor=white)
99
+ ![REST](https://img.shields.io/badge/REST-25A162?style=for-the-badge)
100
+ ![HTTP](https://img.shields.io/badge/HTTP%2F2-005cc5?style=for-the-badge)
101
+ ![POSIX](https://img.shields.io/badge/POSIX-3776AB?style=for-the-badge)
102
+ ![XDG](https://img.shields.io/badge/XDG%20Base%20Dir-5E2BFF?style=for-the-badge)
103
+ ![MCP](https://img.shields.io/badge/Model%20Context%20Protocol-444?style=for-the-badge)
104
+ ![OAuth2](https://img.shields.io/badge/OAuth%202.0%20%2B%20PKCE-0e8a16?style=for-the-badge&logo=auth0&logoColor=white)
105
+ ![Ed25519](https://img.shields.io/badge/Ed25519-7C3AED?style=for-the-badge)
106
+ ![SHA-256](https://img.shields.io/badge/SHA--256-444?style=for-the-badge)
107
+ ![AES-GCM](https://img.shields.io/badge/AES--GCM-004E8C?style=for-the-badge)
108
+ ![DPAPI](https://img.shields.io/badge/DPAPI-0078D4?style=for-the-badge&logo=windows&logoColor=white)
109
+ ![libsecret](https://img.shields.io/badge/libsecret-4A90E2?style=for-the-badge)
110
+ ![macOS Keychain](https://img.shields.io/badge/macOS%20Keychain-000?style=for-the-badge&logo=apple&logoColor=white)
111
+ ![Docker](https://img.shields.io/badge/Docker-2496ED?style=for-the-badge&logo=docker&logoColor=white)
112
+ ![Compose](https://img.shields.io/badge/Docker%20Compose-2496ED?style=for-the-badge&logo=docker&logoColor=white)
113
+ ![Podman](https://img.shields.io/badge/Podman-892CA0?style=for-the-badge&logo=podman&logoColor=white)
114
+ ![Buildx](https://img.shields.io/badge/Buildx-2496ED?style=for-the-badge&logo=docker&logoColor=white)
115
+ ![QEMU](https://img.shields.io/badge/QEMU-FF6600?style=for-the-badge&logo=qemu&logoColor=white)
116
+ ![tini](https://img.shields.io/badge/tini-444?style=for-the-badge)
117
+ ![OCI](https://img.shields.io/badge/OCI%20Image-262261?style=for-the-badge)
118
+ ![ripgrep](https://img.shields.io/badge/ripgrep-333?style=for-the-badge)
119
+ ![GitHub Actions](https://img.shields.io/badge/GitHub%20Actions-2088FF?style=for-the-badge&logo=githubactions&logoColor=white)
120
+ ![GHCR](https://img.shields.io/badge/GHCR-181717?style=for-the-badge&logo=github&logoColor=white)
121
+ ![npm Provenance](https://img.shields.io/badge/npm%20Provenance-CB3837?style=for-the-badge&logo=npm&logoColor=white)
122
+ ![Sigstore](https://img.shields.io/badge/Sigstore-2B3A67?style=for-the-badge)
123
+ ![Dependabot](https://img.shields.io/badge/Dependabot-025E8C?style=for-the-badge&logo=dependabot&logoColor=white)
124
+ ![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-FA6673?style=for-the-badge&logo=conventionalcommits&logoColor=white)
125
+ ![SemVer](https://img.shields.io/badge/SemVer-3F4551?style=for-the-badge&logo=semver&logoColor=white)
126
+ ![Ollama](https://img.shields.io/badge/Ollama-000000?style=for-the-badge&logo=ollama&logoColor=white)
127
+ ![LM Studio](https://img.shields.io/badge/LM%20Studio-4A90E2?style=for-the-badge&logoColor=white)
128
+ ![vLLM](https://img.shields.io/badge/vLLM-FA5C00?style=for-the-badge&logoColor=white)
129
+ ![llama.cpp](https://img.shields.io/badge/llama.cpp-FFCE00?style=for-the-badge&logoColor=black)
130
+ ![Anthropic](https://img.shields.io/badge/Anthropic-D4A27F?style=for-the-badge&logo=anthropic&logoColor=black)
131
+ ![OpenAI](https://img.shields.io/badge/OpenAI--compat-412991?style=for-the-badge&logo=openai&logoColor=white)
132
+ ![Azure OpenAI](https://img.shields.io/badge/Azure%20OpenAI-0078D4?style=for-the-badge&logo=microsoftazure&logoColor=white)
133
+ ![Groq](https://img.shields.io/badge/Groq-F55036?style=for-the-badge)
134
+ ![Together AI](https://img.shields.io/badge/Together%20AI-0F6FFF?style=for-the-badge)
135
+ ![LocalAI](https://img.shields.io/badge/LocalAI-2a9d8f?style=for-the-badge)
136
+ ![Fireworks](https://img.shields.io/badge/Fireworks-6B2CE7?style=for-the-badge)
137
+ ![Llama](https://img.shields.io/badge/Llama-0467DF?style=for-the-badge&logo=meta&logoColor=white)
138
+ ![Qwen](https://img.shields.io/badge/Qwen-615CED?style=for-the-badge&logo=alibabacloud&logoColor=white)
139
+ ![DeepSeek](https://img.shields.io/badge/DeepSeek-1E40AF?style=for-the-badge)
140
+ ![Gemma](https://img.shields.io/badge/Gemma-4285F4?style=for-the-badge&logo=google&logoColor=white)
141
+ ![Phi](https://img.shields.io/badge/Phi-00A4EF?style=for-the-badge&logo=microsoft&logoColor=white)
142
+ ![Mistral](https://img.shields.io/badge/Mistral-FF7000?style=for-the-badge&logo=mistralai&logoColor=white)
143
+ ![Codestral](https://img.shields.io/badge/Codestral-FF7000?style=for-the-badge)
144
+ ![CodeLlama](https://img.shields.io/badge/CodeLlama-0467DF?style=for-the-badge&logo=meta&logoColor=white)
145
+ ![StarCoder](https://img.shields.io/badge/StarCoder-FFD21E?style=for-the-badge&logo=huggingface&logoColor=black)
146
+ ![Granite](https://img.shields.io/badge/Granite-054ADA?style=for-the-badge&logo=ibm&logoColor=white)
147
+ ![Command R](https://img.shields.io/badge/Command%20R+-39594D?style=for-the-badge&logo=cohere&logoColor=white)
148
+ ![macOS](https://img.shields.io/badge/macOS-000?style=for-the-badge&logo=apple&logoColor=white)
149
+ ![Linux](https://img.shields.io/badge/Linux-FCC624?style=for-the-badge&logo=linux&logoColor=black)
150
+ ![Windows](https://img.shields.io/badge/Windows-0078D6?style=for-the-badge&logo=windows&logoColor=white)
151
+ ![WSL2](https://img.shields.io/badge/WSL2-0078D4?style=for-the-badge&logo=windows&logoColor=white)
152
+ ![linux/amd64](https://img.shields.io/badge/linux%2Famd64-444?style=for-the-badge)
153
+ ![linux/arm64](https://img.shields.io/badge/linux%2Farm64-444?style=for-the-badge)
154
+ ![Git](https://img.shields.io/badge/Git-F05032?style=for-the-badge&logo=git&logoColor=white)
155
+ ![GitHub](https://img.shields.io/badge/GitHub-181717?style=for-the-badge&logo=github&logoColor=white)
156
+ ![VS Code](https://img.shields.io/badge/VS%20Code-007ACC?style=for-the-badge&logo=visualstudiocode&logoColor=white)
157
+ ![EditorConfig](https://img.shields.io/badge/EditorConfig-E0EFEF?style=for-the-badge&logo=editorconfig&logoColor=000)
158
+
159
+ ---
160
+
161
+ ## Why Forge
162
+
163
+ Most "AI coding tools" are thin chat wrappers over a cloud API. Forge is
164
+ **engineering infrastructure** with first-class:
165
+
166
+ ```mermaid
167
+ mindmap
168
+ root((Forge))
169
+ Local-first
170
+ Auto-detect Ollama / LM Studio / vLLM / llama.cpp
171
+ Model-family auto-adapt
172
+ Offline-safe mode
173
+ Agentic
174
+ 6 role-typed agents
175
+ Iterative tool-use executor
176
+ Validation gate (typecheck/lint)
177
+ Bounded retries + diagnose
178
+ Controllable
179
+ Default-deny permissions
180
+ Path-realpath-confined sandbox
181
+ Risk-classified shell
182
+ OS-keychain credentials
183
+ Inspectable
184
+ Tasks JSON · Sessions JSONL · Events JSONL
185
+ Prompt-hashed, replayable
186
+ Concurrent-writer-safe
187
+ Extensible
188
+ Markdown skills
189
+ MCP connectors
190
+ Pluggable agents + tools
191
+ Performant
192
+ REPL cold-start 238 ms
193
+ UI shell 89 KB · zero CDN
194
+ Providers probe in 1.5 s
195
+ ```
196
+
197
+ - **Local-first.** Forge auto-detects Ollama, LM Studio, vLLM, and
198
+ llama.cpp on their default ports. Cloud (Anthropic / OpenAI / LocalAI /
199
+ Together / Groq / Azure) is opt-in, not required.
200
+ - **Agentic but controllable.** Every action is classified (risk ×
201
+ side-effect × sensitivity), gated by a permission system, and logged
202
+ with a reproducible prompt hash.
203
+ - **Inspectable.** Sessions JSONL, tasks JSON, events JSONL. Two processes
204
+ can edit the same conversation concurrently (POSIX `O_APPEND` +
205
+ `mkdir` lockfile).
206
+ - **Mode-driven.** 9 explicit modes — each carries **enforceable**
207
+ budgets (max executor turns, max validation retries, allowMutations,
208
+ maxAutoRisk).
209
+ - **Extensible.** Drop a Markdown file in `~/.forge/skills/`. Add an
210
+ `Agent`. Wire an MCP connector. No rebuild required.
211
+ - **Performant.** `forge doctor` cold-starts in 173 ms. The UI shell is a
212
+ single 89 KB JavaScript file with zero CDN dependencies. Providers are
213
+ probed in parallel with a 1.5 s timeout.
214
+ - **Open source.** MIT license. No telemetry, no phoning home, no hidden
215
+ backdoors. You get the whole stack. Unlike hosted assistants, Forge is fully inspectable, replayable, and yours.
216
+
217
+ > [!TIP]
218
+ > Unlike Claude Code or OpenAI Codex, Forge is not a hosted assistant. It's local-first infrastructure. You pick & host the model. You approve the actions. Everything is inspectable, replayable, and yours.
219
+
220
+ ---
221
+
222
+ ## Quick start
223
+
224
+ ```bash
225
+ # Option 1 — npm (global):
226
+ npm install -g @hoangsonw/forge
227
+ forge doctor # green checks + role→model mapping
228
+ forge run "explain this repo"
229
+
230
+ # Option 2 — Docker:
231
+ docker run --rm -it \
232
+ -v forge-home:/data -v "$PWD:/workspace" \
233
+ ghcr.io/hoangsonw/forge-agentic-coding-cli:latest forge run "explain this repo"
234
+
235
+ # Option 3 — full stack (forge + ollama + dashboard):
236
+ docker compose -f docker/docker-compose.yml up -d
237
+ # open http://127.0.0.1:7823
238
+ ```
239
+
240
+ **Requirements:** Node ≥ 20 *and/or* Docker ≥ 25. At least one LLM source
241
+ (local runtime or API key). See [`docs/INSTALL.md`](docs/INSTALL.md) for
242
+ per-OS notes.
243
+
244
+ ---
245
+
246
+ ## The agentic loop
247
+
248
+ Every non-trivial task flows through the same pipeline. Nothing escapes
249
+ it — no hidden shortcut, no "just this once" bypass.
250
+
251
+ ```mermaid
252
+ flowchart LR
253
+ classDef step fill:#0f172a,stroke:#38bdf8,color:#f1f5f9,rx:4,ry:4
254
+ classDef gate fill:#1e1b4b,stroke:#a78bfa,color:#ede9fe,rx:4,ry:4
255
+ classDef term fill:#14532d,stroke:#10b981,color:#d1fae5,rx:4,ry:4
256
+ classDef fail fill:#450a0a,stroke:#f87171,color:#fee2e2,rx:4,ry:4
257
+
258
+ IN([user prompt]):::step --> CLASSIFY[classify]:::step
259
+ CLASSIFY --> PLAN[plan · DAG]:::step
260
+ PLAN --> VALID{valid plan?}:::gate
261
+ VALID -->|no| FIX[auto-fix]:::step --> VALID
262
+ VALID -->|yes| APPROVE{user approves?}:::gate
263
+ APPROVE -->|edit| PLAN
264
+ APPROVE -->|cancel| CANCEL([cancelled]):::fail
265
+ APPROVE -->|yes| EXEC[execute]:::step
266
+ EXEC --> STEP[next step]:::step
267
+ STEP --> TOOLS[iterative tool use]:::step
268
+ TOOLS --> VGATE{validation gate?}:::gate
269
+ VGATE -->|fail + budget| TOOLS
270
+ VGATE -->|fail + exhausted| RETRY{retries?}:::gate
271
+ VGATE -->|ok| DONE{more steps?}:::gate
272
+ RETRY -->|yes| STEP
273
+ RETRY -->|no| DIAG[diagnose]:::step --> FAIL([failed]):::fail
274
+ DONE -->|yes| STEP
275
+ DONE -->|no| VERIFY[reviewer]:::step
276
+ VERIFY --> VSUM{approves?}:::gate
277
+ VSUM -->|no| STEP
278
+ VSUM -->|yes| COMP([completed]):::term
279
+ ```
280
+
281
+ Source: [`src/core/loop.ts`](src/core/loop.ts). Retry cap is 3, then the
282
+ debugger agent diagnoses before the task is marked `failed`.
283
+
284
+ ### A concrete run
285
+
286
+ ```
287
+ forge run "fix the failing login test" --mode heavy
288
+ → classified: bugfix · complexity=moderate · risk=low
289
+ → plan: 4 steps (analyze → locate → patch → run_tests)
290
+ → approve? [y/n/edit]
291
+ → executor: turn 1 — read_file src/auth/login.ts
292
+ turn 2 — grep "issuedAt" in src
293
+ turn 3 — apply_patch src/auth/login.ts
294
+ turn 4 — run_command "npm test -- auth.login"
295
+ → validate: typecheck ✓ lint ✓
296
+ → reviewer: approved
297
+ → ✔ Done. Files changed: src/auth/login.ts
298
+ ```
299
+
300
+ ---
301
+
302
+ ## Task state machine
303
+
304
+ Every task lives in exactly one of **10 statuses**. Transitions are
305
+ enforced by `LEGAL_TRANSITIONS` — illegal moves throw `state_invalid`
306
+ with the legal-next list in `recoveryHint`.
307
+
308
+ ```mermaid
309
+ stateDiagram-v2
310
+ [*] --> draft
311
+ draft --> planned: planner output
312
+ draft --> cancelled
313
+
314
+ planned --> approved: user approves
315
+ planned --> cancelled
316
+ planned --> blocked
317
+
318
+ approved --> scheduled
319
+ approved --> cancelled
320
+
321
+ scheduled --> running
322
+ scheduled --> cancelled
323
+ scheduled --> blocked
324
+
325
+ running --> verifying
326
+ running --> failed
327
+ running --> blocked
328
+ running --> cancelled
329
+
330
+ verifying --> completed
331
+ verifying --> failed
332
+ verifying --> running: reviewer bounces
333
+
334
+ completed --> draft: forge resume
335
+ failed --> draft: forge resume
336
+ blocked --> draft: forge resume
337
+ blocked --> cancelled
338
+ cancelled --> draft: forge resume
339
+
340
+ completed --> [*]
341
+ failed --> [*]
342
+ cancelled --> [*]
343
+ ```
344
+
345
+ Source: [`src/persistence/tasks.ts#LEGAL_TRANSITIONS`](src/persistence/tasks.ts).
346
+
347
+ ---
348
+
349
+ ## Executor — iterative tool-use loop
350
+
351
+ Each plan step runs a **bounded model↔tool conversation**, not a one-shot
352
+ call. The model sees every tool result and can adapt within the same
353
+ step — retry with different args, switch tools, or signal done.
354
+
355
+ ```mermaid
356
+ sequenceDiagram
357
+ autonumber
358
+ participant L as loop.ts
359
+ participant E as executor.ts
360
+ participant M as model
361
+ participant T as tool
362
+ participant V as validator
363
+
364
+ L->>E: runStep(step)
365
+ loop up to maxExecutorTurns (mode-capped)
366
+ E->>M: prompt + schema (JSON-mode)
367
+ M-->>E: { actions[], summary, done? }
368
+ alt done && no failures
369
+ E-->>L: completed
370
+ else has actions
371
+ E->>T: execute each action
372
+ T-->>E: stdout / stderr / exitCode / error
373
+ E->>E: digest + append user turn
374
+ end
375
+ end
376
+ opt step wrote files & mode enables gate
377
+ loop up to maxValidationRetries
378
+ E->>V: typecheck / lint / tsc
379
+ alt passes
380
+ E-->>L: completed
381
+ else fails
382
+ E->>M: VALIDATION_FAILED · <output>
383
+ M-->>E: corrective actions
384
+ E->>T: execute
385
+ end
386
+ end
387
+ end
388
+ E-->>L: { toolResults, summary, filesChanged, completed }
389
+ ```
390
+
391
+ Mode caps — read directly from [`src/core/mode-policy.ts`](src/core/mode-policy.ts):
392
+
393
+ | Mode | maxExecutorTurns | maxValidationRetries | allowMutations | maxAutoRisk |
394
+ |------|:---:|:---:|:---:|:---:|
395
+ | fast | 2 | 0 | ✅ | low |
396
+ | balanced | 4 | 1 | ✅ | medium |
397
+ | heavy | 8 | 2 | ✅ | high |
398
+ | plan | 0→1 | 0 | ❌ | low |
399
+ | execute | 4 | 1 | ✅ | medium |
400
+ | audit | 3 | 0 | ❌ | low |
401
+ | debug | 6 | 2 | ✅ | medium |
402
+ | architect | 3 | 1 | ✅ | medium |
403
+ | offline-safe | 3 | 1 | ✅ | medium |
404
+
405
+ ---
406
+
407
+ ## Memory layers
408
+
409
+ Four tiers with distinct retention and access cost:
410
+
411
+ ```mermaid
412
+ flowchart TB
413
+ classDef hot fill:#450a0a,stroke:#f87171,color:#fee2e2,rx:4,ry:4
414
+ classDef warm fill:#451a03,stroke:#fb923c,color:#ffedd5,rx:4,ry:4
415
+ classDef cold fill:#0c4a6e,stroke:#38bdf8,color:#e0f2fe,rx:4,ry:4
416
+ classDef learn fill:#14532d,stroke:#10b981,color:#d1fae5,rx:4,ry:4
417
+
418
+ Q[retrieve.ts · query] --> H["Hot<br/>current-session facts<br/>src/memory/hot.ts"]:::hot
419
+ Q --> W["Warm<br/>recent tasks · SQLite<br/>src/memory/warm.ts"]:::warm
420
+ Q --> C["Cold<br/>project files · grep · AST<br/>src/memory/cold.ts"]:::cold
421
+ Q --> L["Learning<br/>patterns + confidence<br/>src/memory/learning.ts"]:::learn
422
+
423
+ H -.clear on task end.-> X([evict])
424
+ W -.age out after N days.-> X
425
+ L -.decay if unreinforced.-> L
426
+ ```
427
+
428
+ - **Hot** — in-process per-task facts, cleared at task end.
429
+ - **Warm** — SQLite index of recent task metadata; powers "what was I
430
+ doing yesterday" queries.
431
+ - **Cold** — lazy file/grep/AST index scoped to `projectRoot`. No
432
+ background indexer; populated on demand.
433
+ - **Learning** — patterns keyed by `intent:scope` with confidence that
434
+ evolves on success/failure. **The planner reads the top-K patterns
435
+ before producing every plan** (see `src/agents/planner.ts#learnedPatternBlock`).
436
+
437
+ ---
438
+
439
+ ## Provider routing & auto-adaptation
440
+
441
+ ```mermaid
442
+ flowchart LR
443
+ classDef local fill:#0c4a6e,stroke:#38bdf8,color:#e0f2fe,rx:4,ry:4
444
+ classDef hosted fill:#3f1d5c,stroke:#a78bfa,color:#ede9fe,rx:4,ry:4
445
+ classDef route fill:#1e293b,stroke:#f1f5f9,color:#f1f5f9,rx:4,ry:4
446
+
447
+ ROUTER[router.ts · resolveModel]:::route
448
+ ADAPT[adapter.ts · resolveLocalModel]:::route
449
+ CB[circuit-breaker]:::route
450
+ RL[rate-limit]:::route
451
+ CACHE[prompt cache]:::route
452
+ COST[USD cost ledger]:::route
453
+
454
+ subgraph LOCAL[Local runtimes · auto-detected]
455
+ OLL["ollama<br/>:11434"]:::local
456
+ LMS["lmstudio<br/>:1234"]:::local
457
+ VLL["vllm<br/>:8000"]:::local
458
+ LCP["llamacpp<br/>:8080"]:::local
459
+ end
460
+ subgraph HOSTED[Hosted · opt-in]
461
+ ANT["anthropic"]:::hosted
462
+ OAI["openai-compat<br/>(OpenAI / Azure / LocalAI / Together / Groq / Fireworks)"]:::hosted
463
+ end
464
+
465
+ ROUTER --> ADAPT --> OLL & LMS & VLL & LCP
466
+ ROUTER --> ANT & OAI
467
+ ROUTER --> CB & RL & CACHE & COST
468
+ ```
469
+
470
+ ### Auto-adaptation
471
+
472
+ If your configured model isn't pulled on the provider, Forge **picks the
473
+ best-fit installed model for each role** via
474
+ [`src/models/local-catalog.ts`](src/models/local-catalog.ts) +
475
+ [`src/models/adapter.ts`](src/models/adapter.ts). Cached per process,
476
+ warns once, never refuses to route.
477
+
478
+ ### Supported runtimes
479
+
480
+ | Runtime | Default endpoint | Override |
481
+ |---------|------------------|----------|
482
+ | Ollama | `http://127.0.0.1:11434` | `OLLAMA_ENDPOINT` |
483
+ | LM Studio | `http://127.0.0.1:1234/v1` | `LMSTUDIO_ENDPOINT` |
484
+ | vLLM | `http://127.0.0.1:8000/v1` | `VLLM_ENDPOINT` |
485
+ | llama.cpp server | `http://127.0.0.1:8080/v1` | `LLAMACPP_ENDPOINT` |
486
+ | OpenAI-compatible | env-configured | `OPENAI_BASE_URL` + `OPENAI_API_KEY` |
487
+ | Anthropic | hosted | `ANTHROPIC_API_KEY` |
488
+
489
+ ### Model family classification (41 families)
490
+
491
+ | Role | Families preferred |
492
+ |------|--------------------|
493
+ | architect / reviewer / debugger | Llama 3.x / 4.x, Mixtral, Command-R+, DeepSeek V3/R1, Mistral-Large |
494
+ | planner | Qwen 2.5/3, Llama 3.x, DeepSeek V3, Gemma 3, Mistral-Nemo, Command-R, Phi 4 |
495
+ | executor (code specialists) | DeepSeek-Coder, Qwen 2.5-Coder, CodeLlama, Codestral, StarCoder, Granite-Code, WizardCoder |
496
+ | fast | Phi 3/4, Gemma 2, TinyLlama, SmolLM, MiniCPM |
497
+
498
+ Unknown models are accepted too — Forge rates them as generic executors
499
+ rather than refusing to route.
500
+
501
+ ---
502
+
503
+ ## Safety model (not optional)
504
+
505
+ Forge treats safety as load-bearing. These invariants are enforced in
506
+ code, not convention:
507
+
508
+ ```mermaid
509
+ flowchart TB
510
+ classDef ask fill:#1e1b4b,stroke:#a78bfa,color:#ede9fe,rx:4,ry:4
511
+ classDef allow fill:#14532d,stroke:#10b981,color:#d1fae5,rx:4,ry:4
512
+ classDef deny fill:#450a0a,stroke:#f87171,color:#fee2e2,rx:4,ry:4
513
+
514
+ REQ[tool invocation] --> CLASSIFY[classify risk × sideEffect × sensitivity]
515
+ CLASSIFY --> SANDBOX{path in sandbox? / cmd allow-listed?}
516
+ SANDBOX -->|no| BLOCK[hard-block · sandbox_violation]:::deny
517
+ SANDBOX -->|yes| GATE{risk × sideEffect}
518
+ GATE -->|low · read| AUTO[auto-allow]:::allow
519
+ GATE -->|med · write| ASK[ask user]:::ask
520
+ GATE -->|high · execute / network| STRICT[ask even with --skip-permissions]:::ask
521
+ ASK --> FLAGS{session flags?}
522
+ FLAGS -->|--allow-shell / --allow-files etc.| AUTO
523
+ FLAGS -->|--non-interactive| DENY[deny silently]:::deny
524
+ FLAGS -->|else| PROMPT[interactive prompt]
525
+ PROMPT -->|allow| AUTO
526
+ PROMPT -->|deny| DENY
527
+ AUTO --> EXEC[execute] --> TRUST[trust calibration<br/>auto-allow after N confirmations<br/>src/permissions/manager.ts]
528
+ ```
529
+
530
+ | Invariant | Where |
531
+ |---|---|
532
+ | Instruction precedence: `System Safety > Page Rules > Mode Rules > Approved Plan > Project Defaults > User Preferences` | `src/prompts/assembler.ts` |
533
+ | Permission model = default deny | `src/permissions/manager.ts` |
534
+ | `--skip-permissions` skips *routine* prompts only; critical/destructive still ask | `src/permissions/risk.ts` |
535
+ | Retry cap = 3, then debugger escalates | `src/core/loop.ts` |
536
+ | Hard limits: `maxSteps=50` · `maxToolCalls=100` · `maxRuntimeSeconds=600` | `src/config/schema.ts` |
537
+ | Untrusted content (web / MCP / retrieved) fenced as data, never instructions | `src/security/injection.ts` |
538
+ | Secrets redacted before every log, session entry, and prompt | `src/security/redact.ts` |
539
+ | Scoped filesystem sandbox; symlink-escape-proof via realpath | `src/sandbox/fs.ts` |
540
+ | Destructive shell commands blocked (`rm -rf /`, `sudo`, fork bombs, curl-to-shell) | `src/sandbox/shell.ts` |
541
+ | Credentials in OS keychain (macOS / libsecret / DPAPI) + AES-GCM fallback | `src/keychain/` |
542
+ | Release artefacts: SHA-256 + Ed25519 signature verification | `src/release/` |
543
+
544
+ ---
545
+
546
+ ## Modes
547
+
548
+ ```mermaid
549
+ flowchart LR
550
+ classDef ro fill:#1e293b,stroke:#64748b,color:#cbd5e1,rx:4,ry:4
551
+ classDef rw fill:#0c4a6e,stroke:#38bdf8,color:#e0f2fe,rx:4,ry:4
552
+ classDef big fill:#3f1d5c,stroke:#a78bfa,color:#ede9fe,rx:4,ry:4
553
+
554
+ FAST[fast · 2 turns]:::rw
555
+ BAL[balanced · 4 turns · default]:::rw
556
+ HEAVY[heavy · 8 turns · 2 validate retries]:::big
557
+ PLAN[plan · 0 turns · no mutations]:::ro
558
+ EXEC[execute · 4 turns]:::rw
559
+ AUDIT[audit · 3 turns · no mutations]:::ro
560
+ DEBUG[debug · 6 turns · 2 validate retries]:::rw
561
+ ARCH[architect · 3 turns]:::big
562
+ OFFLINE[offline-safe · 3 turns · never hosted]:::rw
563
+ ```
564
+
565
+ Each mode is an **enforceable budget** — not a hint to the model. See
566
+ [`src/core/mode-policy.ts`](src/core/mode-policy.ts).
567
+
568
+ ---
569
+
570
+ ## CLI reference
571
+
572
+ 24 subcommands. Full surface:
573
+
574
+ ```
575
+ forge # REPL (default)
576
+ forge init # create ~/.forge + project .forge
577
+ forge run "<prompt>" # full agentic loop
578
+ forge plan "<prompt>" # plan-only
579
+ forge execute "<prompt>" # auto-approve + execute
580
+ forge resume [taskId] # resume any prior task (any status)
581
+ forge status # runtime state
582
+ forge doctor # health check + role→model mapping
583
+ forge task list|search # task history (SQLite-indexed)
584
+ forge session list|replay <id> # session JSONL inspection
585
+ forge model list # probe all providers
586
+ forge config get|set|path # configuration
587
+ forge mcp list|add|remove # MCP connections
588
+ forge skills list|new # skill management
589
+ forge agents list # custom agents
590
+ forge permissions reset|list # permission grants
591
+ forge daemon start|stop|status # optional background process
592
+ forge memory {hot|warm|cold} # memory inspection
593
+ forge cost # USD spend ledger
594
+ forge ui start # local dashboard at :7823
595
+ forge bundle {pack|unpack} # offline bundles
596
+ forge container up|down # compose wrapper
597
+ forge update [--check|--force] # self-update
598
+ forge migrate # DB migrations
599
+ forge changelog # local changelog view
600
+ forge dev # dev helpers
601
+ forge web {search|fetch} # web tools
602
+ forge spec {new|show|diff} # spec-driven development
603
+ ```
604
+
605
+ ### Common flags (`run` / `plan` / `execute`)
606
+
607
+ ```
608
+ --mode <m> fast|balanced|heavy|plan|execute|audit|debug|architect|offline-safe
609
+ --yes auto-approve plan
610
+ --skip-permissions skip routine prompts (high-risk still asked)
611
+ --allow-files pre-approve file writes for this session
612
+ --allow-shell pre-approve shell for this session
613
+ --allow-network pre-approve network tools
614
+ --allow-web pre-approve web search/fetch/browse
615
+ --allow-mcp pre-approve MCP tool calls
616
+ --strict confirm every action
617
+ --non-interactive deny all prompts silently (CI mode)
618
+ --deterministic fixed temperatures for reproducibility
619
+ --trace full trace (implies --debug)
620
+ --no-banner omit startup banner
621
+ ```
622
+
623
+ ---
624
+
625
+ ## Filesystem layout
626
+
627
+ ```mermaid
628
+ flowchart TB
629
+ classDef g fill:#18181b,stroke:#f59e0b,color:#fef3c7,rx:4,ry:4
630
+ classDef p fill:#0c4a6e,stroke:#38bdf8,color:#e0f2fe,rx:4,ry:4
631
+
632
+ subgraph GLOBAL["~/.forge (global)"]
633
+ G1["config.json"]:::g
634
+ G2["instructions.md"]:::g
635
+ G3["skills/*.md"]:::g
636
+ G4["agents/*.md"]:::g
637
+ G5["mcp/*"]:::g
638
+ G6["models/"]:::g
639
+ G7["logs/forge.log"]:::g
640
+ G8["global/index.db ← SQLite"]:::g
641
+ G9["projects/&lt;hash&gt;/tasks · sessions · events"]:::g
642
+ end
643
+
644
+ subgraph PROJECT["./.forge (per-project)"]
645
+ P1["config.json"]:::p
646
+ P2["instructions.md"]:::p
647
+ P3["skills/ (override global)"]:::p
648
+ P4["agents/"]:::p
649
+ P5["mcp/"]:::p
650
+ end
651
+ ```
652
+
653
+ Paths resolved via [`src/config/xdg.ts`](src/config/xdg.ts) — respects
654
+ `XDG_*` env vars on Linux.
655
+
656
+ ---
657
+
658
+ ## Skills · Instructions · MCP
659
+
660
+ ### Skills — a Markdown file with YAML frontmatter
661
+
662
+ ```markdown
663
+ ---
664
+ name: conventional-commit
665
+ description: Enforce Conventional Commits in every commit message.
666
+ triggers: [commit, git]
667
+ ---
668
+ When writing commit messages, use Conventional Commits:
669
+ feat(scope): …
670
+ fix(scope): …
671
+ refactor(scope): …
672
+ ```
673
+
674
+ Drop into `~/.forge/skills/` (global) or `./.forge/skills/` (project).
675
+ Project skills override global.
676
+
677
+ ### Instructions
678
+
679
+ Both `~/.forge/instructions.md` and `./.forge/instructions.md` are
680
+ layered into every prompt via [`src/prompts/assembler.ts`](src/prompts/assembler.ts).
681
+ Precedence is: **System Safety > Page > Mode > Plan > Project > User**.
682
+
683
+ ### MCP connections
684
+
685
+ ```bash
686
+ forge mcp list
687
+ forge mcp add <name> --transport stdio --command "…"
688
+ forge mcp add <name> --transport http --url https://… --auth oauth2-pkce
689
+ forge mcp status
690
+ ```
691
+
692
+ Both `stdio` and HTTP-stream transports supported. OAuth 2.0 + PKCE or
693
+ API key auth. Tokens stored in the OS keychain.
694
+
695
+ ---
696
+
697
+ ## Run in a container (Docker or Podman)
698
+
699
+ Single hardened image (non-root, HEALTHCHECK, OCI labels, ~355 MB) that
700
+ serves both CLI and UI.
701
+
702
+ ```bash
703
+ # Pull (multi-arch: linux/amd64 + linux/arm64):
704
+ docker pull ghcr.io/hoangsonw/forge-agentic-coding-cli:latest
705
+
706
+ # One-shot CLI:
707
+ docker run --rm -it -v forge-home:/data -v "$PWD:/workspace" \
708
+ ghcr.io/hoangsonw/forge-agentic-coding-cli:latest forge run "explain this repo"
709
+
710
+ # Dashboard:
711
+ docker run --rm -p 7823:7823 -v forge-home:/data \
712
+ ghcr.io/hoangsonw/forge-agentic-coding-cli:latest forge ui start --bind 0.0.0.0
713
+
714
+ # Full stack (forge + ollama + UI):
715
+ docker compose -f docker/docker-compose.yml up -d
716
+ # or: podman-compose -f docker/docker-compose.yml up -d
717
+ ```
718
+
719
+ Stack topology:
720
+
721
+ ```mermaid
722
+ flowchart LR
723
+ classDef c fill:#0c4a6e,stroke:#38bdf8,color:#e0f2fe,rx:4,ry:4
724
+ classDef v fill:#18181b,stroke:#f59e0b,color:#fef3c7,rx:4,ry:4
725
+
726
+ OLLAMA["ollama<br/>:11434 · healthcheck"]:::c
727
+ UI["forge-ui<br/>:7823 · healthcheck · restart unless-stopped"]:::c
728
+ CORE["forge-core<br/>(on-demand via compose run)"]:::c
729
+ FH[forge-home · named volume]:::v
730
+ OM[ollama-models · named volume]:::v
731
+
732
+ OLLAMA --> OM
733
+ UI --> FH
734
+ CORE --> FH
735
+ UI --> OLLAMA
736
+ CORE --> OLLAMA
737
+ ```
738
+
739
+ Full install guide: [`docs/INSTALL.md`](docs/INSTALL.md).
740
+
741
+ ---
742
+
743
+ ## CI/CD pipeline
744
+
745
+ ### CI (every PR + push)
746
+
747
+ ```mermaid
748
+ flowchart LR
749
+ classDef pass fill:#14532d,stroke:#10b981,color:#d1fae5,rx:4,ry:4
750
+ classDef gate fill:#1e1b4b,stroke:#a78bfa,color:#ede9fe,rx:4,ry:4
751
+
752
+ PR[PR / push] --> FMT["🎨 format"]:::pass
753
+ PR --> LINT["🧹 lint"]:::pass
754
+ PR --> TYPE["🧠 typecheck"]:::pass
755
+ PR --> TEST["🧪 test matrix<br/>Ubuntu + macOS × Node 20 + 22"]:::pass
756
+ TEST --> COV["📈 coverage"]:::pass
757
+ TYPE --> BUILD["🏗️ build"]:::pass
758
+ BUILD --> DOCKER["🐳 docker-build"]:::pass
759
+ PR --> AUDIT["🔐 audit"]:::pass
760
+ FMT & LINT & TYPE & TEST & BUILD & DOCKER & AUDIT & COV --> STATUS["📊 pipeline status<br/>GH step summary · fails if any required job failed"]:::gate
761
+ ```
762
+
763
+ ### Release (on `v*` tag)
764
+
765
+ ```mermaid
766
+ flowchart LR
767
+ classDef gate fill:#1e1b4b,stroke:#a78bfa,color:#ede9fe,rx:4,ry:4
768
+ classDef ship fill:#451a03,stroke:#fb923c,color:#ffedd5,rx:4,ry:4
769
+
770
+ TAG[git tag v*] --> GATE["🧪 pre-release gate<br/>build + full test suite"]:::gate
771
+ GATE --> ART["📦 artifacts<br/>5 tarball targets"]:::ship
772
+ GATE --> DOCKP["🐳 docker publish<br/>multi-arch → ghcr.io"]:::ship
773
+ ART --> MAN["📝 manifest + gh-release<br/>ed25519-signed"]:::ship
774
+ MAN --> NPM["📤 npm publish<br/>--provenance --access public"]:::ship
775
+ GATE & ART & DOCKP & MAN & NPM --> RSUM["📊 release status"]:::gate
776
+ ```
777
+
778
+ Workflows: [`.github/workflows/ci.yml`](.github/workflows/ci.yml),
779
+ [`.github/workflows/release.yml`](.github/workflows/release.yml),
780
+ [`.github/workflows/nightly.yml`](.github/workflows/nightly.yml).
781
+
782
+ ---
783
+
784
+ ## Architecture map
785
+
786
+ ```mermaid
787
+ flowchart TB
788
+ classDef surface fill:#0f172a,stroke:#38bdf8,color:#f1f5f9,rx:6,ry:6
789
+ classDef core fill:#082f49,stroke:#38bdf8,color:#e0f2fe,rx:6,ry:6
790
+ classDef agent fill:#1e293b,stroke:#a78bfa,color:#ede9fe,rx:6,ry:6
791
+ classDef io fill:#0f172a,stroke:#10b981,color:#d1fae5,rx:6,ry:6
792
+ classDef store fill:#18181b,stroke:#f59e0b,color:#fef3c7,rx:6,ry:6
793
+
794
+ subgraph S[User surfaces]
795
+ CLI["CLI (commander)"]:::surface
796
+ REPL["REPL (raw-mode editor)"]:::surface
797
+ UI["Dashboard (HTTP + WS)"]:::surface
798
+ end
799
+
800
+ ORCH["Orchestrator · src/core/orchestrator.ts"]:::core
801
+ LOOP["Agentic loop · src/core/loop.ts"]:::core
802
+ CLS["Classifier"]:::core
803
+
804
+ subgraph A[Agents · src/agents]
805
+ PL[planner]:::agent
806
+ AR[architect]:::agent
807
+ EX[executor]:::agent
808
+ RV[reviewer]:::agent
809
+ DB[debugger]:::agent
810
+ ME[memory]:::agent
811
+ end
812
+
813
+ subgraph I[I/O surfaces]
814
+ TOOLS["18 tools · src/tools"]:::io
815
+ MODELS["6 providers · src/models"]:::io
816
+ PERM["Permissions"]:::io
817
+ SAND["Sandbox (fs + shell)"]:::io
818
+ MCP["MCP bridge"]:::io
819
+ end
820
+
821
+ subgraph P[Durable state]
822
+ TASKS[tasks/*.json]:::store
823
+ SESS[sessions/*.jsonl]:::store
824
+ CONV[conversations/*.jsonl]:::store
825
+ IDX[SQLite index]:::store
826
+ MEM["memory/{hot,warm,cold,learning}"]:::store
827
+ end
828
+
829
+ CLI --> ORCH
830
+ REPL --> ORCH
831
+ UI --> ORCH
832
+ ORCH --> CLS --> LOOP
833
+ LOOP --> PL --> EX --> RV
834
+ RV --> LOOP
835
+ LOOP --> AR & DB & ME
836
+ EX --> TOOLS
837
+ TOOLS --> PERM & SAND & MCP
838
+ PL --> MODELS
839
+ EX --> MODELS
840
+ LOOP --> TASKS & SESS & CONV & IDX
841
+ ME --> MEM
842
+ ```
843
+
844
+ Full map with every subsystem explained: [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).
845
+
846
+ ### Executor turn budget per mode
847
+
848
+ ```mermaid
849
+ xychart-beta
850
+ title "Executor turns per mode (hard runtime cap)"
851
+ x-axis ["plan", "fast", "audit", "architect", "offline-safe", "balanced", "execute", "debug", "heavy"]
852
+ y-axis "turns" 0 --> 8
853
+ bar [1, 2, 3, 3, 3, 4, 4, 6, 8]
854
+ ```
855
+
856
+ ---
857
+
858
+ ## Development
859
+
860
+ ```bash
861
+ git clone https://github.com/hoangsonw/Forge-Agentic-Coding-CLI && cd forge
862
+ npm install
863
+ npm run build # tsc + copy-assets
864
+ npm test # 249 tests across 43 files; all must pass
865
+ ./bin/forge.js doctor
866
+ ```
867
+
868
+ | Task | Command |
869
+ |------|---------|
870
+ | Build | `npm run build` |
871
+ | Watch | `npm run build:watch` |
872
+ | Tests | `npm test` |
873
+ | One test file | `npx vitest run test/unit/<file>.test.ts` |
874
+ | Coverage | `npm run test:coverage` |
875
+ | Typecheck | `npm run typecheck` |
876
+ | Lint / format | `npm run lint` · `npm run format` · `npm run format:check` |
877
+ | Metrics | `bash scripts/metrics.sh` |
878
+ | Docker | `docker build -f docker/Dockerfile -t forge/core:dev .` |
879
+ | REPL | `./bin/forge.js` |
880
+ | Dashboard | `./bin/forge.js ui start` |
881
+
882
+ Full guide: [`docs/SETUP.md`](docs/SETUP.md).
883
+
884
+ ### Measured performance (reproduce with the commands shown)
885
+
886
+ | Target | Measured | How |
887
+ |--------|----------|-----|
888
+ | `forge --help` cold-start | **238 ms** | `time node bin/forge.js --help` |
889
+ | `forge doctor` cold-start | **173 ms** | `time node bin/forge.js doctor --no-banner` |
890
+ | UI `app.js` uncompressed | **89 KB** | `wc -c src/ui/public/app.js` |
891
+ | Landing `index.html` | **25 KB**, self-contained, zero CDN | `wc -c index.html` |
892
+ | Full test suite | **~3.3 s** wall-clock | `npx vitest run` |
893
+ | Container image | **~355 MB** multi-arch non-root | `docker images` |
894
+
895
+ ---
896
+
897
+ ## Agent-facing context
898
+
899
+ If you're a code-writing agent (Claude Code, Codex, Cursor, Aider, Cline,
900
+ Continue, …) working in this repo, start here:
901
+
902
+ - [`CLAUDE.md`](CLAUDE.md) — Claude Code / Claude-family context
903
+ - [`AGENTS.md`](AGENTS.md) — OpenAI `AGENTS.md` convention (used by Codex and most others)
904
+
905
+ Both files carry: canonical commands, hot paths, conventions, performance
906
+ posture, security posture, and pre-completion checklist.
907
+
908
+ ---
909
+
910
+ ## License
911
+
912
+ MIT. See [LICENSE](LICENSE) for more details.
913
+
914
+ ---
915
+
916
+ <div align="center" style="margin-top: 2em">
917
+ <p>Son Nguyen · <a href="https://sonnguyenhoang.com">sonnguyenhoang.com</a> · <a href="https://github.com/hoangsonww">github.com/hoangsonww</a></p>
918
+ <p>Thank you for checking out Forge! If you have any questions, feedback, or want to contribute, please open an issue or a pull request.</p>
919
+ </div>