Remix.run Logo
btucker 8 hours ago

I haven't dug too deep, but it appears to be using a bubblewrap sandbox inside a vm on the Mac using Apple's Virtualization.framework from what I can tell. It then uses unix sockets to proxy network via socat.

ETA: used Claude Code to reverse engineer it:

   Insight ─────────────────────────────────────

  Claude.app VM Architecture:
  1. Uses Apple's Virtualization.framework (only on ARM64/Apple Silicon, macOS 13+)
  2. Communication is via VirtioSocket (not stdio pipes directly to host)
  3. The VM runs a full Linux system with EFI/GRUB boot

  ─────────────────────────────────────────────────

        ┌─────────────────────────────────────────────────────────────────────────────────┐
        │  macOS Host                                                                     │
        │                                                                                 │
        │  Claude Desktop App (Electron + Swift native bindings)                          │
        │      │                                                                          │
        │      ├─ @anthropic-ai/claude-swift (swift_addon.node)                           │
        │      │   └─ Links: Virtualization.framework (ARM64 only, macOS 13+)            │
        │      │                                                                          │
        │      ↓ Creates/Starts VM via VZVirtualMachine                                   │
        │                                                                                 │
        │  ┌──────────────────────────────────────────────────────────────────────────┐  │
        │  │  Linux VM (claudevm.bundle)                                              │  │
        │  │                                                                          │  │
        │  │  ┌────────────────────────────────────────────────────────────────────┐  │  │
        │  │  │  Bubblewrap Sandbox (bwrap)                                        │  │  │
        │  │  │  - Network namespace isolation (--unshare-net)                     │  │  │
        │  │  │  - PID namespace isolation (--unshare-pid)                         │  │  │
        │  │  │  - Seccomp filtering (unix-block.bpf)                              │  │  │
        │  │  │                                                                    │  │  │
        │  │  │  ┌──────────────────────────────────────────────────────────────┐  │  │  │
        │  │  │  │  /usr/local/bin/claude                                       │  │  │  │
        │  │  │  │  (Claude Code SDK - 213MB ARM64 ELF binary)                  │  │  │  │
        │  │  │  │                                                              │  │  │  │
        │  │  │  │  --input-format stream-json                                  │  │  │  │
        │  │  │  │  --output-format stream-json                                 │  │  │  │
        │  │  │  │  --model claude-opus-4-5-20251101                            │  │  │  │
        │  │  │  └──────────────────────────────────────────────────────────────┘  │  │  │
        │  │  │       ↑↓ stdio (JSON-RPC)                                          │  │  │
        │  │  │                                                                    │  │  │
        │  │  │  socat proxies:                                                    │  │  │
        │  │  │  - TCP:3128 → /tmp/claude-http-*.sock (HTTP proxy)                │  │  │
        │  │  │  - TCP:1080 → /tmp/claude-socks-*.sock (SOCKS proxy)              │  │  │
        │  │  └────────────────────────────────────────────────────────────────────┘  │  │
        │  │                                                                          │  │
        │  └──────────────────────────────────────────────────────────────────────────┘  │
        │           ↕ VirtioSocket (RPC)                                                 │
        │      ClaudeVMDaemonRPCClient.swift                                             │
        │           ↕                                                                    │
        │      Node.js IPC layer                                                         │
        └─────────────────────────────────────────────────────────────────────────────────┘
VM Specifications (from inside)

ComponentDetailsKernelLinux 6.8.0-90-generic aarch64 (Ubuntu PREEMPT_DYNAMIC)OSUbuntu 22.04.5 LTS (Jammy Jellyfish)HostnameclaudeCPU4 cores, Apple Silicon (virtualized), 48 BogoMIPSRAM3.8 GB total (~620MB used at idle)SwapNone

Storage Layout

DeviceSizeTypeMount PointPurpose/dev/nvme0n1p19.6 GBext4/Root filesystem (rootfs.img)/dev/nvme0n1p1598 MBvfat/boot/efiEFI boot partition/dev/nvme1n19.8 GBext4/sessionsSession data (sessiondata.img)virtiofs-virtiofs/mnt/.virtiofs-root/shared/...Host filesystem access

Filesystem Mounts (User Perspective)

        /sessions/gallant-vigilant-lamport/
        ├── mnt/
        │   ├── claude-cowork/     → Your selected folder (virtiofs + bindfs)
        │   ├── .claude/           → ~/.claude config (bindfs, rw)
        │   ├── .skills/           → Skills/plugins (bindfs, ro)
        │   └── uploads/           → Uploaded files (bindfs)
        └── tmp/                   → Session temp files
        
        Session User
        A dedicated user is created per session with a Docker-style random name:
        User: gallant-vigilant-lamport
        UID:  1001
        Home: /sessions/gallant-vigilant-lamport
        Process Tree
        PID 1: bwrap (bubblewrap sandbox)
        └── bash (shell wrapper)
            ├── socat TCP:3128 → unix socket (HTTP proxy)
            ├── socat TCP:1080 → unix socket (SOCKS proxy)
            └── /usr/local/bin/claude (Claude Code SDK)
                └── bash (tool execution shells)

        Security Layers

        Apple Virtualization.framework - Hardware-level VM isolation
        Bubblewrap (bwrap) - Linux container/sandbox

        --unshare-net - No direct network access
        --unshare-pid - Isolated PID namespace
        --ro-bind / / - Read-only root (with selective rw binds)


        Seccomp - System call filtering (unix-block.bpf)
        Network Isolation - All traffic via proxied unix sockets

        Network Architecture
        ┌─────────────────────────────────────────────────────────────┐
        │  Inside Sandbox                                             │
        │                                                             │
        │  claude process                                             │
        │      │                                                      │
        │      ↓ HTTP/HTTPS requests                                  │
        │  localhost:3128 (HTTP proxy via env vars)                   │
        │      │                                                      │
        │      ↓                                                      │
        │  socat → /tmp/claude-http-*.sock ─────────┐                │
        │                                            │                │
        │  localhost:1080 (SOCKS proxy)              │                │
        │      │                                     │                │
        │      ↓                                     │                │
        │  socat → /tmp/claude-socks-*.sock ────────┤                │
        └───────────────────────────────────────────┼────────────────┘
                                                    │
                                VirtioSocket ←──────┘
                                                    │
        ┌───────────────────────────────────────────┼────────────────┐
        │  Host (macOS)                             │                │
        │                                           ↓                │
        │                              Claude Desktop App            │
        │                                           │                │
        │                                           ↓                │
        │                                    Internet                │
        └─────────────────────────────────────────────────────────────┘
        Key insight: The VM has only a loopback interface (lo). No eth0, no bridge. All external network access is tunneled through unix sockets that cross the VM boundary via VirtioSocket.


  Communication Flow

  From the logs and symbols:

  1. VM Start: Swift calls VZVirtualMachine.start() with EFI boot
  2. Guest Ready: VM guest connects (takes ~6 seconds)
  3. SDK Install: Copies /usr/local/bin/claude into VM
  4. Process Spawn: RPC call to spawn /usr/local/bin/claude with args

  The spawn command shows the actual invocation:
  /usr/local/bin/claude --output-format stream-json --verbose \
    --input-format stream-json --model claude-opus-4-5-20251101 \
    --permission-prompt-tool stdio --mcp-config {...}