Small files between a Mac and Linux
Read a Linux sandbox agent's result on your Mac, send a reply, and observe renames and deletes through the same mountable.io filesystem.
Both machines mount the same filesystem. The Linux process writes a small result. The Mac reads it, renames it to acknowledge the result, then writes a reply. Linux reads that reply. Each side also observes a deletion by the other.
The runnable companion uses Python's standard library. It writes 58 bytes of synthetic text in total. It does not call a model or run a database.
1. Prepare the filesystem and machines
Use an existing paid mountable.io account and a dedicated test filesystem. Set a monthly spending cap and quotas before testing. The run below used an existing filesystem with a €1 monthly cap, a 1 GiB quota, a 10,000-entry quota and 100 changes per minute. Those are limits, not free allowances.
Install the current CLI on both machines:
curl -fsSL https://mountable.io/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
mountable versionThe Mac needs Apple Silicon and macOS 26. Linux needs /dev/fuse and
permission to mount, including a helper such as fusermount3 for an
unprivileged process. See Mount on a Mac and
Mount from a sandbox.
Download handoff.py
to local disk on each machine. Keep the script outside the mount. Choose a
fresh run ID together, such as demo-4182; use that same ID on both sides.
2. Mount both sides and wait for readiness
On your trusted backend or signed-in Mac, create a separate session for each machine. Keep each session ID so you can revoke it:
mountable login
FS_ID=your-filesystem-id
umask 077
mountable ticket create "$FS_ID" --max-duration 10m --json > mac-session.json
mountable ticket create "$FS_ID" --max-duration 10m --json > linux-session.json
MAC_SESSION_ID=$(python3 -c 'import json; print(json.load(open("mac-session.json"))["id"])')
LINUX_SESSION_ID=$(python3 -c 'import json; print(json.load(open("linux-session.json"))["id"])')Each response contains an id and a one-time ticket. Pass only the Linux
ticket through the sandbox's secret input as MOUNTABLE_TICKET. Keep the
reusable API key and login on the trusted machine. Never print tickets, put
them in arguments, or commit the response files.
On the Mac, in a dedicated terminal:
mkdir -p ~/agent-work
python3 -c 'import json; print(json.load(open("mac-session.json"))["ticket"])' |
mountable mount --ticket-stdin --json ~/agent-workOn Linux, in a dedicated terminal:
mkdir -p /tmp/agent-work
printf '%s\n' "$MOUNTABLE_TICKET" |
mountable mount --ticket-stdin --json /tmp/agent-workBoth commands stay running. Wait for the JSON mounted event on each
machine before starting either companion. Stop if either command exits
or readiness takes more than 30 seconds. An ordinary unmounted directory is
local disk, so do not continue there.
Tickets must be exchanged within five minutes and are single use. Remove the response files after retaining the session IDs for cleanup.
3. Run the handoff
From another terminal on each machine, run the following within 20 seconds
of one another. Run Python from the local directory containing handoff.py.
python3 handoff.py linux /tmp/agent-work --run-id demo-4182python3 handoff.py mac ~/agent-work --run-id demo-4182The companion creates only handoff-demo-4182/. The Linux side refuses to
reuse an existing directory. Each file is closed after fsync, and each
reader checks its full expected bytes.
| Step | Linux | Mac |
|---|---|---|
| Result | Writes result.txt | Waits for and reads the result |
| Acknowledgement | Waits for reviewed.txt with the same bytes, then deletes it | Renames result.txt to reviewed.txt, then waits for deletion |
| Reply | Waits for and reads reply.txt, then renames it to accepted.txt | Writes reply.txt, then waits for the rename with the same bytes |
| Finish | Waits for deletion of accepted.txt | Deletes accepted.txt |
Success ends with linux: handoff complete and mac: handoff complete.
A missing confirmation raises TimeoutError and exits nonzero. Stop both
processes if either fails; do not continue the workflow or assume a write was
seen. Each polling step has a 20-second deadline. A blocked OS filesystem call
can outlast that deadline, so an orchestrator should also impose an overall
process deadline (100 seconds for this tiny run).
Each side writes only its own file. Coordinate writers by path; this is not a shared-database or simultaneous-editing protocol.
4. Clean up and revoke
After both processes succeed, remove only this run's directory from the Mac.
macOS can leave ._* sidecar files in it, so inspect its contents first:
ls -la ~/agent-work/handoff-demo-4182
rm -r ~/agent-work/handoff-demo-4182
mountable unmount ~/agent-workOn Linux:
mountable unmount /tmp/agent-workFrom the trusted backend, revoke both retained session IDs:
mountable sessions revoke "$MAC_SESSION_ID"
mountable sessions revoke "$LINUX_SESSION_ID"
mountable files list "$FS_ID" /
mountable fs usage "$FS_ID"For a failed run, stop both companions, unmount and revoke the sessions, then inspect the dedicated run directory through the Files API. Remove its files, sidecars and empty directory without touching other paths. A new attempt needs fresh tickets and a fresh run ID.
Verified scope and cost
On 26 October 2026, released CLI 0.8.0 passed this companion on an Apple Silicon Mac running macOS 26.7.1 and Ubuntu 24.04 arm64 in a throwaway local Colima VM. Both mounts reached readiness. Both exact-byte reads, both renames and both deletes passed; mounts were detached, sessions revoked, the test tree removed and the VM deleted. This verifies that local Linux VM, rather than a new hosted sandbox provider.
The older CLI 0.6.0 measurement on 23 October used small files on an idle filesystem: all 30 write, rename and delete observations took under a second, with a maximum of 0.78 seconds. That is a measured result, not a coherence or latency guarantee. This companion did not measure current-release latency. The filesystem contract covers mount behavior.
The 0.8.0 run's usage counters increased by 9,704 written bytes and 58 read bytes, including filesystem overhead beyond the 31-byte result and 27-byte reply. Two 4,096-byte Mac sidecars were observed and removed. The final usage snapshot reported 792,207 retained bytes and 3 entries, versus 782,503 bytes and 3 entries before; directory listing confirmed the test tree was gone. Reserved usage remained €0.03 for this shared test filesystem. These snapshots do not isolate settled provider costs.
Storage is €0.17/GiB-month and downloads €0.017/GiB in EUR, plus file charges; see billing. At those rates, 9,704 bytes retained for a full month would be about €0.00000154 storage and 58 downloaded bytes about €0.00000000092, before file charges, tax and billing aggregation. The test did not retain its files for a month. The local VM and standard-library script added no hosted provider or model API spend, paid plan or credit.