opencode-forge 0.1.5

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 (309) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +534 -0
  3. package/config.jsonc +47 -0
  4. package/dist/agents/architect.d.ts +3 -0
  5. package/dist/agents/architect.d.ts.map +1 -0
  6. package/dist/agents/architect.js +152 -0
  7. package/dist/agents/architect.js.map +1 -0
  8. package/dist/agents/auditor.d.ts +3 -0
  9. package/dist/agents/auditor.d.ts.map +1 -0
  10. package/dist/agents/auditor.js +168 -0
  11. package/dist/agents/auditor.js.map +1 -0
  12. package/dist/agents/code.d.ts +3 -0
  13. package/dist/agents/code.d.ts.map +1 -0
  14. package/dist/agents/code.js +67 -0
  15. package/dist/agents/code.js.map +1 -0
  16. package/dist/agents/index.d.ts +4 -0
  17. package/dist/agents/index.d.ts.map +1 -0
  18. package/dist/agents/index.js +9 -0
  19. package/dist/agents/index.js.map +1 -0
  20. package/dist/agents/prompts.d.ts +1 -0
  21. package/dist/agents/prompts.d.ts.map +1 -0
  22. package/dist/agents/prompts.js +4 -0
  23. package/dist/agents/prompts.js.map +1 -0
  24. package/dist/agents/types.d.ts +34 -0
  25. package/dist/agents/types.d.ts.map +1 -0
  26. package/dist/agents/types.js +2 -0
  27. package/dist/agents/types.js.map +1 -0
  28. package/dist/cache/index.d.ts +4 -0
  29. package/dist/cache/index.d.ts.map +1 -0
  30. package/dist/cache/index.js +5 -0
  31. package/dist/cache/index.js.map +1 -0
  32. package/dist/cache/memory-cache.d.ts +14 -0
  33. package/dist/cache/memory-cache.d.ts.map +1 -0
  34. package/dist/cache/memory-cache.js +51 -0
  35. package/dist/cache/memory-cache.js.map +1 -0
  36. package/dist/cache/types.d.ts +8 -0
  37. package/dist/cache/types.d.ts.map +1 -0
  38. package/dist/cache/types.js +2 -0
  39. package/dist/cache/types.js.map +1 -0
  40. package/dist/cli/commands/cancel.d.ts +15 -0
  41. package/dist/cli/commands/cancel.d.ts.map +1 -0
  42. package/dist/cli/commands/cancel.js +194 -0
  43. package/dist/cli/commands/cancel.js.map +1 -0
  44. package/dist/cli/commands/graph.d.ts +16 -0
  45. package/dist/cli/commands/graph.d.ts.map +1 -0
  46. package/dist/cli/commands/graph.js +208 -0
  47. package/dist/cli/commands/graph.js.map +1 -0
  48. package/dist/cli/commands/restart.d.ts +15 -0
  49. package/dist/cli/commands/restart.d.ts.map +1 -0
  50. package/dist/cli/commands/restart.js +268 -0
  51. package/dist/cli/commands/restart.js.map +1 -0
  52. package/dist/cli/commands/status.d.ts +17 -0
  53. package/dist/cli/commands/status.d.ts.map +1 -0
  54. package/dist/cli/commands/status.js +356 -0
  55. package/dist/cli/commands/status.js.map +1 -0
  56. package/dist/cli/commands/upgrade.d.ts +3 -0
  57. package/dist/cli/commands/upgrade.d.ts.map +1 -0
  58. package/dist/cli/commands/upgrade.js +40 -0
  59. package/dist/cli/commands/upgrade.js.map +1 -0
  60. package/dist/cli/index.d.ts +3 -0
  61. package/dist/cli/index.d.ts.map +1 -0
  62. package/dist/cli/index.js +224 -0
  63. package/dist/cli/index.js.map +1 -0
  64. package/dist/cli/utils.d.ts +36 -0
  65. package/dist/cli/utils.d.ts.map +1 -0
  66. package/dist/cli/utils.js +163 -0
  67. package/dist/cli/utils.js.map +1 -0
  68. package/dist/command/template/review.txt +101 -0
  69. package/dist/config.d.ts +5 -0
  70. package/dist/config.d.ts.map +1 -0
  71. package/dist/config.js +186 -0
  72. package/dist/config.js.map +1 -0
  73. package/dist/constants/loop.d.ts +10 -0
  74. package/dist/constants/loop.d.ts.map +1 -0
  75. package/dist/constants/loop.js +6 -0
  76. package/dist/constants/loop.js.map +1 -0
  77. package/dist/graph/cache.d.ts +17 -0
  78. package/dist/graph/cache.d.ts.map +1 -0
  79. package/dist/graph/cache.js +50 -0
  80. package/dist/graph/cache.js.map +1 -0
  81. package/dist/graph/client.d.ts +51 -0
  82. package/dist/graph/client.d.ts.map +1 -0
  83. package/dist/graph/client.js +152 -0
  84. package/dist/graph/client.js.map +1 -0
  85. package/dist/graph/clone-detection.d.ts +9 -0
  86. package/dist/graph/clone-detection.d.ts.map +1 -0
  87. package/dist/graph/clone-detection.js +148 -0
  88. package/dist/graph/clone-detection.js.map +1 -0
  89. package/dist/graph/constants.d.ts +18 -0
  90. package/dist/graph/constants.d.ts.map +1 -0
  91. package/dist/graph/constants.js +532 -0
  92. package/dist/graph/constants.js.map +1 -0
  93. package/dist/graph/database.d.ts +11 -0
  94. package/dist/graph/database.d.ts.map +1 -0
  95. package/dist/graph/database.js +250 -0
  96. package/dist/graph/database.js.map +1 -0
  97. package/dist/graph/index.d.ts +14 -0
  98. package/dist/graph/index.d.ts.map +1 -0
  99. package/dist/graph/index.js +13 -0
  100. package/dist/graph/index.js.map +1 -0
  101. package/dist/graph/repo-map.d.ts +59 -0
  102. package/dist/graph/repo-map.d.ts.map +1 -0
  103. package/dist/graph/repo-map.js +948 -0
  104. package/dist/graph/repo-map.js.map +1 -0
  105. package/dist/graph/rpc.d.ts +34 -0
  106. package/dist/graph/rpc.d.ts.map +1 -0
  107. package/dist/graph/rpc.js +139 -0
  108. package/dist/graph/rpc.js.map +1 -0
  109. package/dist/graph/service.d.ts +46 -0
  110. package/dist/graph/service.d.ts.map +1 -0
  111. package/dist/graph/service.js +329 -0
  112. package/dist/graph/service.js.map +1 -0
  113. package/dist/graph/tree-sitter.d.ts +40 -0
  114. package/dist/graph/tree-sitter.d.ts.map +1 -0
  115. package/dist/graph/tree-sitter.js +799 -0
  116. package/dist/graph/tree-sitter.js.map +1 -0
  117. package/dist/graph/types.d.ts +175 -0
  118. package/dist/graph/types.d.ts.map +1 -0
  119. package/dist/graph/types.js +105 -0
  120. package/dist/graph/types.js.map +1 -0
  121. package/dist/graph/utils.d.ts +64 -0
  122. package/dist/graph/utils.d.ts.map +1 -0
  123. package/dist/graph/utils.js +406 -0
  124. package/dist/graph/utils.js.map +1 -0
  125. package/dist/graph/worker.d.ts +2 -0
  126. package/dist/graph/worker.d.ts.map +1 -0
  127. package/dist/graph/worker.js +6043 -0
  128. package/dist/graph/worker.js.map +1 -0
  129. package/dist/hooks/compaction-utils.d.ts +21 -0
  130. package/dist/hooks/compaction-utils.d.ts.map +1 -0
  131. package/dist/hooks/compaction-utils.js +82 -0
  132. package/dist/hooks/compaction-utils.js.map +1 -0
  133. package/dist/hooks/graph-command.d.ts +27 -0
  134. package/dist/hooks/graph-command.d.ts.map +1 -0
  135. package/dist/hooks/graph-command.js +57 -0
  136. package/dist/hooks/graph-command.js.map +1 -0
  137. package/dist/hooks/graph-tools.d.ts +11 -0
  138. package/dist/hooks/graph-tools.d.ts.map +1 -0
  139. package/dist/hooks/graph-tools.js +125 -0
  140. package/dist/hooks/graph-tools.js.map +1 -0
  141. package/dist/hooks/index.d.ts +5 -0
  142. package/dist/hooks/index.d.ts.map +1 -0
  143. package/dist/hooks/index.js +5 -0
  144. package/dist/hooks/index.js.map +1 -0
  145. package/dist/hooks/loop.d.ts +23 -0
  146. package/dist/hooks/loop.d.ts.map +1 -0
  147. package/dist/hooks/loop.js +667 -0
  148. package/dist/hooks/loop.js.map +1 -0
  149. package/dist/hooks/sandbox-tools.d.ts +13 -0
  150. package/dist/hooks/sandbox-tools.d.ts.map +1 -0
  151. package/dist/hooks/sandbox-tools.js +105 -0
  152. package/dist/hooks/sandbox-tools.js.map +1 -0
  153. package/dist/hooks/session.d.ts +19 -0
  154. package/dist/hooks/session.d.ts.map +1 -0
  155. package/dist/hooks/session.js +56 -0
  156. package/dist/hooks/session.js.map +1 -0
  157. package/dist/index.d.ts +11 -0
  158. package/dist/index.d.ts.map +1 -0
  159. package/dist/index.js +298 -0
  160. package/dist/index.js.map +1 -0
  161. package/dist/sandbox/context.d.ts +27 -0
  162. package/dist/sandbox/context.d.ts.map +1 -0
  163. package/dist/sandbox/context.js +18 -0
  164. package/dist/sandbox/context.js.map +1 -0
  165. package/dist/sandbox/docker.d.ts +29 -0
  166. package/dist/sandbox/docker.d.ts.map +1 -0
  167. package/dist/sandbox/docker.js +213 -0
  168. package/dist/sandbox/docker.js.map +1 -0
  169. package/dist/sandbox/manager.d.ts +23 -0
  170. package/dist/sandbox/manager.d.ts.map +1 -0
  171. package/dist/sandbox/manager.js +131 -0
  172. package/dist/sandbox/manager.js.map +1 -0
  173. package/dist/sandbox/path.d.ts +4 -0
  174. package/dist/sandbox/path.d.ts.map +1 -0
  175. package/dist/sandbox/path.js +27 -0
  176. package/dist/sandbox/path.js.map +1 -0
  177. package/dist/services/kv.d.ts +17 -0
  178. package/dist/services/kv.d.ts.map +1 -0
  179. package/dist/services/kv.js +62 -0
  180. package/dist/services/kv.js.map +1 -0
  181. package/dist/services/loop.d.ts +96 -0
  182. package/dist/services/loop.d.ts.map +1 -0
  183. package/dist/services/loop.js +315 -0
  184. package/dist/services/loop.js.map +1 -0
  185. package/dist/setup.d.ts +4 -0
  186. package/dist/setup.d.ts.map +1 -0
  187. package/dist/setup.js +118 -0
  188. package/dist/setup.js.map +1 -0
  189. package/dist/storage/database.d.ts +6 -0
  190. package/dist/storage/database.d.ts.map +1 -0
  191. package/dist/storage/database.js +90 -0
  192. package/dist/storage/database.js.map +1 -0
  193. package/dist/storage/graph-projects.d.ts +80 -0
  194. package/dist/storage/graph-projects.d.ts.map +1 -0
  195. package/dist/storage/graph-projects.js +154 -0
  196. package/dist/storage/graph-projects.js.map +1 -0
  197. package/dist/storage/index.d.ts +5 -0
  198. package/dist/storage/index.d.ts.map +1 -0
  199. package/dist/storage/index.js +3 -0
  200. package/dist/storage/index.js.map +1 -0
  201. package/dist/storage/kv-queries.d.ts +18 -0
  202. package/dist/storage/kv-queries.d.ts.map +1 -0
  203. package/dist/storage/kv-queries.js +70 -0
  204. package/dist/storage/kv-queries.js.map +1 -0
  205. package/dist/tools/graph.d.ts +9 -0
  206. package/dist/tools/graph.d.ts.map +1 -0
  207. package/dist/tools/graph.js +272 -0
  208. package/dist/tools/graph.js.map +1 -0
  209. package/dist/tools/index.d.ts +6 -0
  210. package/dist/tools/index.d.ts.map +1 -0
  211. package/dist/tools/index.js +16 -0
  212. package/dist/tools/index.js.map +1 -0
  213. package/dist/tools/loop.d.ts +21 -0
  214. package/dist/tools/loop.d.ts.map +1 -0
  215. package/dist/tools/loop.js +570 -0
  216. package/dist/tools/loop.js.map +1 -0
  217. package/dist/tools/plan-approval.d.ts +15 -0
  218. package/dist/tools/plan-approval.d.ts.map +1 -0
  219. package/dist/tools/plan-approval.js +203 -0
  220. package/dist/tools/plan-approval.js.map +1 -0
  221. package/dist/tools/plan-execute.d.ts +4 -0
  222. package/dist/tools/plan-execute.d.ts.map +1 -0
  223. package/dist/tools/plan-execute.js +85 -0
  224. package/dist/tools/plan-execute.js.map +1 -0
  225. package/dist/tools/plan-kv.d.ts +4 -0
  226. package/dist/tools/plan-kv.d.ts.map +1 -0
  227. package/dist/tools/plan-kv.js +107 -0
  228. package/dist/tools/plan-kv.js.map +1 -0
  229. package/dist/tools/review.d.ts +4 -0
  230. package/dist/tools/review.d.ts.map +1 -0
  231. package/dist/tools/review.js +90 -0
  232. package/dist/tools/review.js.map +1 -0
  233. package/dist/tools/sandbox-fs.d.ts +22 -0
  234. package/dist/tools/sandbox-fs.d.ts.map +1 -0
  235. package/dist/tools/sandbox-fs.js +83 -0
  236. package/dist/tools/sandbox-fs.js.map +1 -0
  237. package/dist/tools/types.d.ts +26 -0
  238. package/dist/tools/types.d.ts.map +1 -0
  239. package/dist/tools/types.js +2 -0
  240. package/dist/tools/types.js.map +1 -0
  241. package/dist/tui.d.ts +3 -0
  242. package/dist/tui.js +2061 -0
  243. package/dist/types.d.ts +124 -0
  244. package/dist/types.d.ts.map +1 -0
  245. package/dist/types.js +2 -0
  246. package/dist/types.js.map +1 -0
  247. package/dist/utils/git-branch.d.ts +11 -0
  248. package/dist/utils/git-branch.d.ts.map +1 -0
  249. package/dist/utils/git-branch.js +35 -0
  250. package/dist/utils/git-branch.js.map +1 -0
  251. package/dist/utils/graph-status-store.d.ts +72 -0
  252. package/dist/utils/graph-status-store.d.ts.map +1 -0
  253. package/dist/utils/graph-status-store.js +62 -0
  254. package/dist/utils/graph-status-store.js.map +1 -0
  255. package/dist/utils/logger.d.ts +8 -0
  256. package/dist/utils/logger.d.ts.map +1 -0
  257. package/dist/utils/logger.js +89 -0
  258. package/dist/utils/logger.js.map +1 -0
  259. package/dist/utils/loop-format.d.ts +5 -0
  260. package/dist/utils/loop-format.d.ts.map +1 -0
  261. package/dist/utils/loop-format.js +29 -0
  262. package/dist/utils/loop-format.js.map +1 -0
  263. package/dist/utils/loop-helpers.d.ts +9 -0
  264. package/dist/utils/loop-helpers.d.ts.map +1 -0
  265. package/dist/utils/loop-helpers.js +20 -0
  266. package/dist/utils/loop-helpers.js.map +1 -0
  267. package/dist/utils/loop-launch.d.ts +32 -0
  268. package/dist/utils/loop-launch.d.ts.map +1 -0
  269. package/dist/utils/loop-launch.js +162 -0
  270. package/dist/utils/loop-launch.js.map +1 -0
  271. package/dist/utils/model-fallback.d.ts +27 -0
  272. package/dist/utils/model-fallback.d.ts.map +1 -0
  273. package/dist/utils/model-fallback.js +33 -0
  274. package/dist/utils/model-fallback.js.map +1 -0
  275. package/dist/utils/partial-match.d.ts +7 -0
  276. package/dist/utils/partial-match.d.ts.map +1 -0
  277. package/dist/utils/partial-match.js +56 -0
  278. package/dist/utils/partial-match.js.map +1 -0
  279. package/dist/utils/plan-execution.d.ts +65 -0
  280. package/dist/utils/plan-execution.d.ts.map +1 -0
  281. package/dist/utils/plan-execution.js +107 -0
  282. package/dist/utils/plan-execution.js.map +1 -0
  283. package/dist/utils/session-stats.d.ts +36 -0
  284. package/dist/utils/session-stats.d.ts.map +1 -0
  285. package/dist/utils/session-stats.js +145 -0
  286. package/dist/utils/session-stats.js.map +1 -0
  287. package/dist/utils/tui-graph-status.d.ts +38 -0
  288. package/dist/utils/tui-graph-status.d.ts.map +1 -0
  289. package/dist/utils/tui-graph-status.js +95 -0
  290. package/dist/utils/tui-graph-status.js.map +1 -0
  291. package/dist/utils/tui-plan-store.d.ts +54 -0
  292. package/dist/utils/tui-plan-store.d.ts.map +1 -0
  293. package/dist/utils/tui-plan-store.js +168 -0
  294. package/dist/utils/tui-plan-store.js.map +1 -0
  295. package/dist/utils/tui-refresh-helpers.d.ts +44 -0
  296. package/dist/utils/tui-refresh-helpers.d.ts.map +1 -0
  297. package/dist/utils/tui-refresh-helpers.js +120 -0
  298. package/dist/utils/tui-refresh-helpers.js.map +1 -0
  299. package/dist/utils/upgrade.d.ts +23 -0
  300. package/dist/utils/upgrade.d.ts.map +1 -0
  301. package/dist/utils/upgrade.js +111 -0
  302. package/dist/utils/upgrade.js.map +1 -0
  303. package/dist/version.d.ts +2 -0
  304. package/dist/version.d.ts.map +1 -0
  305. package/dist/version.js +2 -0
  306. package/dist/version.js.map +1 -0
  307. package/package.json +92 -0
  308. package/scripts/build.ts +67 -0
  309. package/src/command/template/review.txt +101 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Chris Scott
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,534 @@
1
+ <h1 align="center">OpenCode Forge</h1>
2
+
3
+ <p align="center">
4
+ <strong>Loops, plans, sandboxing, and graph tooling for <a href="https://opencode.ai">OpenCode</a> AI agents</strong>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/opencode-forge"><img src="https://img.shields.io/npm/v/opencode-forge" alt="npm" /></a>
9
+ <a href="https://www.npmjs.com/package/opencode-forge"><img src="https://img.shields.io/npm/dm/opencode-forge" alt="npm downloads" /></a>
10
+ <a href="https://github.com/chriswritescode-dev/opencode-forge/blob/main/LICENSE"><img src="https://img.shields.io/github/license/chriswritescode-dev/opencode-forge" alt="License" /></a>
11
+ </p>
12
+
13
+ ## Quick Start
14
+
15
+ ```bash
16
+ pnpm add opencode-forge
17
+ ```
18
+
19
+ Add to your `opencode.json`:
20
+
21
+ ```json
22
+ {
23
+ "plugin": ["opencode-forge"]
24
+ }
25
+ ```
26
+
27
+ ## Features
28
+
29
+ - **Graph Indexing** - Code structure graph with file watching, auto-scanning, and symbol tracking
30
+ - **Iterative Development Loops** - Autonomous coding/auditing loop with optional worktree isolation, session rotation, stall detection, and review finding persistence
31
+ - **Session Plan Storage** - Session-scoped plan storage with 7-day TTL for managing implementation plans
32
+ - **Review Finding Persistence** - Store and retrieve audit findings across session rotations
33
+ - **Bundled Agents** - Ships with Code, Architect, Auditor and Librarian agents preconfigured for graph-aware workflows
34
+ - **CLI Tools** - Loop status, cancel, restart, graph status, graph scan, and upgrade commands via `opencode-forge`
35
+ - **Docker Sandbox** - Run loops inside isolated Docker containers with bind-mounted project directory, automatic container lifecycle, and selective tool routing (bash, glob, grep)
36
+
37
+ ## Agents
38
+
39
+ The plugin bundles four agents that integrate with the graph system:
40
+
41
+ | Agent | Mode | Description |
42
+ |-------|------|-------------|
43
+ | **code** | primary | Primary coding agent with graph awareness. Checks the code graph before unfamiliar code, stores architectural decisions and conventions as it works. |
44
+ | **architect** | primary | Read-only planning agent. Researches the codebase, designs implementation plans, then hands off to code via `plan-execute`. |
45
+ | **auditor** | subagent | Read-only code auditor with access to project graph for convention-aware reviews. Invoked via Task tool to review diffs, commits, branches, or PRs against stored conventions and decisions. |
46
+
47
+ The auditor agent is a read-only subagent (`temperature: 0.0`) that can read the graph but cannot write, edit, or delete graph entries or execute plans. It is invoked by other agents via the Task tool to review code changes against stored project conventions and decisions.
48
+
49
+ The architect agent operates in read-only mode (`temperature: 0.0`, all edits denied) with message-level enforcement via the `experimental.chat.messages.transform` hook. Plans are built incrementally in the KV store during the planning session. After approval, execution is dispatched programmatically — no additional LLM calls are needed. The user can view and edit the cached plan from the sidebar or command palette before or during execution.
50
+
51
+
52
+ ## Tools
53
+
54
+ ### Plan Tools
55
+
56
+ Session-scoped plan storage with 7-day TTL for managing implementation plans.
57
+
58
+ | Tool | Description |
59
+ |------|-------------|
60
+ | `plan-write` | Store the entire plan content. Auto-resolves key to `plan:{sessionID}`. |
61
+ | `plan-edit` | Edit the plan by finding `old_string` and replacing with `new_string`. |
62
+ | `plan-read` | Retrieve the plan. Supports pagination with offset/limit and pattern search. |
63
+ | `plan-execute` | Create a new Code session and send an approved plan as the first prompt |
64
+
65
+ ### Review Tools
66
+
67
+ Review finding storage for persisting audit results across session rotations.
68
+
69
+ | Tool | Description |
70
+ |------|-------------|
71
+ | `review-write` | Store a review finding with file, line, severity, and description. Auto-injects branch field. |
72
+ | `review-read` | Retrieve review findings. Filter by file path or search by regex pattern. |
73
+ | `review-delete` | Delete a review finding by file and line. |
74
+
75
+ ### Loop Tools
76
+
77
+ Iterative development loops with automatic auditing. Defaults to current directory execution; set `worktree: true` for isolated git worktree.
78
+
79
+ | Tool | Description |
80
+ |------|-------------|
81
+ | `loop` | Execute a plan using an iterative development loop. Default runs in current directory. Set `worktree` to true for isolated git worktree. |
82
+ | `loop-cancel` | Cancel an active loop by worktree name |
83
+ | `loop-status` | List all active loops or get detailed status by worktree name. Supports `restart` to resume inactive loops. |
84
+
85
+ ### Graph Tools
86
+
87
+ Code structure graph with file watching and symbol tracking.
88
+
89
+ | Tool | Description |
90
+ |------|-------------|
91
+ | `graph-index` | Index the codebase and build a symbol graph |
92
+ | `graph-search` | Search the graph for symbols, references, or file patterns |
93
+ | `graph-status` | Show graph indexing status and statistics |
94
+
95
+ ## Slash Commands
96
+
97
+ | Command | Description | Agent |
98
+ |---------|-------------|-------|
99
+ | `/review` | Run a code review on current changes | auditor (subtask) |
100
+ | `/loop` | Start an iterative development loop in a worktree | code |
101
+ | `/loop-status` | Check status of all active loops | code |
102
+ | `/loop-cancel` | Cancel the active loop | code |
103
+
104
+ ## CLI
105
+
106
+ Manage loops and graph operations using the `opencode-forge` CLI. The CLI auto-detects the project ID from git.
107
+
108
+ ```bash
109
+ opencode-forge <command> [options]
110
+ ```
111
+
112
+ **Global options** (apply to all commands):
113
+
114
+ | Flag | Description |
115
+ |------|-------------|
116
+ | `--project, -p <name>` | Project name or SHA (auto-detected from git) |
117
+ | `--dir, -d <path>` | Git repo path for project detection |
118
+ | `--help, -h` | Show help |
119
+
120
+ ### Commands
121
+
122
+ #### upgrade
123
+
124
+ Check for plugin updates and install the latest version.
125
+
126
+ ```bash
127
+ opencode-forge upgrade
128
+ ```
129
+
130
+ #### status
131
+
132
+ Show loop status for the current project.
133
+
134
+ ```bash
135
+ opencode-forge loop status
136
+ opencode-forge loop status --project my-project
137
+ ```
138
+
139
+ | Flag | Description |
140
+ |------|-------------|
141
+ | `--project, -p <name>` | Project name or SHA (auto-detected from git) |
142
+
143
+ #### cancel
144
+
145
+ Cancel a loop by worktree name.
146
+
147
+ ```bash
148
+ opencode-forge loop cancel my-worktree-name
149
+ opencode-forge loop cancel --project my-project my-worktree-name
150
+ ```
151
+
152
+ | Flag | Description |
153
+ |------|-------------|
154
+ | `--project, -p <name>` | Project name or SHA (auto-detected from git) |
155
+
156
+ #### restart
157
+
158
+ Restart a loop by worktree name.
159
+
160
+ ```bash
161
+ opencode-forge loop restart my-worktree-name
162
+ opencode-forge loop restart --project my-project my-worktree-name
163
+
164
+ #### graph
165
+
166
+ Check graph status or trigger a scan.
167
+
168
+ ```bash
169
+ opencode-forge graph status
170
+ opencode-forge graph scan
171
+ ```
172
+ ```
173
+
174
+ | Flag | Description |
175
+ |------|-------------|
176
+ | `--project, -p <name>` | Project name or SHA (auto-detected from git) |
177
+
178
+ ## Configuration
179
+
180
+ On first run, the plugin automatically copies the bundled config to your config directory:
181
+ - Path: `~/.config/opencode/forge-config.jsonc`
182
+ - Falls back to: `$XDG_CONFIG_HOME/opencode/forge-config.jsonc`
183
+
184
+ **Note:** Configuration is stored at `~/.config/opencode/forge-config.jsonc`.
185
+
186
+ The plugin supports JSONC format, allowing comments with `//` and `/* */`.
187
+
188
+ You can edit this file to customize settings. The file is created only if it doesn't already exist.
189
+
190
+ ```jsonc
191
+ {
192
+ // Logging configuration
193
+ "logging": {
194
+ "enabled": false, // Enable file logging
195
+ "debug": false, // Enable debug-level output
196
+ "file": "" // Log file path (defaults to ~/.local/share/opencode/forge/logs/forge.log)
197
+ },
198
+
199
+ // Session compaction settings
200
+ "compaction": {
201
+ "customPrompt": true // Use custom compaction prompt for continuity
202
+ },
203
+
204
+ // Messages transform hook for graph injection and read-only enforcement
205
+ "messagesTransform": {
206
+ "enabled": true, // Enable transform hook
207
+ "debug": false // Enable debug logging
208
+ },
209
+
210
+ // Model override for plan execution sessions (format: "provider/model")
211
+ "executionModel": "",
212
+
213
+ // Model override for the auditor agent (format: "provider/model")
214
+ "auditorModel": "",
215
+
216
+ // Iterative development loop settings
217
+ "loop": {
218
+ "enabled": true, // Enable iterative loops
219
+ "defaultMaxIterations": 15, // Max iterations (0 = unlimited)
220
+ "cleanupWorktree": false, // Auto-remove worktree on cancel
221
+ "defaultAudit": true, // Run auditor after each coding iteration
222
+ "model": "", // Model override for loop sessions
223
+ "minAudits": 1, // Minimum audit iterations before completion
224
+ "stallTimeoutMs": 60000 // Stall detection timeout (60s)
225
+ },
226
+
227
+ // Docker sandbox configuration for isolated loop execution
228
+ "sandbox": {
229
+ "mode": "off", // Sandbox mode: "off" or "docker"
230
+ "image": "opencode-forge-sandbox:latest" // Docker image for sandbox containers
231
+ },
232
+
233
+ // Graph indexing configuration
234
+ "graph": {
235
+ "enabled": true, // Enable graph indexing
236
+ "autoScan": true, // Auto-scan on startup
237
+ "watch": true, // Watch for file changes
238
+ "debounceMs": 100, // Debounce delay for file watches
239
+ "maxFiles": 1000 // Maximum files to index
240
+ },
241
+
242
+ // TUI sidebar widget configuration
243
+ "tui": {
244
+ "sidebar": true, // Show memory sidebar in OpenCode TUI
245
+ "showLoops": true, // Display loop status in sidebar
246
+ "showVersion": true // Show plugin version in sidebar title
247
+ }
248
+ }
249
+ ```
250
+
251
+ ### Options
252
+
253
+ #### Logging
254
+ - `logging.enabled` - Enable file logging (default: `false`)
255
+ - `logging.debug` - Enable debug-level log output (default: `false`)
256
+ - `logging.file` - Log file path. When empty, resolves to `~/.local/share/opencode/forge/logs/forge.log` (default: `""`). Logs remain in the data directory, only config has moved.
257
+
258
+ When enabled, logs are written to the specified file with timestamps. The log file has a 10MB size limit with automatic rotation.
259
+
260
+ #### Compaction
261
+ - `compaction.customPrompt` - Use a custom compaction prompt optimized for session continuity (default: `true`)
262
+
263
+ #### Messages Transform
264
+ - `messagesTransform.enabled` - Enable the messages transform hook that handles graph injection and Architect read-only enforcement (default: `true`)
265
+ - `messagesTransform.debug` - Enable debug logging for messages transform (default: `false`)
266
+
267
+ #### Execution
268
+ - `executionModel` - Model override for plan execution sessions, format: `provider/model` (e.g. `anthropic/claude-haiku-3-5-20241022`). When set, `plan-execute` uses this model for the new Code session. When empty or omitted, OpenCode's default model is used (typically the `model` field from `opencode.json`). **Recommended:** Set this to a fast, cheap model (e.g. Haiku or MiniMax) and use a smart model (e.g. Opus) for the Architect session — planning needs reasoning, execution needs speed.
269
+
270
+ #### Loop
271
+ - `loop.enabled` - Enable iterative development loops (default: `true`)
272
+ - `loop.defaultMaxIterations` - Default max iterations for loops, 0 = unlimited (default: `15`)
273
+ - `loop.cleanupWorktree` - Auto-remove worktree on cancel (default: `false`)
274
+ - `loop.defaultAudit` - Run auditor after each coding iteration by default (default: `true`)
275
+ - `loop.model` - Model override for loop sessions (`provider/model`), falls back to `executionModel` (default: `""`)
276
+ - `loop.stallTimeoutMs` - Watchdog stall detection timeout in milliseconds (default: `60000`)
277
+ - `loop.minAudits` - Minimum audit iterations required before completion (default: `1`)
278
+
279
+ #### Sandbox
280
+ - `sandbox.mode` - Sandbox mode: `"off"` or `"docker"` (default: `"off"`)
281
+ - `sandbox.image` - Docker image for sandbox containers (default: `"opencode-forge-sandbox:latest"`)
282
+
283
+ #### Graph
284
+ - `graph.enabled` - Enable graph indexing (default: `true`)
285
+ - `graph.autoScan` - Auto-scan codebase on startup (default: `true`)
286
+ - `graph.watch` - Watch for file changes (default: `true`)
287
+ - `graph.debounceMs` - Debounce delay for file watch events (default: `100`)
288
+ - `graph.maxFiles` - Maximum files to index (default: `1000`)
289
+
290
+ #### Top-level
291
+ - `defaultKvTtlMs` - Default TTL for KV store entries in milliseconds (default: `604800000` / 7 days)
292
+
293
+ #### Auditor
294
+ - `auditorModel` - Model override for the auditor agent (`provider/model`). When set, overrides the auditor agent's default model. When not set, uses platform default (default: `""`)
295
+
296
+ #### TUI
297
+ - `tui.sidebar` - Show the forge sidebar widget in OpenCode TUI (default: `true`)
298
+ - `tui.showLoops` - Display active and recent loop status in the sidebar (default: `true`)
299
+ - `tui.showVersion` - Show plugin version number in the sidebar title (default: `true`)
300
+
301
+ ## TUI Plugin
302
+
303
+ The plugin includes a TUI sidebar widget and dialog system for monitoring and managing loops directly in the OpenCode terminal interface.
304
+
305
+ ### Sidebar
306
+
307
+ The sidebar shows all loops for the current project:
308
+
309
+ - Loop name (truncated to 25 chars with middle ellipsis) with a colored status dot
310
+ - Status text: current phase for active loops, termination reason for completed/cancelled
311
+ - Clicking a **worktree loop** opens the Loop Details dialog
312
+ - Clicking a **non-worktree loop** navigates directly to its session
313
+ - **Plan indicator** — When a plan exists for the current session, a 📋 Plan link appears. Click it to open the Plan Viewer dialog.
314
+
315
+ ### Plan Viewer
316
+
317
+ When an architect session produces a plan, it is cached in the project KV store. The plan is accessible from the sidebar (📋 Plan link) or the command palette (`Memory: View plan`).
318
+
319
+ The plan viewer dialog renders the full plan as GitHub-flavored markdown with syntax highlighting:
320
+
321
+ Click `[edit]` to switch to edit mode, where you can modify the plan text directly in a textarea. Click **Save** to write changes back to the KV store, or `[view]` to return to the rendered view without saving.
322
+
323
+ ### Loop Details Dialog
324
+
325
+ The Loop Details dialog shows a detailed view of a single loop:
326
+
327
+ - Name and status badge (active / completed / error / cancelled / stalled)
328
+ - Session stats: session ID, iteration count, token usage (input/output/cache), cost
329
+ - Latest output from the last assistant message (scrollable, up to 500 chars)
330
+ - **Back** — return to the loop list (when opened from the command palette)
331
+ - **Cancel loop** — abort the active loop session (visible only when loop is active)
332
+ - **Close (esc)** — dismiss the dialog
333
+
334
+ ### Command Palette
335
+
336
+ The `Memory: Show loops` command is registered in the command palette when loops exist for the current project. It opens a list of all **worktree loops** (large dialog), then drills into the Loop Details dialog for the selected loop (medium dialog) with a Back button to return to the list.
337
+
338
+ ### Setup
339
+
340
+ When installed via npm, the TUI plugin loads automatically when added to your TUI config. The plugin is auto-detected via the `./tui` export in `package.json`.
341
+
342
+ Add to your `~/.config/opencode/tui.json` or project-level `tui.json`:
343
+
344
+ ```json
345
+ {
346
+ "$schema": "https://opencode.ai/tui.json",
347
+ "plugin": [
348
+ "opencode-forge"
349
+ ]
350
+ }
351
+ ```
352
+
353
+ For local development, reference the built TUI file directly:
354
+
355
+ ```json
356
+ {
357
+ "$schema": "https://opencode.ai/tui.json",
358
+ "plugin": [
359
+ "/path/to/opencode-forge/dist/tui.js"
360
+ ]
361
+ }
362
+ ```
363
+
364
+ TUI options are configured in `~/.config/opencode/forge-config.jsonc` under the `tui` key:
365
+
366
+ ```jsonc
367
+ {
368
+ "tui": {
369
+ "sidebar": true,
370
+ "showLoops": true,
371
+ "showVersion": true
372
+ }
373
+ }
374
+ ```
375
+
376
+ Set `sidebar` to `false` to completely disable the widget.
377
+
378
+ ## architect → code Workflow
379
+
380
+ Plan with a smart model, execute with a fast model. The architect agent researches the codebase and designs an implementation plan; the code agent implements it.
381
+
382
+ ### How Plans Work
383
+
384
+ During planning, the architect writes the plan incrementally to the project KV store — building sections, appending content, and making targeted line-based edits. The plan is cached under a session-scoped key, not generated as a single LLM response.
385
+
386
+ The user can view the cached plan at any time from the **sidebar** (📋 Plan link) or the **command palette** (`Memory: View plan`). The plan viewer renders full GitHub-flavored markdown and supports inline editing — the user can modify the plan directly before approving.
387
+
388
+ ### Execution
389
+
390
+ After the architect presents a summary, the user approves via one of four execution modes:
391
+
392
+ - **New session** — Creates a new Code session and sends the plan as the initial prompt. The architect session is aborted and the TUI navigates to the new session.
393
+ - **Execute here** — The architect session is aborted and the code agent takes over the same session immediately with the plan.
394
+ - **Loop (worktree)** — Creates an isolated git worktree and launches an iterative coding/auditing loop. When `config.sandbox.mode` is `"docker"`, the loop automatically uses Docker sandbox.
395
+ - **Loop (in-place)** — Runs an iterative coding/auditing loop in the current directory without worktree isolation.
396
+
397
+ Execution is immediate — there are no additional LLM calls between approval and execution. The system intercepts the user's approval answer, reads the cached plan from KV, and dispatches it programmatically to the code agent. The architect never processes the approval response.
398
+
399
+ Set `executionModel` in your config to a fast model (e.g., Haiku) and use a smart model (e.g., Opus) for the architect session.
400
+
401
+ ## Loop
402
+
403
+ The loop is an iterative development system that alternates between coding and auditing phases:
404
+
405
+ 1. **Coding phase** — A Code session works on the task
406
+ 2. **Auditing phase** — The Auditor agent reviews changes against project conventions and stored review findings
407
+ 3. **Session rotation** — A fresh session is created for the next iteration
408
+ 4. **Repeat** — Audit findings feed back into the next coding iteration
409
+
410
+ ### Session Rotation
411
+
412
+ Each iteration runs in a **fresh session** to keep context small and prioritize speed. After each phase completes, the current session is destroyed and a new one is created. The original task prompt and any audit findings are re-injected into the new session as a continuation prompt, so no context is lost while keeping the window clean.
413
+
414
+ ### Review Finding Persistence
415
+
416
+ Audit findings survive session rotation via the **review store**. The auditor stores each bug and warning using `review-write` with file, line, severity, and description. At the start of each audit:
417
+
418
+ - Existing findings are retrieved via `review-read`
419
+ - Resolved findings are deleted via `review-delete`
420
+ - Unresolved findings are carried forward into the review
421
+
422
+ ### Worktree Isolation
423
+
424
+ Loops default to current directory execution. Set `worktree: true` to run in an isolated git worktree with its own branch (e.g., `opencode/loop-<slug>`). In worktree mode, changes are auto-committed and the worktree is removed on completion (branch preserved for later merge).
425
+
426
+ ### Auditor Integration
427
+
428
+ After each coding iteration, the auditor agent reviews changes against project conventions and stored review findings. Findings are persisted via `review-write` scoped to the loop's branch. Outstanding findings block completion, and a minimum audit count (`minAudits`, default: `1`) must be met before the completion promise is honored.
429
+
430
+ ### Stall Detection
431
+
432
+ A watchdog monitors loop activity. If no progress is detected within `stallTimeoutMs` (default: 60s), the current phase is re-triggered. After 5 consecutive stalls, the loop terminates with reason `stall_timeout`.
433
+
434
+ ### Model Configuration
435
+
436
+ Loops use `loop.model` if set, falling back to `executionModel`, then the platform default. On model errors, automatic fallback to the default model kicks in.
437
+
438
+ ### Safety
439
+
440
+ - `git push` is denied inside active loop sessions
441
+ - Tools like `question`, `plan-execute`, and `loop` are blocked to prevent recursive loops and keep execution autonomous
442
+
443
+ ### Management
444
+
445
+ - **Slash commands**: `/loop` to start, `/loop-cancel` to cancel
446
+ - **Tools**: `loop` to start with parameters, `loop-status` for checking progress (with restart capability), `loop-cancel` to cancel
447
+ - **CLI**: `opencode-forge loop status` and `opencode-forge loop cancel` for loop management
448
+
449
+ ### Completion and Termination
450
+
451
+ The loop completes when the Code agent outputs the completion promise. It auto-terminates after `maxIterations` (if set) or after 3 consecutive errors.
452
+
453
+ By default, loops run in the current directory. Set `worktree: true` to run in an isolated git worktree instead (enables worktree creation, auto-commit, and cleanup on completion).
454
+
455
+ ## Docker Sandbox
456
+
457
+ Run loop iterations inside an isolated Docker container. Three tools (`bash`, `glob`, `grep`) execute inside the container via `docker exec`, while `read`/`write`/`edit` operate on the host filesystem. Your project directory is bind-mounted at `/workspace` for instant file sharing.
458
+
459
+ ### Prerequisites
460
+
461
+ - Docker running on your machine
462
+
463
+ ### Setup
464
+
465
+ **1. Build the sandbox image:**
466
+
467
+ ```bash
468
+ docker build -t opencode-forge-sandbox:latest container/
469
+ ```
470
+
471
+ The image includes Node.js 24, pnpm, Bun, Python 3 + uv, ripgrep, git, and jq.
472
+
473
+ **2. Enable sandbox mode in your config** (`~/.config/opencode/forge-config.jsonc`):
474
+
475
+ ```jsonc
476
+ {
477
+ "sandbox": {
478
+ "mode": "docker",
479
+ "image": "opencode-forge-sandbox:latest"
480
+ }
481
+ }
482
+ ```
483
+
484
+ **3. Restart OpenCode.**
485
+
486
+ ### Usage
487
+
488
+ Start a sandbox loop via the architect plan approval flow (select "Loop (worktree)") or directly with the `loop` tool:
489
+
490
+ ```
491
+ loop with worktree: true
492
+ ```
493
+
494
+ Sandbox is automatically enabled when `config.sandbox.mode` is set to `"docker"` and the loop uses `worktree: true`. The loop:
495
+ 1. Creates a git worktree
496
+ 2. Starts a Docker container with the worktree directory bind-mounted at `/workspace`
497
+ 3. Redirects `bash`, `glob`, and `grep` tool calls into the container
498
+ 4. Cleans up the container on loop completion or cancellation
499
+
500
+ ### How It Works
501
+
502
+ - **Bind mount** -- the project directory is mounted directly into the container at `/workspace`. No sync daemon, no file copying. Changes are visible instantly on both sides.
503
+ - **Tool redirection** -- `bash`, `glob`, and `grep` route through `docker exec` when a session belongs to a sandbox loop. The `read`/`write`/`edit` tools operate on the host filesystem directly (compatible with host LSP).
504
+ - **Git blocking** -- git commands are explicitly blocked inside the container. All git operations (commit, push, branch management) are handled by the loop system on the host.
505
+ - **Host LSP** -- since files are shared via the bind mount, OpenCode's LSP servers on the host read the same files and provide diagnostics after writes and edits.
506
+ - **Container lifecycle** -- one container per loop, automatically started and stopped. Container name format: `opencode-forge-sandbox-<worktreeName>`.
507
+
508
+ ### Configuration
509
+
510
+ | Option | Default | Description |
511
+ |--------|---------|-------------|
512
+ | `sandbox.mode` | `"off"` | Set to `"docker"` to enable sandbox support |
513
+ | `sandbox.image` | `"opencode-forge-sandbox:latest"` | Docker image to use for sandbox containers |
514
+
515
+ ### Customizing the Image
516
+
517
+ The `container/Dockerfile` is included in the project. To add project-specific tools (e.g., Go, Rust, additional language servers), edit the Dockerfile and rebuild:
518
+
519
+ ```bash
520
+ docker build -t opencode-forge-sandbox:latest container/
521
+ ```
522
+
523
+
524
+ ## Development
525
+
526
+ ```bash
527
+ pnpm build # Compile TypeScript to dist/
528
+ pnpm test # Run tests
529
+ pnpm typecheck # Type check without emitting
530
+ ```
531
+
532
+ ## License
533
+
534
+ MIT
package/config.jsonc ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "logging": {
3
+ "enabled": false,
4
+ "debug": false,
5
+ "file": ""
6
+ },
7
+ "compaction": {
8
+ "customPrompt": true
9
+ },
10
+ "messagesTransform": {
11
+ "enabled": true,
12
+ "debug": false
13
+ },
14
+ "executionModel": "",
15
+ "auditorModel": "",
16
+ // Per-agent overrides (temperature range: 0.0 - 2.0)
17
+ // "agents": {
18
+ // "architect": { "temperature": 0.0 },
19
+ // "auditor": { "temperature": 0.0 },
20
+ // "code": {}
21
+ // },
22
+ "loop": {
23
+ "enabled": true,
24
+ "defaultMaxIterations": 15,
25
+ "cleanupWorktree": false,
26
+ "defaultAudit": true,
27
+ "model": "",
28
+ "minAudits": 1,
29
+ "stallTimeoutMs": 60000
30
+ },
31
+ "sandbox": {
32
+ "mode": "off",
33
+ "image": "ocm-sandbox:latest"
34
+ },
35
+ "graph": {
36
+ "enabled": true,
37
+ "autoScan": true,
38
+ "watch": true,
39
+ "debounceMs": 100,
40
+ "maxFiles": 1000
41
+ },
42
+ "tui": {
43
+ "sidebar": true,
44
+ "showLoops": true,
45
+ "showVersion": true
46
+ }
47
+ }
@@ -0,0 +1,3 @@
1
+ import type { AgentDefinition } from './types';
2
+ export declare const architectAgent: AgentDefinition;
3
+ //# sourceMappingURL=architect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"architect.d.ts","sourceRoot":"","sources":["../../src/agents/architect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE9C,eAAO,MAAM,cAAc,EAAE,eAsJ5B,CAAA"}