tests / confined (conversation) (pull_request_target) Successful in 55s
tests / confined (proxy) (pull_request_target) Successful in 1m7s
tests / runner-env (confined) (pull_request_target) Successful in 33s
tests / confined (shellcheck) (pull_request_target) Successful in 47s
tests / confined (providers) (pull_request_target) Successful in 2m0s
tests / confined (remote) (pull_request_target) Successful in 3m25s
tests / privileged (pull_request_target) Successful in 3m37s
tests / confined (static) (pull_request_target) Successful in 3m37s
tests / runner-env (privileged) (pull_request_target) Successful in 34s
tests / confined (project) (pull_request_target) Successful in 4m23s
tests / confined (config) (pull_request_target) Successful in 6m32s
tests / confined (audit) (pull_request_target) Successful in 7m21s
Everything asserted here was established by running Cline in this container, because its documentation is wrong about the part that matters most. Rules are read from ~/Documents/Cline/Rules on Linux, not ~/Cline/Rules as documented, and CLINE_RULES does nothing - so R3 is delivered as a file at a path found by testing rather than by reading. R5 clears with the machinery that already exists, which was the open question. Cline configured for anthropic with the placeholder key sandbox-credential-proxy-placeholder, pointed at the real hostname, ran a real completion through dejima's in-container terminator and host-side proxy. No base-URL override and no new proxy work: the session is indistinguishable from a stock install, exactly as Claude Code's faked .credentials.json makes it. R4 is the requirement Cline clears most cleanly, and not for the reason the assessment gave. --data-dir is convenient, but the forcing fact is that Cline indexes every session it has ever run in one sessions.db, with the project a session belonged to as a field inside the record rather than a directory above it. There is no per-project subtree of the operator's data directory to mount, so mounting it would put every project's transcripts into every session - #104 exactly. Each workspace gets its own data directory under [harness.cline] state_dir, the way epitaph.dir and audit.dir already work. Provider-agnostic turns out not to mean endpoint-agnostic. With base_url unset the session reaches Anthropic through the credential proxy and the key never enters the container. Pointed at someone else's hosted API there is no proxy that could hold a key back, so the key would have to go in - which is R5 failing rather than a network restriction. base_url is therefore accepted only for a literal loopback or RFC 1918 address, where an open-weight model served locally needs no credential and R5 has nothing to protect. The octets are compared as numbers, because a glob on "10." accepts 10.example.com and takes the key with it. proxy = off and transport = loopback refuse for the same reason: claude-code falls back to mounting the real credential there and cline has nothing to fall back to. A second harness also made three things in core Claude Code's that were never supposed to be: The briefing preamble said --dangerously-skip-permissions and ~/.claude. Both are one harness's, and telling a Cline session about a flag it does not have is not cosmetic - the preamble is where a session learns what state it is in. The flag now comes from the manifest as {{no_confirm_args}}, and the sentence about where session history lives moved into the harness fragment, along with the closing parenthetical that named ~/.claude outright. Briefing delivery ran entirely through a Claude Code SessionStart hook, and with it the container-side work every harness needs: this container's id, the gap between what the project declares and what the image has, and the project's .dejima.md. That is now hooks/dejima-briefing-render.sh, baked into the image and called by both routes. A harness with no hook declares briefing_path and entrypoint.sh renders the briefing into it root-owned and read-only, refusing to start the session if that fails - a session that does not know it is sandboxed is the one thing R3 exists to prevent. Harness plugins were never shellchecked. They are sourced, so they carry no shebang, so the shebang-based discovery dropped them silently while they sat in the trusted computing base. Two things are deliberately not integrated, and the blocker is dejima's rather than Cline's. dejima-epitaph and dejima-conversation-ship both find transcripts by asking for a projects_dir key and walking <dir>/<slug>/*.jsonl, which is Claude Code's layout written into core. Cline's is one JSON object rewritten in place, already per-project because the data directory is. Both tools no-op cleanly for a harness defining neither hook, so nothing misreports; making them work means teaching core to ask a harness where its transcripts are, which is a change to those two tools and not to this harness. One incidental finding, which docs/security.md had left open as something an integration had to establish rather than assume: Cline's web-fetch tool runs in the container and returns "Unable to connect" for a host the allowlist does not carry. The egress allowlist bounds what reaches a Cline session, which is not true of Claude Code's WebSearch. Cline needs AVX2 - its CLI is a Bun-embedded binary and Bun's default build requires it - so a VM whose CPU model is x86-64-v2-AES gets SIGILL before printing anything.
128 B
128 B
{{resume_command}}
(session history is shared via the bind-mounted ~/.claude, so it will pick up right where this left off).