Environment probe · comparative analysis

claude.ai chat / Claude Cowork / Kimi

Three agent sandboxes, probed from the inside. They differ less in what they contain than in what they are for — and the clearest signal of intent is not the toolchain but the egress proxy.

compiled 2026-07-24 chat probe 2026-06-10 cowork probe 2026-07-24T06:22:10Z kimi probe 2026-07-23 rev v2
containment capability chat microVM · 4 tools cowork microVM · dev agent kimi container · full desktop
Cowork is not a midpoint between the other two. It occupies the high-containment / high-capability corner — which is the expensive corner to build, and explains the TLS-terminating proxy, the signing hooks, and the off-by-default Docker daemon.
claude.ai chat Claude Cowork Kimi

§1 Substrate & isolation

Where the boundary actually sits, and how much sits above it.

Platform
Dimensionchatcoworkkimi
Isolation modelFirecracker microVMFirecracker microVMcontainerd container (K8s pod)
Kernelown guest, 6.18.5own guest, 6.18.5shared host, 5.10.134 (Alibaba LifseaOS)
PID 1process_api (Rust)process_api (Rust, vsock 2024)s6-svscan
Root filesystemext4 on /dev/vdaext4 + 2× ro squashfsoverlayfs, 114+ layers
Base imageUbuntu 24.04.4 · serial 20260410Ubuntu 24.04.4 · same serialDebian 12 on LifseaOS (OSTree)
Fleet marker--wiggle----remote_cowork--numeric instance ID only
Agent uidrootrootroot

The load-bearing difference

Firecracker gives each session its own kernel behind a hardware-virtualised boundary. A container shares the host kernel. That is one fewer layer between the agent and the host, and it changes what a kernel-level bug costs.

Hardening flags

Settingchatcoworkkimi
init_on_free=1setnot setnot set
nomodulesetsetnot set
SELinuxn/a (VM)n/a (VM)selinux=0
Kernel auditn/an/aaudit=0
Spectre IBRSdefaultdefaultnoibrs
cgroupsv1 + v2v1 + v2v1 only
Loopback bypassblockedblockedsshd on 0.0.0.0:22

Individually each is defensible. Read together, Kimi's set trades containment for performance and capability; Anthropic's trades the reverse.

§2 Compute & storage

Cowork figures are from the 2026-07-24 probe. See §6 for what moved since 2026-07-15.

Dimensionchatcoworkkimi
CPUXeon @ 2.80 GHzXeon @ 2.80 GHzXeon Platinum @ 2.50 GHz
Cores1 vCPU2 vCPU2 vCPU
RAM3.9 GB7.8 GB4.0 GB
Swap / GPUnone / nonenone / nonenone / none (bochs-drm)
Disk252 GB252 GB, 30 GB avail40 GB (30 GB usable)
Packages8661009minimal image
Python / Node3.12.3 / 22.22.23.11.15 / 22.22.23.12.12 / —
User-data transport4× rclone FUSE → filestorelocal ext4, no rcloneFUSE portal at /mnt/agents
Persistence failure moderclone cache-flush non-determinismephemeral; durability via gitoverlay ephemeral; portal backend unobservable

New this week

Cowork's host moved from a 2.10 GHz to a 2.80 GHz Xeon — the same clock the chat sandbox reports. Two probes a week apart landing on different host generations is ordinary fleet heterogeneity, not a spec change, so treat the clock as a per-session draw rather than a guarantee.

Reference point for planning: matmul 2000×2000 = 0.103 s on this run.

§3 Egress — cage vs disguise

The sharpest split of the three. Same component, opposite purpose.

Dimensionchatcoworkkimi
Mechanism403 intercept, x-deny-reasonTLS-terminating MITM at 127.0.0.1:39185 + Anthropic CABright Data residential proxy 10.86.13.73:5900
Purposerestrict reachrestrict reach, across many toolchainsextend reach past anti-bot defences
Exit IPsAnthropic infraAnthropic infrarotating residential ISPs (TH, ID), per request
Metadata / RFC-1918not testedhard-blocked (000)not reported
Anti-detectionnonenone--disable-blink-features=AutomationControlled, spoofed UA
Scopeall trafficall trafficbrowser only — Python has no proxy

Cage vs disguise

Anthropic's proxies are a cage; Kimi's is a disguise. One exists so the agent cannot reach things; the other exists so the agent can reach things that would otherwise block it.

Kimi's design is internally coherent — exposing the residential pool only to Chromium and not to Python is a deliberate boundary that stops arbitrary code from abusing the IP pool. It does carry a third-party consent question: residential proxy traffic exits through real consumer connections, and the sourcing of those endpoints has been a sustained criticism of the residential-proxy industry generally.

Cowork egress, 2026-07-24

DestinationResultReading
pypi.org200allowed
registry.npmjs.org200allowed
github.com400reached, ambiguous — something answered, so the host is not blocked; a 400 most likely reflects the probe's request form through the CONNECT proxy rather than policy
www.google.com000no response at all — blocked
169.254.169.254000cloud metadata hard-blocked

400 and 000 are different failures and should not be collapsed. 000 means curl got no response; 400 means it got one. Only the former is evidence of a block.

§4 Product posture

Three product classes, not three sizes of the same thing.

Dimensionchatcoworkkimi
Runtime on top4-tool interfaceClaude Code CLI 2.1.218 (Bun-compiled, squashfs)s6 service stack + Jupyter kernel
Interaction modelone-shot tool executionagent: MCP, hooks, sub-agents, workflows, scheduled tasksremote desktop: Xvnc + KasmVNC + non-headless Chromium
BrowserPlaywright (headless, staged)Playwright + Chrome automationChromium 149 on a real X display, driven by Playwright + pyautogui
DatabasesnoneRedis + Postgres 16.13 (on demand, in-box only)not reported
ContainersabsentCLI + dockerd present, daemon off, Hub blockednot reported
Debug toolingno strace/lsofstrace + lsofminimal image; no ip/ss/netstat
Reach to user's machinenoneremote-devices bridge (ro / rw / rw-no-delete)SSH in (ed25519, moonshot@space.local), no password auth
Git posturea capabilitycentral — SSH commit-signing, session/stop hooksnot reported

Reading the three

chat — hardened ephemeral scratchpad. Reason, generate documents, run short code.

cowork — git-native software-engineering agent. The Docker tooling, proxy trust bundle, and signing hooks all exist to let a general dev toolchain run under one policy gate.

kimi — multimodal desktop agent. It gives the model a screen and a mouse rather than a CLI, and the whole browser/VNC/proxy stack follows from that choice.

Cowork and Kimi are closer in ambition to each other than either is to chat — but they get there by opposite routes: Cowork hands the agent a developer's terminal, Kimi hands it a user's desktop.

§5 Evidence quality & corrections

All three sources are self-probes. That method has a systematic failure mode: over-reading strings output, where a build-toolchain artifact embedded in a binary is mistaken for the binary's own implementation.

Corrections to the chat whitepaper (2026-06-10)

ClaimStatusBasis
rclone-filestore is Rust, built with rustc 1.95-nightly wrong Strings show crypto/internal/fips140, go.shape.*, zeebo/xxh3 — it is Go, as rclone has always been.
chat has a Rust nightly toolchain over-read No installed rustc was ever found; that was a version string inside a shipped binary.
sudo absent in chat untested Not observed-absent. Never probed.
chat egress does not terminate TLS untested 403s were observed; MITM was never checked for.
process_api is Rust holds Cargo registry paths, hyper, jsonwebtoken.

What we missed

Cowork's claude binary was described as "Bun-compiled" — correct but under-resolved. Bun v2.1.181+ ships the Zig→Rust port of Bun itself, so both 2.1.210 and this week's 2.1.218 embed a Rust-generation runtime. The discriminating probe — Rust vs Zig markers in the embedded runtime strings — has still not been run.

Note this is a rewrite of Bun, not of Claude Code, and is unrelated to process_api's Rust.

Confidence tiers in the Kimi report

ClaimConfidence
Bright Data proxy — lum_city/lum_region fields, 5 distinct exit IPs, residential ASNshigh — near-conclusive
Chrome launch flags, process table, s6 stack, boot cmdlinehigh — directly observable
containerd / overlayfs, K8s DNShigh
FUSE portal backend protocol ("9P, virtiofs, or custom")low — explicitly speculative
Cross-session persistence behaviourlow — backend not observable
Absent tooling (strace, lsof)low — self-reported untested

Unresolved across all three. Anthropic's public containment write-up describes claude.ai code execution as gVisor, while direct probing finds Firecracker. Both may be true of different code paths. Flagged, not resolved.

§6 Cowork drift — week over week

2026-07-15 → 2026-07-24. Only fields that moved.

Field2026-07-152026-07-24
claude_cli2.1.2102.1.218
agentclaude-code_2-1-210_agentclaude-code_2-1-218_agent
runnerstaging-a54e7c22brelease-1186d93b9-ext
cpuXeon @ 2.10 GHzXeon @ 2.80 GHz
https_proxy127.0.0.1:45919127.0.0.1:39185

What the drift says

staging → release. The most interesting field. Last week's session ran on a staging- runner; this week's on release-…-ext. Findings from the 07-15 probe were therefore taken against a pre-release build and should not be assumed to describe the shipping environment — anything load-bearing from that run is worth re-confirming.

Proxy port rotates per session. 45919 → 39185 is ephemeral binding, not a config change. Never hard-code it; read $https_proxy at runtime.

Two CLI point releases in nine days. Consistent with Claude Code's normal cadence. Both are past 2.1.181, so both carry Rust-Bun.

Unchanged and worth restating: init_on_free still not set, Docker daemon still off, kernel still 6.18.5, base image still serial 20260410. The substrate is stable; only the product layer moved.

§7 Summary

IsolationEgress intentAgent surface
chatstrongest — microVM + init_on_freerestrict4 tools
coworkstrong — microVMrestrict, elaboratelyfull dev agent
kimiweakest — shared kernel, mitigations offextendfull desktop

Capability and containment trade against each other, and each of the three sits at a different point on that curve — deliberately.