Login
View Ticket
Login
Ticket Hash: a144ae3a71bf13431fbd8b7f9498f9626436b2c1
Title: A sandbox binds .claude.json as one file, which goes stale when the host replaces it and cannot be replaced inside
Status: Open Type: Code_Defect
Severity: Normal Priority: High
Subsystem: sandbox Resolution:
Last Modified: 2026-11-02 04:04:04
9.2 days ago
Created: 2026-11-02 02:33:10
9.2 days ago
Version Found In: b297c80b37
Description:
Every Claude pattern lists the file in homes (docs/protocol-v1-examples.md:67, ocx-node/r-senders.json:10, ocx-rootfs/hosts.json), and Launch binds it with --bind-try (src/ocx/launch.cr:149). Such a bind holds the file's inode, not its name.

Demonstrated 2026-11-02 with bwrap on x86-1 on a scratch file: the host replaced it by rename, as a program saving atomically does, and inside the sandbox it still read the old text; and 'mv' over it from inside failed with 'Resource busy'. So a sign-in or save outside a running sandbox is not seen inside, and what the sandbox then writes goes to a file no longer at that name. Not demonstrated with Claude itself.

Change, as data, with no change to src: Claude's CLAUDE_CONFIG_DIR. Demonstrated with Claude 2.1.316 on x86-1: with it set to a scratch folder, Claude wrote .claude.json inside that folder. So each pattern's process.env sets CLAUDE_CONFIG_DIR=$$workspace$$/.claude and drops the file from homes; the same in r-senders.json, hosts.json's homes, the Dockerfile and build-rootfs.cr's seed; and on each machine the file moves once, from HOME/.claude.json to HOME/.claude/.claude.json, with running sessions ended first. Not tried: a whole signed-in session this way.

This does not settle 5fbc06fea7, which is older: sessions still share one mutable file. It removes the stale inode; a folder per session would remove the sharing and needs a sign-in per session.

Passes when: a sign-in on the host reaches a session that starts after it and a running session's next read, in a test, and the session's own save lands in the host's file.

Happened on x86-1, Nov 1, 2026, Eastern: a Claude started by hand in the client replaced /home/ocx/.claude.json (likely, not proven), and the daemon and running sessions kept a copy marked //deleted. A new sandbox binding that file fails: 'Can't bind mount ... No such file or directory', reproduced with bwrap at this run's own bound copy; binding the .claude folder still works. Stone's run at 11:01 PM used this ticket's fields (homes without .claude.json, CLAUDE_CONFIG_DIR=$$workspace$$/.claude) with a copy of the file in that folder and no restart: it started, and its sandbox binds only the folder. Whether Claude works fully this way is not shown until its first post.