Files
dejima/harnesses/claude-code/briefing.md
T
branderson 9aee4bb6c7
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
Add Cline as the second supported harness
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.
2026-08-21 21:05:37 -07:00

128 B

{{resume_command}}

(session history is shared via the bind-mounted ~/.claude, so it will pick up right where this left off).