Skip to main content
← Back to list
01Issue
BugShippedSwamp CLI
Assigneeskeeb

#413 Harness detection invents env vars for kiro/opencode/codex

Opened by keeb · 5/22/2026· Shipped 5/22/2026

Summary

src/domain/telemetry/agent_harness_detection.ts ships with predicates for kiro, opencode, and codex that check env vars those harnesses do not actually export. Result: dashboards see Claude (and Cursor) but report no detectedAiTool for any other harness, even when those harnesses are clearly driving swamp. The original PR (#1342, closes swamp-club#292) flagged these as TODOs awaiting confirmation; this is the confirmation pass — verified by reading each upstream's source.

Per-harness evidence

opencode — OPENCODE_VERSION and TERM_PROGRAM=opencode are wrong

From anomalyco/opencode packages/opencode/src/index.ts:109-110:

process.env.AGENT = "1"
process.env.OPENCODE = "1"
process.env.OPENCODE_PID = String(process.pid)
  • OPENCODE_VERSION is build-time only (baked into the binary via script/build.ts); it is never exported at runtime.
  • TERM_PROGRAM=opencode is not set — opencode is a TUI and does not override TERM_PROGRAM.
  • The real universal marker is OPENCODE=1, set at process startup and inherited by every child.
  • Opencode also exports AGENT=1 itself, which is why the generic fallback in genericAgentDetected() does fire — but detectedAiTool stays undefined, masking opencode in telemetry.

codex — CODEX_AGENT_HARNESS does not exist

From openai/codex codex-rs/core/src/spawn.rs and codex-rs/core/src/sandboxing/mod.rs:

pub const CODEX_SANDBOX_NETWORK_DISABLED_ENV_VAR: &str = "CODEX_SANDBOX_NETWORK_DISABLED";
pub const CODEX_SANDBOX_ENV_VAR: &str = "CODEX_SANDBOX";
// ...
if !network_sandbox_policy.is_enabled() {
    cmd.env(CODEX_SANDBOX_NETWORK_DISABLED_ENV_VAR, "1");
}
#[cfg(target_os = "macos")]
if sandbox == SandboxType::MacosSeatbelt {
    env.insert(CODEX_SANDBOX_ENV_VAR.to_string(), "seatbelt".to_string());
}
  • Codex calls env_clear() before each shell-tool spawn, so parent env does not propagate.
  • The only stable signals on a child process are CODEX_SANDBOX_NETWORK_DISABLED=1 (any platform, when network sandbox is enabled — the default) and CODEX_SANDBOX=seatbelt (macOS only).
  • CODEX_AGENT_HARNESS is fabricated and matches nothing.
  • Known limit (not fixable from our side): if a user disables sandboxing entirely (--dangerously-bypass-approvals-and-sandbox), no codex-identifying env var is set. We can detect codex when it is sandboxed; without sandbox, codex is invisible until upstream adds a stable identity marker.

kiro — KIRO_AGENT does not exist; we are also missing the agent-session signal

From kiro.dev docs (/docs/cli/reference/built-in-tools/) and confirmed by an independent blog post:

  • TERM_PROGRAM=kiro is real and set in IDE terminal sessions. Current predicate is correct on this half.
  • KIRO_AGENT=1 is fabricated — not mentioned in any Kiro source, docs, or community reference.
  • Missing signal: when Kiro's CLI agent drives a shell command, it exports AGENT_CONTEXT_OUT and AGENT_DISPLAY_OUT (FIFO paths). Non-empty AGENT_CONTEXT_OUT is the agent-driven case we actually want — TERM_PROGRAM=kiro only catches a human in Kiro's terminal, not the agent invoking swamp.

What needs to change

In src/domain/telemetry/agent_harness_detection.ts:

  1. opencode predicateenv.OPENCODE === "1". Drop OPENCODE_VERSION and TERM_PROGRAM=opencode.
  2. kiro predicate → keep TERM_PROGRAM === "kiro"; drop KIRO_AGENT; add AGENT_CONTEXT_OUT non-empty as the agent-driven signal.
  3. codex predicateCODEX_SANDBOX_NETWORK_DISABLED non-empty OR CODEX_SANDBOX defined. Drop CODEX_AGENT_HARNESS. Add a code comment documenting the no-sandbox blind spot.
  4. RELEVANT_ENV_VARS: add OPENCODE, AGENT_CONTEXT_OUT, CODEX_SANDBOX_NETWORK_DISABLED, CODEX_SANDBOX; remove KIRO_AGENT, OPENCODE_VERSION, CODEX_AGENT_HARNESS.
  5. Update agent_harness_detection_test.ts to mirror — existing tests assert on the fabricated env vars, so they pass against fiction and would silently keep passing under the wrong implementation.

Reproduction

  1. Launch swamp from inside an opencode/codex/kiro CLI session.
  2. Inspect a telemetry entry: detectedAiTool is undefined even though agentSessionDetected may be true via the generic AGENT fallback (opencode case) or via CODEX_SANDBOX_NETWORK_DISABLED not matching any predicate (codex case).
  3. Confirm with env | grep -iE 'opencode|codex|kiro|agent' inside each harness — none of the env vars our predicates look for are set; the ones that are set don't match any predicate.

Environment

  • swamp 7e04104b (main, dev build)
  • File: src/domain/telemetry/agent_harness_detection.ts
  • Original feature PR: #1342 / swamp-club#292 (shipped)

Out of scope

  • Detecting codex when its sandbox is fully disabled — requires upstream to expose a stable identity env var. Worth filing upstream as a feature request once this lands.
02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 3 MOREFINDINGS+ 3 MOREPR_MERGED+ 1 MORENOTIFICATION_SKIPPED

Shipped

5/22/2026, 5:17:38 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
keeb assigned keeb5/22/2026, 4:52:41 PM

Sign in to post a ripple.