fix(firecracker): run the agent from /home/node, not the /root SSH cwd
The control SSH logs in as root, so the agent (dropped to node via runuser) inherited cwd=/root. That was harmless while the rootless rootfs left /root node-owned, but the dropbear fix (chown /root → root:root 0700) made /root unreadable to node — so the agent's cwd was inaccessible, breaking Node's process.cwd(), Claude Code's shell-snapshot machinery, and `/doctor` (which reported /root/.claude EACCES and failed every Bash command). Run the agent from its workdir (default /home/node) via `env --chdir`. Not a `sh -c 'cd … && exec "$@"'` wrapper: ssh space-joins everything after the host into one string for the guest shell, so the quoted script + $@ get re-split and mangled (it exec'd the $0 placeholder → exit 127). `env --chdir=DIR …` is all simple words, so it survives the join. Verified end-to-end: a real headless claude bottle now runs its Bash tool and exits 0 (was EACCES/127 before). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WBMWTEtQdJ4W5UrWuLHCck
This commit is contained in:
@@ -235,11 +235,17 @@ class TestBottleAgentArgv(unittest.TestCase):
|
||||
argv[idx:],
|
||||
)
|
||||
|
||||
def test_workdir_wraps_command(self):
|
||||
def test_workdir_sets_chdir(self):
|
||||
# The agent runs from its workdir via `env --chdir` (ssh-safe;
|
||||
# not a `sh -c 'cd …'` wrapper, which the ssh arg-join mangles).
|
||||
argv = _bottle(agent_workdir="/home/node/workspace").agent_argv([], tty=False)
|
||||
self.assertIn("sh", argv)
|
||||
joined = " ".join(argv)
|
||||
self.assertIn("cd /home/node/workspace", joined)
|
||||
self.assertIn("--chdir=/home/node/workspace", argv)
|
||||
|
||||
def test_default_workdir_still_chdirs_off_root(self):
|
||||
# Even with the default workdir the agent must leave /root (the
|
||||
# root-SSH cwd it can't read); it cd's to /home/node.
|
||||
argv = _bottle().agent_argv([], tty=False)
|
||||
self.assertIn("--chdir=/home/node", argv)
|
||||
|
||||
def test_guest_env_injected(self):
|
||||
argv = _bottle(guest_env={"HTTPS_PROXY": "http://100.64.0.0:9099"}).agent_argv(
|
||||
|
||||
Reference in New Issue
Block a user