gaslamp 2.2.2 → 3.0.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.
package/README.md CHANGED
@@ -6,175 +6,143 @@
6
6
  [![node](https://img.shields.io/node/v/gaslamp)](https://www.npmjs.com/package/gaslamp)
7
7
  [![license](https://img.shields.io/badge/license-AGPL--3.0--or--later-blue)](LICENSE)
8
8
 
9
- Let Claude Code and Codex consult each other from the shell — and reach Gemini
10
- and Grok as read-only consult targets.
9
+ Let coding agents consult each other from the shell: Claude, Codex, Gemini and
10
+ Grok.
11
11
 
12
12
  ```sh
13
- gaslamp codex "review this diff for races: …" # Claude asks Codex
14
- gaslamp claude "verify this proof sketch: …" # Codex asks Claude
15
- git diff | gaslamp codex "review for races:" # piped stdin rides as evidence
16
- gaslamp codex - < notes/design-spar.md # or: the whole prompt from a file
17
- gaslamp claude --thread api-spar "counterpoint: …" # named session, continued
18
- gaslamp gemini "is this migration reversible? …" # Gemini via Antigravity CLI
19
- gaslamp grok "what does this stack trace mean? …" # Grok via Grok Build
13
+ gaslamp codex "review this diff for races: …" # Claude asks Codex
14
+ gaslamp claude "verify this proof sketch: …" # Codex asks Claude
15
+ git diff | gaslamp codex "review for races:" # piped stdin rides along as evidence
16
+ gaslamp gemini "what changed in the v5 API? cite URLs" # Gemini, through Antigravity CLI
17
+ gaslamp grok --thread launch "how did people react?" # Grok, through Grok Build
20
18
  ```
21
19
 
22
- Each call blocks until the reply, then prints it plus a greppable trailer:
20
+ Each call blocks until the reply, then prints it and one line:
23
21
 
24
22
  ```
25
23
  lamplight
26
- [gaslamp] job: cx-20260612-142457-744e · session: 019ebdb9-… · resume: gaslamp codex --resume 019ebdb9-… · tok: 32k→60
24
+ [gaslamp] job cx-20261026-142457-744e · continue: gaslamp codex --resume cx-20261026-142457-744e
27
25
  ```
28
26
 
29
- The agent backgrounds the call with its own facility (Claude Code:
30
- `run_in_background`; Codex: its background terminal), keeps working, and gets
31
- the reply when it lands — so several consults run in parallel and replies
32
- trickle in. No MCP servers, no daemon: asynchrony is the harness's job, and
33
- gaslamp stays a thin wrapper around `claude -p` / `codex exec`.
34
-
35
- > 1.x was a pair of MCP servers. 2.0 replaced them with this CLI: MCP tool
36
- > calls are blocking and serial, Codex's MCP client enforced a per-call
37
- > timeout that killed long consults, and its per-directory trust gate could
38
- > stall calls invisibly. All three problems are structural to MCP and absent
39
- > from a shell call.
27
+ The calling agent runs the command in the background (`run_in_background` in
28
+ Claude Code, a background terminal in Codex), keeps working, and gets the reply
29
+ when it lands, so several consults run at once. No MCP servers, no daemon:
30
+ asynchrony is the harness's job, and gaslamp stays a thin wrapper around each
31
+ agent's headless mode.
40
32
 
41
33
  ## Requirements
42
34
 
43
- Both CLIs installed and logged in: [Claude Code](https://code.claude.com/docs)
44
- and [Codex](https://developers.openai.com/codex). Node ≥ 18. For the other two
45
- targets, [Antigravity CLI](https://antigravity.google/docs/cli/headless/)
46
- (`agy`, signed in once interactively) and/or
47
- [Grok Build](https://docs.x.ai/build/overview) (`grok login`).
35
+ Node ≥ 18, and whichever agents you want to reach, installed and signed in:
36
+ [Claude Code](https://code.claude.com/docs), [Codex](https://developers.openai.com/codex),
37
+ [Antigravity CLI](https://antigravity.google/docs/cli/headless/) (`agy`, signed
38
+ in once interactively), [Grok Build](https://docs.x.ai/build/overview) (`grok login`).
39
+ Fenced Claude consults on Linux need `bubblewrap` and `socat`, which Claude
40
+ Code's sandbox runs on.
48
41
 
49
42
  ## Install
50
43
 
51
44
  ```sh
52
45
  npm install -g gaslamp
53
- gaslamp setup # allowlist the command in ~/.claude/settings.json
54
- gaslamp setup --skill # …and install the gaslamp skill for BOTH agents
46
+ gaslamp setup
55
47
  ```
56
48
 
57
- `setup` allowlists the command so a consult doesn't stall on a permission
58
- prompt. It does **not** touch your agent instructions: a CLI can't
59
- self-advertise the way MCP tools did, so each agent needs to learn gaslamp
60
- exists from somewhere. The clean way is `--skill`: both CLIs speak the same
61
- SKILL.md standard, so one flag installs a direction-aware skill on each side
62
- (`~/.claude/skills/gaslamp/` teaching Claude to consult Codex,
63
- `$CODEX_HOME/skills/gaslamp/` teaching Codex to consult Claude). The manual
64
- alternative is a short note pasted into each agent's instruction file.
65
-
66
- **`~/.claude/CLAUDE.md`** — so Claude consults Codex:
67
-
68
- > Hand work to Codex for a second pair of eyes — verify a fix, spar on a design,
69
- > review a diff, diagnose with fresh context. Send raw evidence (errors, diffs,
70
- > commands), not just your framing.
71
- >
72
- > ```
73
- > gaslamp codex [--thread <name>] [--model <m>] [--sandbox <mode>] "<prompt>"
74
- > git diff | gaslamp codex "…" # piped stdin rides as an evidence block
75
- > gaslamp codex --json --schema '<json-schema>' "…" # typed reply in .data
76
- > gaslamp fleet codex -n N "…" # fan out N takes in one command
77
- > ```
78
- >
79
- > Run it as a background shell task (`run_in_background`) and keep working — the
80
- > reply lands when it's done; several can run in parallel. A consult is one hop
81
- > (the consulted agent can't consult back), so own the synthesis. `gaslamp jobs`
82
- > lists records, `gaslamp poll <job|--last>` fetches one (exit 10 = running),
83
- > `gaslamp threads` lists named sessions.
84
-
85
- **`~/.codex/AGENTS.md`** — so Codex consults Claude: the same block with
86
- `claude`/`Claude` in place of `codex`/`Codex`, and "run it in your background
87
- terminal, check back between steps" in place of the `run_in_background` line.
88
-
89
- ### From source
49
+ `setup` links gaslamp's skill into `~/.claude/skills/` and
50
+ `$CODEX_HOME/skills/`, which is how both agents learn the command exists, and
51
+ allowlists `Bash(gaslamp *)` in `~/.claude/settings.json` so a consult doesn't
52
+ stall on a permission prompt. It is idempotent and never touches an agent's
53
+ instruction files. The skill is a link into the installed package, so it
54
+ always matches the binary.
90
55
 
91
- ```sh
92
- git clone https://github.com/a9lim/gaslamp
93
- cd gaslamp
94
- ./setup.sh # === gaslamp setup --local (pins this checkout's path)
95
- ```
56
+ From source: clone, `npm link`, `gaslamp setup`.
96
57
 
97
58
  ## CLI
98
59
 
99
60
  ```
100
- gaslamp claude [opts] <prompt|-> Consult Claude (blocks until the reply).
101
- gaslamp codex [opts] <prompt|-> Consult Codex (blocks until the reply).
102
- gaslamp gemini [opts] <prompt|-> Consult Gemini through Antigravity CLI (agy).
103
- gaslamp grok [opts] <prompt|-> Consult Grok through Grok Build.
104
- gaslamp fleet <backend> [opts] Fan out a fleet of consults in one command.
105
- gaslamp fleet --resume <fleet-id> Finish an interrupted fleet.
106
- gaslamp jobs [-n N] [--json] List consult records, newest first.
107
- gaslamp threads List named threads, latest activity first.
108
- gaslamp poll <job|fleet|--last> [--json] One record's reply/status (exit 10 = running).
109
- gaslamp tail <job|--last> Follow one consult's events as one-liners.
110
- gaslamp setup [--local] [--skill] Allowlist the command; --skill installs the
111
- gaslamp skill for both agents.
112
-
113
- Consult options:
114
- --resume <session|job> Continue a session (a prior job id works too).
115
- --thread <name> Named session: continue if bound, else start + bind.
116
- --model <m> An exact model id, or a tier word: claude's own
117
- aliases (fable, opus, sonnet, haiku); codex tiers
118
- (astra, sol, luna) and gemini tiers (argon, flash)
119
- resolve to the newest id in that harness's catalog.
120
- --effort <level> Reasoning effort (native on every backend).
121
- --schema <file|json> JSON Schema for the reply; --json gains data.
122
- --label <s> Tag the job record (shows in gaslamp jobs).
123
- --sandbox <mode> claude: read-only | danger-full-access
124
- codex: read-only | workspace-write | danger-full-access
125
- gemini: read-only | danger-full-access
126
- grok: read-only | workspace-write | danger-full-access
127
- --raw Skip the consult preamble.
128
- --cwd <dir> Working directory for the consult.
129
- --json {backend, jobId, sessionId, status, exitCode,
130
- content, label?, usage?, data?}
131
-
132
- Fleet options (plus the consult options above, applied to every consult):
133
- -n, --count N Replicate the prompt across N fresh sessions.
134
- -j, --concurrency N Max consults in flight (default 4).
135
- --stream Print replies as they complete (--json: JSONL).
136
- - < tasks.jsonl One task per line: {"prompt", model?, sandbox?,
137
- effort?, cwd?, resume?, thread?, label?, schema?,
138
- raw?} or a bare prompt.
61
+ gaslamp <claude|codex|gemini|grok> [opts] <prompt|-> Consult one; blocks until the reply.
62
+ gaslamp jobs [-n N] [--json] Recent consults, newest first.
63
+ gaslamp poll <job|--last> [--json] One consult's reply (exit 10 = running).
64
+ gaslamp threads Named conversations, latest first.
65
+ gaslamp setup Link the skill, allowlist the command.
66
+
67
+ --thread <name> Name the conversation: start it, or continue it.
68
+ --resume <job-id> Continue an unnamed consult's conversation.
69
+ --model <m> An exact id or a tier: claude fable|opus|sonnet|haiku,
70
+ codex astra|sol|luna, gemini argon|flash.
71
+ --effort <level> low|medium|high|xhigh|max.
72
+ --sandbox <mode> read-only | workspace-write | danger-full-access.
73
+ --cwd <dir> Where the consult runs.
74
+ --schema <file|json> JSON Schema for the reply (with --json: parsed into data).
75
+ --json {backend, jobId, status, thread, content, error?, data?}
139
76
  ```
140
77
 
141
- ## Evidence on stdin
78
+ Tier words resolve against each harness's own model catalog, so a new
79
+ generation is picked up without a gaslamp release. A gemini consult always
80
+ pins a Gemini model (argon unless you say otherwise): Antigravity also serves
81
+ Claude and GPT models under the same account.
142
82
 
143
- A prompt argument plus piped stdin composes them: the prompt frames, stdin is
144
- the evidence, appended as a `<stdin>` block (codex's own convention for the
145
- case, applied to both backends):
83
+ ## Conversations
84
+
85
+ `--thread <name>` names a conversation. The first consult with a name starts
86
+ it and every later one continues it, so you never handle session ids:
146
87
 
147
88
  ```sh
148
- git diff | gaslamp codex "review this diff for races:"
149
- cargo test 2>&1 | gaslamp claude "why is this failing?"
89
+ gaslamp codex --thread api-spar "opening take: …"
90
+ gaslamp codex --thread api-spar "counterpoint: …" # same conversation
91
+ gaslamp threads
150
92
  ```
151
93
 
152
- Send raw evidence — errors, diffs, failing output — not just your framing of
153
- it; the fresh-context advantage works on facts. A bare `-` (or piping with no
154
- prompt argument) still reads the whole prompt from stdin.
94
+ A reused name carries the earlier context along, so name a conversation for
95
+ its subject, and use a new name for an independent second opinion. A thread
96
+ belongs to the directory it started in. From anywhere else, gaslamp refuses
97
+ (continue it with `--cwd`, or pick another name), so a common name can't pull
98
+ one repository's conversation into another. One consult runs per conversation
99
+ at a time; a second gets exit 5. Without `--thread`, a consult is a one-off,
100
+ and the trailer's `--resume <job-id>` still continues it.
101
+
102
+ ## Sandboxes
103
+
104
+ | | omitted | read-only | workspace-write | danger-full-access |
105
+ |---|---|---|---|---|
106
+ | claude | its own config | Claude Code's sandbox, no writes | Claude Code's sandbox, cwd only | no checks |
107
+ | codex | its own config | codex's sandbox | codex's sandbox | no checks |
108
+ | gemini | read-only | Seatbelt, no writes (macOS) | Seatbelt, cwd only (macOS) | no checks |
109
+ | grok | read-only | grok's sandbox | grok's sandbox | no checks |
110
+
111
+ The fenced modes are enforced by the OS, and a fence that can't start refuses
112
+ the consult instead of running it unfenced. "No writes" means nothing outside
113
+ the harness's own state and temp dirs. The fences cover the filesystem, not
114
+ the network: a read-only consultee can still search and fetch. Claude Code's
115
+ sandbox wraps Bash commands only, so gaslamp also turns off Claude's file-edit
116
+ tools in read-only. A fenced Claude consult loads none of your Claude settings
117
+ files (only managed settings), because their sandbox exceptions would merge
118
+ into the fence: it runs without your hooks, env and permission rules.
119
+ Managed (organization) Claude settings still apply, and any sandbox exceptions
120
+ they grant apply inside the fence too. Grok's
121
+ and Gemini's own permission layers are skipped; their fence is the kernel's. Gemini's fence is Seatbelt (`sandbox-exec`) with agy's own
122
+ permission layer skipped. Seatbelt doesn't exist on Linux and doesn't nest
123
+ inside another sandbox, so in those environments a fenced gemini consult is
124
+ refused (exit 4).
125
+
126
+ Inside a sandboxed Codex with network off, no consult can reach its provider;
127
+ gaslamp detects `CODEX_SANDBOX_NETWORK_DISABLED=1` and refuses (exit 4)
128
+ instead of timing out.
155
129
 
156
- ## Threads
130
+ ## Evidence on stdin
157
131
 
158
- `--thread <name>` is a named session: continue it if the name is bound, start
159
- and bind it if not — idempotent, no fishing session UUIDs out of old trailers.
132
+ A prompt argument plus piped stdin composes them: the prompt frames, and
133
+ stdin is appended as a `<stdin>` block. A bare `-`, or piping with no prompt
134
+ argument, reads the whole prompt from stdin.
160
135
 
161
136
  ```sh
162
- gaslamp codex --thread api-spar "opening take: …"
163
- gaslamp codex --thread api-spar "counterpoint: …" # same conversation
164
- gaslamp threads # list them
137
+ cargo test 2>&1 | gaslamp claude "why is this failing?"
138
+ gaslamp codex - < notes/design-spar.md
165
139
  ```
166
140
 
167
- A thread is one pointer file under `~/.gaslamp/threads/`, re-pointed on every
168
- consult. This matters doubly for claude, where each resume forks a *new*
169
- session id — the pointer chases it automatically, which manual `--resume`
170
- juggling cannot.
171
-
172
141
  ## Typed replies
173
142
 
174
- `--schema <file|inline-json>` plumbs a JSON Schema to each backend's native
175
- structured output (`claude --json-schema` / `codex exec --output-schema`); the
176
- `--json` envelope then carries `data`, the parsed object. A reply that fails to
177
- parse marks the consult **failed** — trust the exit code.
143
+ `--schema` plumbs a JSON Schema to each backend's native structured output.
144
+ With `--json` the parsed object lands in `data`, and a reply that doesn't
145
+ parse fails the consult.
178
146
 
179
147
  ```sh
180
148
  gaslamp codex --json --schema '{"type":"object","properties":{"verdict":
@@ -182,170 +150,60 @@ gaslamp codex --json --schema '{"type":"object","properties":{"verdict":
182
150
  "is this fix correct? …" | jq .data.verdict
183
151
  ```
184
152
 
185
- One backend asymmetry, papered over: OpenAI's endpoint only accepts *strict*
186
- schemas (every object needs `additionalProperties:false` and all properties
187
- required), so gaslamp strictifies schemas on the way to codex — spell optional
188
- fields nullable (`{"type":["string","null"]}`) rather than leaving them out of
189
- `required`. Claude takes the schema as written.
190
-
191
- ## The consult preamble
192
-
193
- A consulted agent gets a few fixed lines of framing (claude via
194
- `--append-system-prompt`, codex prepended as a `<gaslamp_consult>` block): it
195
- is a one-hop consult, its final message returns verbatim to the calling agent,
196
- deliver the deliverable. Without this, consulted agents reply conversationally
197
- or promise work instead of doing it. `--raw` drops it. It is fixed and tiny by
198
- design — not a context-injection hook.
199
-
200
- ## Fleets
201
-
202
- `gaslamp fleet` fires a whole batch of consults from one command and blocks
203
- until every reply is in — `-n N "<prompt>"` runs one prompt across N fresh
204
- sessions (voting, diverse sampling), or a JSONL manifest on stdin runs one
205
- `{prompt, model?, sandbox?, cwd?, resume?, label?}` task per line:
206
-
207
- ```sh
208
- gaslamp fleet codex -n 5 "spot the worst bug in this diff: …" # 5 takes, vote
209
- gaslamp fleet claude - < tasks.jsonl # one task/line
210
- gaslamp fleet codex -n 8 --json "…" | jq '.results[].content' # structured
211
- gaslamp fleet codex -n 4 --stream --json "…" # JSONL as they land
212
- gaslamp fleet --resume fl-20260702-… # finish an interrupted one
213
- ```
214
-
215
- Each task is a normal consult — its own job record and resumable session — so a
216
- killed fleet costs in-flight turns, not sessions. Two safety defaults at N:
217
- fleets run `--sandbox read-only` unless you opt into writes (N agents writing one
218
- directory race), and a manifest that resumes the same session or thread twice is
219
- refused (they'd deadlock on the session lock). `gaslamp poll <fleet-id>` regroups
220
- a fleet's replies later. It's the same move as backgrounding one consult, one
221
- layer up — and it's the only one-command fan-out Codex has, since (unlike Claude
222
- Code) it has no built-in agent-workflow tool.
153
+ OpenAI only accepts *strict* schemas (every object closed, every property
154
+ required), so gaslamp strictifies them on the way to codex. Spell an optional
155
+ field nullable (`{"type":["string","null"]}`) rather than leaving it out of
156
+ `required`.
223
157
 
224
- `--stream` prints each reply the moment it completes (completion order) so the
225
- caller can peek partial output mid-run; with `--json` it becomes explicit JSONL —
226
- one result line per reply, then a `fleet.done` line — leaving the collected
227
- single-object `--json` contract untouched.
228
-
229
- `fleet --resume <fleet-id>` finishes an interrupted fleet from its stored
230
- manifest: done children replay their recorded replies, a killed child whose
231
- session was captured is resumed with a fixed finish-and-deliver nudge (the
232
- session already holds the prompt and partial work), and everything else reruns
233
- fresh. The new fleet record points back via `resumedFrom`.
234
-
235
- ## Job records
158
+ ## Records
236
159
 
237
160
  Every consult writes through to `~/.gaslamp/jobs/<id>/` as it runs: the
238
- prompt, the raw backend event stream, the reply, stderr, and a `meta.json`
239
- whose session id is recorded the moment the backend reports it. If the
240
- harness kills a consult mid-flight, the whole child process group dies with
241
- it (no orphans silently burning API quota) — but the session survives on the
242
- backend's side, so recovery is `--resume <session>`, not a lost half hour.
243
-
244
- Token usage lands in the record too (claude's result usage + cost; codex's
245
- per-turn usage, summed) and shows in the trailer — fleets are quota-shaped,
246
- so quota is visible. `gaslamp jobs --json` and `gaslamp poll <id> --json`
247
- make the records scriptable; `gaslamp tail <job|--last>` follows a running
248
- consult's events as uniform one-liners across every backend's schema.
249
-
250
- Each record also carries **provenance**, because a vendor can change the model
251
- or the system prompt behind a stable product name: the provider and harness
252
- version, the model the backend reported answering with (`unknown` where it
253
- reports none — codex), the tier word and the id actually passed, the
254
- permission mode and effective sandbox, a hash of the vendor system prompt where
255
- the harness exposes one (grok) or `known: false`, the web/X retrieval tools the
256
- consultee had and the ones it used, and the gaslamp version and git revision.
257
-
258
- Two concurrent consults into the same session would race, so gaslamp refuses
259
- the second (exit 5) until the first finishes.
260
-
261
- ## Permissions
262
-
263
- A claude or codex consult with no `--sandbox` runs with the consulted agent's
264
- own config — exactly as that agent would behave if you drove it yourself.
265
- (Gemini and Grok consults default to read-only instead; see below.) Overrides:
266
- `read-only` forces an advisory, no-edit reviewer on either backend;
267
- `danger-full-access` forces full read/write. Claude has no filesystem
268
- sandbox, so `workspace-write` there is a usage error rather than a silent
269
- lie (Codex supports all three).
270
-
271
- Note for sandboxed Codex setups: the gaslamp CLI runs *inside* Codex's
272
- per-command sandbox (1.x's MCP server ran outside it). Under the default
273
- `workspace-write` sandbox, network is disabled and a consulted agent could
274
- reach neither Anthropic nor OpenAI — gaslamp detects this
275
- (`CODEX_SANDBOX_NETWORK_DISABLED=1`) and refuses with instructions instead of
276
- timing out. Grant the call escalated permissions, or set
277
- `network_access = true` / `danger-full-access` in `~/.codex/config.toml`.
278
-
279
- ## Gemini and Grok
280
-
281
- `gaslamp gemini` drives Google's Antigravity CLI (`agy`) in print mode, the
282
- prompt on stdin as one streaming-input event; `gaslamp grok` drives xAI's Grok
283
- Build headless, prompt on stdin, `--output-format streaming-messages-json`.
284
- Same contract as the other two — blocking call, trailer, job records,
285
- threads, `--schema`, fleets — with these differences:
286
-
287
- - **Read-only by default, enforced by the harness.** Grok runs under its
288
- kernel sandbox (`--sandbox read-only`: Seatbelt on macOS, Landlock on Linux;
289
- writes only to `~/.grok` and temp dirs). Grok's permission layer is not a
290
- substitute: headless `--permission-mode default` denied its write tool but
291
- ran an arbitrary shell `touch`. On macOS, a read-only gemini consult runs
292
- agy under Seatbelt (`sandbox-exec`): it can write its own state directory
293
- (`~/.gemini/antigravity-cli`, minus the files that configure it) and temp
294
- dirs, nothing else, whatever Antigravity's permission settings say — so a
295
- user can keep `always-proceed` / `agentMode: auto` for interactive work, and
296
- search and read-only commands still run. Elsewhere (Linux, or inside a
297
- Codex sandbox, where Seatbelt does not nest) the guarantee is Antigravity's
298
- `request-review` preset: the consult refuses to start when its permission
299
- files grant more than reads, read-only git and the end_session off-ramp, or
300
- set a lax `toolPermission` or `agentMode: auto` (which approves writes and
301
- commands under any preset, unreported), and fails if init doesn't confirm
302
- the preset. That path is read-capable rather than airtight: an allowed
303
- `git diff` still accepts git's own `--output=<file>`.
304
- Antigravity has no headless `workspace-write` (`--mode accept-edits` did
305
- not enable writes in print mode), so that is a usage error there.
306
- - **A denied tool call can end the turn empty.** Both harnesses report success
307
- for it; gaslamp marks an empty reply failed and surfaces the harness's
308
- stderr. Pipe evidence in rather than asking the consultee to fetch it.
309
- - **Gemini is pinned.** Antigravity also serves Claude and GPT-OSS models under
310
- the same account; without `--model`, a gemini consult runs the newest
311
- `argon` tier, never the account default.
312
- - **The caller's harness stays home.** Their spawns drop `CLAUDE*`,
313
- `ANTHROPIC_*`, `CODEX_*` and `OPENAI_*` variables (session ids, a messaging
314
- token, account details), and Grok's vendor-compat imports are switched off
315
- for the consult: by default Grok loads `~/.claude/CLAUDE.md` as its own
316
- instructions and runs Claude's skills, MCP servers and hooks. (It also reads
317
- `~/.claude/settings.json` permissions with no switch; gaslamp's explicit
318
- `--permission-mode` overrides that file's `defaultMode`.)
319
- - **Unsigned `agy` hangs.** Without a cached sign-in, print mode prints a
320
- sign-in URL and waits forever; gaslamp stops it and says to run `agy` once.
321
- - **Sessions.** `agy --conversation <id>` resumes in place (same id); so does
322
- `grok --resume <id>`. Usage comes from Antigravity's per-step events, since
323
- its result event counts the whole conversation.
161
+ prompt, the backend's raw event stream, its stderr, the reply, and a small
162
+ `meta.json` (status, error, session, thread, directory, timing). The session is
163
+ recorded the moment the backend reports it. If the calling harness kills a
164
+ consult, the whole child process group dies with it (no orphans quietly
165
+ burning quota), but the conversation survives on the backend's side, so you
166
+ continue it instead of starting over. Failure reasons, gaslamp's own included,
167
+ land in `error` and in the trailer.
168
+
169
+ The consultee gets a few fixed lines of framing: it is a one-hop consult, its
170
+ final message returns verbatim to the caller, so deliver the deliverable.
324
171
 
325
172
  ## Recursion
326
173
 
327
- A consult is **one hop**: agents gaslamp spawns carry `GASLAMP_NESTED=1`
328
- (forced into Codex's shell env via config override, since a strict
329
- `shell_environment_policy` would strip it) and the consult verbs refuse under
330
- it. This is loop prevention, not a security boundary. Set
331
- `GASLAMP_ALLOW_RECURSION=1` to restore unbounded handoffs.
174
+ A consult is one hop: agents gaslamp spawns carry `GASLAMP_NESTED=1` (forced
175
+ into Codex's shell env through a config override, since a strict
176
+ `shell_environment_policy` would strip it), and the consult verbs refuse under
177
+ it. This is loop prevention, not a security boundary.
178
+ `GASLAMP_ALLOW_RECURSION=1` lifts it.
332
179
 
333
- ## Env knobs
180
+ ## Exit codes and environment
181
+
182
+ `0` ok · `1` failed or killed · `2` usage · `3` nested · `4` can't run here (no
183
+ network, or no OS sandbox for the mode) · `5` conversation busy · `poll`: `10`
184
+ still running.
334
185
 
335
186
  | var | default | meaning |
336
187
  |-----|---------|---------|
337
- | `GASLAMP_HOME` | `~/.gaslamp` | state dir (jobs + locks + threads) |
338
- | `GASLAMP_ALLOWED_TOOLS` | `Read,Grep,Glob,WebFetch,WebSearch` + read-only git (`Bash(git diff:*)` etc) | tools the claude `read-only` override permits, comma-separated |
339
- | `GASLAMP_ALLOW_RECURSION` | unset | allow consulted agents to consult back |
340
- | `GASLAMP_DEBUG` | unset | verbose stderr (spawn argv) |
188
+ | `GASLAMP_HOME` | `~/.gaslamp` | state dir (jobs, locks, threads) |
189
+ | `GASLAMP_ALLOW_RECURSION` | unset | let consulted agents consult back |
190
+ | `GASLAMP_DEBUG` | unset | print the spawn argv |
341
191
  | `CLAUDE_BIN` / `CODEX_BIN` / `AGY_BIN` / `GROK_BIN` | autodetected | backend binaries |
342
- | `GROK_HOME` | `~/.grok` | where grok keeps sessions (the system prompt hash is read from there) |
343
- | `GASLAMP_GEMINI_SEATBELT` | on (macOS) | `0` runs read-only gemini consults on Antigravity's preset check instead of Seatbelt |
344
- | `CODEX_HOME` | `~/.codex` | where `setup --skill` puts Codex's copy |
345
-
346
- Exit codes: `0` ok · `1` consult failed/killed · `2` usage · `3` nested
347
- refusal · `4` network-disabled sandbox · `5` session busy · `poll`: `10`
348
- still running.
192
+ | `CODEX_HOME` | `~/.codex` | where `setup` links Codex's skill |
193
+
194
+ ## Upgrading from 2.x
195
+
196
+ - `fleet` and `tail` are gone. Background several consults instead, or use your
197
+ harness's own fan-out.
198
+ - `--label` folded into `--thread`, `--raw` is gone, and `--resume` takes job
199
+ ids only.
200
+ - `meta.json` keeps only what gaslamp reads back. Provenance, usage and cost are
201
+ gone from records and output; the raw event stream still has what each
202
+ harness reported.
203
+ - Claude and Gemini gained `workspace-write`, and Claude's `read-only` is now
204
+ OS-enforced. Gemini's fenced modes need macOS.
205
+ - `setup` always installs the skill (as a link), and `--local`, `--skill`,
206
+ `GASLAMP_ALLOWED_TOOLS` and `GASLAMP_GEMINI_SEATBELT` are gone.
349
207
 
350
208
  ## Development
351
209