From e74a5e0219f76f64286ad93ea757ff47ce4f1f8c Mon Sep 17 00:00:00 2001 From: claude Date: Tue, 23 Jun 2026 18:06:41 +0000 Subject: [PATCH] fix(smolmachines): exclude /tmp+/var/tmp from snapshot; mkdir -p on boot On resume from a committed snapshot, smolvm's pack process remaps all file uids to the host uid (501 on macOS). Files in /tmp that were created during the session (e.g. /tmp/claude-1000 owned by node=uid 1000) get remapped to 501. Claude Code then refuses to use the temp directory because it's owned by a different uid. Two-part fix: - Exclude ./tmp and ./var/tmp from the tar in _exec_tar_to_file. Both directories are ephemeral; a resumed VM should start with clean temp directories identical to a fresh VM. - Add mkdir -p /tmp /var/tmp to _init_vm before chown/chmod, so the directories are created if the committed snapshot omitted them. --- bot_bottle/backend/smolmachines/freezer.py | 7 +++++++ bot_bottle/backend/smolmachines/launch.py | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/bot_bottle/backend/smolmachines/freezer.py b/bot_bottle/backend/smolmachines/freezer.py index 3009544..1315008 100644 --- a/bot_bottle/backend/smolmachines/freezer.py +++ b/bot_bottle/backend/smolmachines/freezer.py @@ -120,6 +120,13 @@ def _exec_tar_to_file(machine: str, dest: Path) -> None: "--exclude=./sys", "--exclude=./dev", "--exclude=./run", + # /tmp and /var/tmp are ephemeral. Their stale contents + # (e.g. /tmp/claude-) have uid remapped by smolvm's + # pack process, causing Claude Code to refuse to use them + # on resume. Exclude both; _init_vm recreates them with + # mkdir -p + correct ownership on every boot. + "--exclude=./tmp", + "--exclude=./var/tmp", f"--file={_VM_COMMIT_TAR}", "--directory=/", ".", diff --git a/bot_bottle/backend/smolmachines/launch.py b/bot_bottle/backend/smolmachines/launch.py index 2bde131..e45fbbb 100644 --- a/bot_bottle/backend/smolmachines/launch.py +++ b/bot_bottle/backend/smolmachines/launch.py @@ -276,10 +276,16 @@ def _init_vm(plan: SmolmachinesBottlePlan) -> None: All folded into one sh -c to avoid back-to-back exec calls immediately after machine_start (libkrun exec-channel race). + mkdir -p guards: when booting from a committed snapshot, /tmp and + /var/tmp are excluded from the archive (they're ephemeral and their + stale contents would have wrong uid after smolvm's uid remap). The + directories must be created before chown/chmod can set permissions. + wait_exec_ready polls until the exec channel is ready for the subsequent provision calls, replacing the empirical sleep.""" _smolvm.machine_exec(plan.machine_name, [ "sh", "-c", + "mkdir -p /tmp /var/tmp && " "chown -R node:node /home/node && " "chown root:root /tmp /var/tmp && " "chmod 1777 /tmp /var/tmp",