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",