-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathforge-config.jsonc
More file actions
203 lines (187 loc) · 9.45 KB
/
Copy pathforge-config.jsonc
File metadata and controls
203 lines (187 loc) · 9.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
{
// Data directory for plugin storage (forge.db, logs)
// When empty, resolves to ~/.local/share/opencode/forge (or XDG_DATA_HOME equivalent)
"dataDir": "",
// Logging configuration
"logging": {
"enabled": false,
"debug": false,
"file": ""
},
// Session compaction settings
"compaction": {
"customPrompt": true,
"maxContextTokens": 0
},
// Messages transform hook for read-only enforcement
"messagesTransform": {
"enabled": true,
"debug": false
},
// Model override for plan execution sessions (format: "provider/model")
"executionModel": "",
// Model override for the auditor agent (format: "provider/model")
"auditorModel": "",
// Default variant (reasoning/thinking-effort) for the execution model (e.g., "high", "max")
"executionVariant": "",
// Default variant for the auditor model (independent; does not inherit executionVariant)
"auditorVariant": "",
// Ordered auditor fallback models used when the current auditor model hits a provider
// usage/auth limit mid-loop. Tried in order. Entries are a "provider/model" string, or
// an object to pin a variant to that fallback; auditorVariant is NOT inherited, so a
// string entry runs with no variant. Empty/omitted means a limited auditor terminates
// the loop as before.
// "auditorFallbackModels": ["provider/model-b", { "model": "provider/model-c", "variant": "high" }],
// Iterative development loop settings
"loop": {
"enabled": true,
"defaultMaxIterations": 15,
"cleanupWorktree": false,
"stallTimeoutMs": 60000,
"maxConsecutiveStalls": 5, // 0 = disabled; default 5
"busyStallTimeoutMs": 900000, // busy with no tool activity or streamed content → abort + continue; 0 = disabled
// Worktree loop completion logging (off by default)
"worktreeLogging": {
"enabled": false,
"directory": ""
}
// Post-completion action (skill and/or prompt) run inside the worktree before teardown.
// (disabled by default)
// "postAction": {
// "enabled": false,
// "skill": "pr-review",
// "prompt": "Auto-defer anything needing clarification; do not use the question tool.",
// "model": "provider/model" // optional: override model (defaults to auditor model chain)
// },
// Host directories loop/audit/post-action sessions may read despite worktree isolation
// (e.g. an Obsidian vault). Use absolute host paths; governs Read/Glob/Grep (external_directory).
// "allowExternalDirectories": ["/abs/host/path/to/vault"]
//
// Per-tool deny overrides for loop, audit, and post-action sessions, layered between the
// external-directory allow rules and Forge's structural denies. Entries are a tool name
// (pattern "*"), or an object to scope the pattern. Only "deny" entries are supported;
// an "allow" array is ignored with a warning. Forge-managed permissions ("*",
// "external_directory", and every structural deny) are rejected, as are blanket denies of
// Forge-required permissions ("review-read", "plan-read", "section-read", "plan-adjust",
// "bash", "read") — scope those with a pattern instead of denying them outright.
// "permissions": {
// "deny": ["browser_navigate", { "permission": "bash", "pattern": "git push *" }]
// }
//
// Shared scratch/temp directory available to loops in BOTH modes. It is added to the
// external_directory allowlist and, for sandboxed loops, bind-mounted read-write at the
// identical container path so absolute temp paths match host<->container. Created on startup
// if missing. Defaults to "/tmp/oc-forge".
// "tmpDir": "/tmp/oc-forge"
//
// Inline opencode config written as opencode.jsonc into each loop worktree (skip-if-exists;
// never overwrites a committed opencode.json/opencode.jsonc). Primarily for enabling per-loop
// MCP servers. The written file is git-excluded so it never enters loop commits.
// "worktreeOpencodeConfig": {
// "mcp": {
// "my-server": { "type": "local", "command": ["npx", "some-mcp-server"], "enabled": true }
// }
// }
},
// Max loops from one group running concurrently. Also bounds concurrent planning passes. Default 3.
"groupLaunch": {
"maxConcurrentLoops": 3
},
// Sandbox configuration. Sandbox is optional: loops always run in an isolated git worktree, and
// when the msb CLI is installed and `msb doctor` reports a usable host a sandbox is provisioned
// automatically. Set "enabled": false to force worktree-only mode even when msb is available.
"sandbox": {
"enabled": true,
"mode": "msb",
"image": "oc-forge-sandbox:latest",
"imageFeatures": {
"browserControl": false
}
// Mount the source project directory read-only at its identical host path. Defaults to true.
// "mountProjectReadonly": true,
// Network access configuration. msb egress is allow-by-default: with no hosts configured,
// forge passes no network flags and all PUBLIC egress is allowed. Restriction is opt-in —
// once any host is listed, forge passes `--net-default deny` plus one `--net-rule allow@<host>`
// per validated host, and only those hosts are reachable. Host loopback (host.microsandbox.internal
// and the gateway IP) is always unreachable from inside the sandbox. Invalid host entries
// (e.g. a bare "*", port-qualified hosts, or single-label hosts) are skipped and logged rather
// than failing the loop launch; if every configured host is invalid, egress is fully denied
// rather than falling back to allow-all. Egress rules cannot be changed on a live sandbox —
// a newly configured host requires recreating the sandbox.
// Host environment variables pass through at create time as bare names (msb resolves each name
// from its own environment, so values never appear on forge's command line); host-held
// secrets are bound reference-only and exposed inside the sandbox as $MSB_<env> placeholders
// that msb substitutes only for the listed hosts.
// "network": {
// // OPT-IN egress restriction: hosts the sandbox may reach. Leave empty (or omit) for
// // msb's default of allowing all public egress.
// "allow": ["registry.npmjs.org"],
// // Host environment variable names to inject into the sandbox at create time.
// // Only names set in the host process are injected, as ordinary guest environment
// // variables (msb resolves a bare name from its own environment, so the value never
// // appears on forge's command line). Host-held credentials belong in "secrets" instead,
// // which never enter the guest.
// "env": ["MY_VAR"],
// // Host-held credentials bound at create time. Each entry references a host env var and
// // the hostnames allowed to receive its real value at the network boundary; the value
// // never enters the guest. The named variable must be exported in the environment that
// // launches opencode: a bound secret with a missing variable makes every sandboxed shell
// // command fail, and forge logs a warning naming the variable.
// "secrets": [
// { "env": "NPM_TOKEN", "hosts": ["registry.npmjs.org"] }
// ]
// },
// Additional host directories to bind-mount into the sandbox at their identical host path.
// "readonly" defaults to true (read-only); set false to grant the sandbox read-write access.
// "mounts": [
// { "host": "/abs/host/reference" },
// { "host": "/abs/host/cache", "readonly": false }
// ]
},
// TUI sidebar widget configuration
"tui": {
"sidebar": true,
"showVersion": true,
// Optional keybinds for Forge palette commands. Leave a value empty to
// register the command without a default binding (run it from the palette).
"keybinds": {
"executePlan": "<leader>f",
"dashboard": ""
}
},
// Dashboard HTTP server bind address (`pnpm dashboard` and the TUI "Open dashboard" command).
// Defaults to loopback only. Use "0.0.0.0" to listen on all interfaces so the dashboard is
// reachable from other devices on a LAN or VPN.
// WARNING: the dashboard has NO authentication. A non-loopback bind exposes every loop plan,
// goal, audit result, finding, and cost to anyone who can reach the port. Restrict access with
// a firewall or VPN.
// Consecutive ports (port..port+9) are tried when the configured port is busy.
"dashboard": {
"host": "localhost",
"port": 4747
},
// TTL in ms for completed/cancelled loops before cleanup. Default: 604800000 (7 days)
"completedLoopTtlMs": 604800000
// Remote opencode servers available as loop launch targets.
// Each entry requires "name" (display name in the TUI picker) and "url" (base URL of the server).
// Optional fields: username (default "opencode"), gitRemote (default "origin"), sandbox (default true).
// Omit "password" when the remote runs without auth.
// "sandbox" must mirror the remote server's actual sandbox capability. See docs/configuration.md#remotes.
// "remotes": [
// {
// "name": "my-server",
// "url": "http://192.168.1.20:4096",
// "password": "",
// "username": "opencode",
// "gitRemote": "origin",
// "sandbox": true
// }
// ]
// Per-agent overrides (temperature range: 0.0 - 2.0)
// Keys are agent display names (e.g., "code", "architect", "auditor")
// "agents": {
// "architect": { "temperature": 0.0 },
// "auditor": { "temperature": 0.0 },
// "code": { "temperature": 0.7 }
// }
}