Relationships
#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_VERSIONis build-time only (baked into the binary viascript/build.ts); it is never exported at runtime.TERM_PROGRAM=opencodeis not set — opencode is a TUI and does not overrideTERM_PROGRAM.- The real universal marker is
OPENCODE=1, set at process startup and inherited by every child. - Opencode also exports
AGENT=1itself, which is why the generic fallback ingenericAgentDetected()does fire — butdetectedAiToolstays 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) andCODEX_SANDBOX=seatbelt(macOS only). CODEX_AGENT_HARNESSis 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=kirois real and set in IDE terminal sessions. Current predicate is correct on this half.KIRO_AGENT=1is 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_OUTandAGENT_DISPLAY_OUT(FIFO paths). Non-emptyAGENT_CONTEXT_OUTis the agent-driven case we actually want —TERM_PROGRAM=kiroonly catches a human in Kiro's terminal, not the agent invoking swamp.
What needs to change
In src/domain/telemetry/agent_harness_detection.ts:
- opencode predicate →
env.OPENCODE === "1". DropOPENCODE_VERSIONandTERM_PROGRAM=opencode. - kiro predicate → keep
TERM_PROGRAM === "kiro"; dropKIRO_AGENT; addAGENT_CONTEXT_OUTnon-empty as the agent-driven signal. - codex predicate →
CODEX_SANDBOX_NETWORK_DISABLEDnon-empty ORCODEX_SANDBOXdefined. DropCODEX_AGENT_HARNESS. Add a code comment documenting the no-sandbox blind spot. RELEVANT_ENV_VARS: addOPENCODE,AGENT_CONTEXT_OUT,CODEX_SANDBOX_NETWORK_DISABLED,CODEX_SANDBOX; removeKIRO_AGENT,OPENCODE_VERSION,CODEX_AGENT_HARNESS.- Update
agent_harness_detection_test.tsto mirror — existing tests assert on the fabricated env vars, so they pass against fiction and would silently keep passing under the wrong implementation.
Reproduction
- Launch swamp from inside an opencode/codex/kiro CLI session.
- Inspect a telemetry entry:
detectedAiToolisundefinedeven thoughagentSessionDetectedmay betruevia the genericAGENTfallback (opencode case) or viaCODEX_SANDBOX_NETWORK_DISABLEDnot matching any predicate (codex case). - 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.
Shipped
Click a lifecycle step above to view its details.
Sign in to post a ripple.