OrbStack Isolated Machine Backend
Status: Deferred — shared-kernel architecture does not address the kernel isolation gap for the current macOS ARM audience; see smolvm backend research for the active VM isolation track
Why This Item Is Deferred
Status changed June 2026 after a deep research pass against the current operator audience, the OrbStack architecture, and the broader AI-agent sandboxing landscape. Three compounding reasons drive the deferral.
The actual boundary for all current users already exists
jackin❯ is macOS ARM-only. Every active operator uses OrbStack as their Docker backend. The role container's existing runtime boundary is already:
macOS ARM → OrbStack Linux VM → Docker daemon → role container + jackin-capsuleOrbStack's Linux VM boundary already exists at launch time. The role container is already isolated from macOS by OrbStack's hypervisor layer. Adding an OrbStack isolated machine between the VM and the inner Docker daemon produces:
macOS ARM → OrbStack Linux VM → isolated machine (same kernel, different namespace) → inner Docker → role containerThis is namespace-within-namespace isolation on the same kernel. The outer VM boundary that OrbStack already provides is not improved.
OrbStack isolated machines are namespaces, not a new kernel
OrbStack explicitly documents that its machines — including isolated machines — share a Linux kernel. They use cgroups and namespaces, not a hypervisor boundary per workload. The wording "isolated" in OrbStack's product language means filesystem-isolated (no automatic Mac filesystem passthrough), not kernel-isolated.
The industry moves toward microVMs for AI agents because of concrete, exploitable weaknesses in the shared-kernel model:
- runc vulnerabilities (November 2025): three high-severity CVEs allowing container escape to the host system, affecting Docker, containerd, and every managed Kubernetes service.
- CVE-2026-34040: Docker authorization bypass via oversized HTTP request — allows creating containers with full host access, fixed in Docker Engine 29.3.1.
- CVE-2024-1086: use-after-free in Linux's netfilter subsystem, confirmed actively exploited in ransomware campaigns (October 2025 CISA advisory).
- DinD
--privileged: the DinD sidecar jackin❯ runs today requires--privileged, giving it near-full access to the OrbStack VM kernel. A compromised DinD container can escape to the VM kernel — and an OrbStack isolated machine surrounding it uses the same kernel.
Namespace isolation does not change any of these attack surfaces. The kernel is the attack surface, and the kernel is shared.
What actually addresses the kernel boundary problem
As of June 2026, three paths give a true per-workload kernel boundary on macOS ARM:
Docker Sandboxes (Docker Inc., launched January 2026): each sandbox runs in a dedicated microVM using a proprietary VMM built on Apple Hypervisor.framework on macOS. The host Docker daemon cannot see sandboxes in docker ps. Each sandbox has its own private Docker daemon and its own kernel. Credentials are proxied outside the VM boundary. Explicitly supports Claude Code, Codex CLI, GitHub Copilot CLI, Gemini CLI, OpenCode, Kiro, and Docker Agent. This is the shape jackin❯ needs: private Docker daemon inside a true hypervisor boundary, not a shared-kernel namespace. Covered in the smolvm backend research comparison.
smolvm (open-source, Apache-2.0): uses libkrun and Hypervisor.framework on macOS to give each workload its own kernel. Network off by default. OCI image input. Direct active research track in smolvm backend research, including a full comparison against Docker Sandboxes.
Apple Container framework (announced with macOS 26 Tahoe, 2026): each OCI container runs inside its own lightweight VM via Virtualization.framework, natively on Apple Silicon. Sub-second start times. True hypervisor isolation per container, not namespace isolation. OCI-compatible. This is the native macOS ARM path closest to what this roadmap item originally sought — a first-class isolation layer without needing Docker or OrbStack machinery at the VM level. Needs evaluation once macOS 26 operator adoption reaches a usable threshold.
gVisor (Google): syscall interception in userspace — no KVM required. However: confirmed broken on OrbStack macOS ARM in v2.1.3 (orbstack/orbstack#2362 — /tmp → /private/tmp symlink causes runsc to crash immediately), and Claude Code hangs indefinitely in gVisor on macOS ARM (anthropics/claude-code#35454). Not viable on the current platform stack.
The OrbStack isolated machine CLI surface is not ready
Even setting aside the shared-kernel architecture issue, the isolated machine CLI has blocking gaps as of v2.1.3:
orb push/orb pullbroken on isolated machines (orbstack/orbstack#2469) — forces thedocker save | orb -m <name> sh -c 'cat > /tmp/img.tar && docker load && rm'stream-import workaround for every image transfer.- PTY allocation, SIGWINCH forwarding, and detach-key behavior of
orb -m <name> <cmd>: completely undocumented. This is the make-or-break question for the attach transport — without empirical confirmation, the entire attach design is a guess. - Network host/machine blocking and SSH agent forwarding controls: documented in v2.1.2 release notes but GUI-only with no confirmed CLI surface in v2.1.3.
When to revisit
- OrbStack documents a true hypervisor boundary (not shared-kernel) for isolated machines, AND the CLI surfaces for selective shares, network blocking, and SSH agent forwarding stabilize, AND
orb pushis fixed. - OR: smolvm research proves insufficient for macOS ARM and OrbStack isolated machines become the next-best open alternative.
- OR: the operator base expands beyond OrbStack macOS ARM to setups where the existing Docker backend does not already have an outer VM boundary.
Until then, the effective isolation roadmap for the current audience is: Docker runtime hardening contract (near-term, improves the existing backend) → smolvm backend research (true per-workload kernel via libkrun/Hypervisor.framework) → Apple Container framework evaluation (native macOS 26 path, once adoption allows).
Problem
jackin❯ works well on macOS through Docker-compatible backends, and many macOS operators already use OrbStack as their Docker engine. OrbStack now also exposes isolated Linux machines that are useful for AI agent sandboxing. That creates a pragmatic path between today's Docker container boundary and a future Kubernetes or true microVM backend.
The question is not "should jackin❯ stop using Docker?" The desired backend is:
run the jackin❯ role environment inside an OrbStack isolated machine, while preserving Docker workflows inside that machine when the role needs them.
This matters because jackin❯ roles often expect Docker-in-Docker style behavior: the agent may build sibling containers, run Compose, use Testcontainers, or inspect Docker state while working. An OrbStack backend that cannot provide a private Docker-compatible engine would not satisfy the current role contract.
What OrbStack Provides
Official OrbStack documentation describes:
- Architecture: OrbStack uses a lightweight Linux virtual machine with a shared kernel. Its Linux machines are not independent VMs in the strict sense, even though they behave like traditional Linux machines for most development workflows.
- Linux machines: machines run full Linux distros with init systems such as systemd, OpenRC, or runit; commands can be executed through the
orbCLI. - Machine commands:
orbcan create, start, stop, delete, inspect, run commands in, push files to, and pull files from machines. - Cloud-init:
orb createsupports-c/--user-datacloud-init files. - File sharing: normal machines expose Mac files under the same
/Users/...path and/mnt/mac. - Machine networking: services in machines are reachable from macOS at
localhost, and machines also receive*.orb.localnames. - Release notes: v2.1.0 added isolated machines without filesystem integration, explicitly called useful for AI agent sandboxing; v2.1.1 added selective file sharing mounts in isolated machines; v2.1.2 added a setting to block network connections to host/machines and opt-in SSH agent forwarding.
Important correction: this roadmap item should not call OrbStack isolated machines "microVMs" in jackin❯ product language. OrbStack itself says machines share a kernel and are not strictly independent VMs. The right label is orbstack-isolated or OrbStack isolated machine backend.
Verified CLI surface (May 2026)
A research pass against the OrbStack release notes, settings docs, and the orbstack/orbstack issue tracker established what is documented and what is not. Current stable is v2.1.3 (May 10, 2026) per the release notes; v2.1.3 fixed proxy support and rseq compatibility but did not change the isolated-machine surface.
| Flag / capability | Confirmed | Source |
|---|---|---|
orb create --isolated <distro> <name> creates an isolated machine | ✅ | orbstack/orbstack#2409 (maintainer kdrag0n showed orbctl create -a arm64 ubuntu:questing isolated-too --isolated --mount ... invocation) and v2.1.0 release notes |
Selective shares use --mount "host_abs_path:container_path", repeatable | ✅ | same issue thread (error path "mount source must be an absolute path" confirms the syntax) and v2.1.1 release notes |
Read-only enforcement at the share layer (:ro suffix or equivalent) | ❌ undocumented | Release notes, settings page, file-sharing docs, and issue tracker have no mention. Treat as unsupported until verified with orb create --help on an installed 2.1.3 |
| Network host/machine blocking (v2.1.2 setting) | ⚠️ unspecified CLI | Release notes call it "Added setting to block network connections to host/machines". No documented orb config set key. Likely GUI-only as of 2.1.3 |
| SSH agent forwarding per-machine opt-in (v2.1.2) | ⚠️ unspecified CLI | Release notes describe the opt-in but do not name the flag. Needs orb create --help verification |
| OrbStack auto-update can be disabled | ❌ not possible | orbstack/orbstack#577 — maintainer kdrag0n: "no plans to allow manually disabling update checks for now." Installing the update is the operator's choice, but the check runs unconditionally |
| Resource limits per-machine | ❌ global only | Settings docs: orb config set memory_mib and orb config set cpu are documented as global percentages |
orb push / orb pull work on isolated machines | ❌ broken in 2.1.3 | orbstack/orbstack#2469 — pull/push route through /mnt/mac which isolated machines block. kdrag0n: "Fixed for the next version" (post-2.1.3) |
orb -m <name> <cmd> PTY / SIGWINCH / detach-key behavior | ❌ undocumented | OrbStack docs page /machines/ shows the invocation but says nothing about PTY allocation, window-resize forwarding, or detach. No issues mention SIGWINCH or PTY behavior in the orbstack/orbstack tracker. Empirical test required before committing to this as the interactive-session transport |
| Multi-user / multi-operator on one host | ❌ undocumented | OrbStack is a per-user macOS app; multi-user concurrency is not documented as supported |
The CLI-verified facts shift several design decisions in this roadmap from "research" to "build against" or "block on workaround". See Decided In This Pass and Open Before Implementation Can Start below.
Goal
Add an experimental macOS backend that:
- Creates one OrbStack isolated machine per jackin❯ instance.
- Shares only the operator-approved workspace/global mounts into that machine.
- Installs or starts a Docker-compatible engine inside the machine when the role needs Docker workflows.
- Runs the jackin❯ role container inside the machine-owned Docker engine, with jackin-capsule as PID 1 exactly as the Docker backend does today.
- Preserves attach, reconnect, inspect, eject, purge, and state-recovery semantics.
- Reports the exact boundary and residual risks in the launch/session contract.
Non-Goals
- Do not replace Docker hardening as the near-term default.
- Do not claim Docker Sandboxes parity. OrbStack does not provide jackin❯ with Docker Sandboxes' host-side credential proxy or per-domain egress policy by itself.
- Do not call this backend a true microVM boundary.
- Do not silently enable global Mac filesystem integration. The provider must use isolated machines with explicit shares only.
- Do not mutate OrbStack global settings, macOS firewall settings, SSH config, or host Docker context silently.
- Do not pursue Kubernetes support in this item. Kubernetes remains future platform expansion.
Backend Shape
Use a backend name that reflects the actual provider:
docker
orbstack-isolatedExample future CLI:
jackin load the-architect . --backend orbstack-isolated
jackin load reviewer . --backend auto --docker-profile hardenedExample future config:
[runtime]
default_backend = "docker"
[runtime.orbstack]
enabled = true
default_distro = "ubuntu"
require_isolated = true
block_host_network = true
ssh_agent = "off" # off | ask | on
[workspaces.my-service.runtime]
backend = "orbstack-isolated"The exact schema must be designed with the backend abstraction. If it touches versioned config files, it must ship with the required migrations and fixtures.
Proposed Runtime Flow
Current Docker flow:
host Docker -> build role image
host Docker -> create per-agent network
host Docker -> start docker:dind sidecar
host Docker -> start role container
role container -> talks to DinD over TLSProposed OrbStack isolated flow:
host Docker or selected builder -> build role image
host -> export image artifact or push to local registry
host -> orb create --isolated jackin-<instance> -c cloud-init.yml
host -> share only approved mount sources into the machine
machine -> install/start Docker engine if needed
host -> transfer/import role image into machine Docker
machine Docker -> start role container with jackin-capsule
role container -> talks to machine-local Docker when required
host -> attach via orb command/SSH/tunnel to jackin-capsuleThe key property: Docker remains inside the isolated machine boundary for agent workflows. The host Docker daemon is only a build/export helper unless a later phase moves builds into the machine.
Why Still Run Docker Inside OrbStack?
jackin❯ role environments are Docker-shaped:
- roles are authored as Dockerfiles
- the construct image provides the common base environment
- agents expect Docker CLI and Compose in many workflows
- Testcontainers and local service stacks need a Docker-compatible daemon
- operators want to inspect what the agent built and ran
Running Docker inside the isolated machine preserves that model while moving the runtime daemon out of the host Docker engine.
There are two possible modes:
| Mode | Description | When useful |
|---|---|---|
containerized-role | Import the role image and run it as a container inside machine Docker. | Best fit for current jackin❯ architecture. |
machine-native-role | Provision the role environment directly in the machine without an outer role container. | Future research only; breaks more assumptions. |
Start with containerized-role.
Image Build and Transfer Options
| Option | Flow | Pros | Cons |
|---|---|---|---|
Host build + docker save + stream into machine via orb -m ... sh -c 'cat > /tmp/img.tar' + docker load | Build with current host Docker, export archive, stream-import inside machine. | Smallest change to existing build path. Avoids the broken orb push path on isolated machines. | Image archives can be large; transfer cost on every rebuild. Stream path is awkward but works today. |
Host build + orb push + machine docker load | Build with current host Docker, push tarball, import inside machine. | Simpler than stream. | Broken on isolated machines in v2.1.3 per orbstack/orbstack#2469. Available once OrbStack ships the fix. |
Host build + local registry + machine docker pull | Push image to a host-local or OrbStack-reachable registry. | Better layer reuse; aligns with future workspace registry cache. | Requires registry lifecycle and network policy design. Registry must be reachable from inside the isolated machine — needs network-block setting awareness. |
| Machine-local build | Copy role repo/build context into machine and run Docker build there. | Strongest boundary for build-time code execution. | Slower first implementation; more file-sync complexity. Same orb push workaround needed for the build context. |
Recommended phased path:
- V1: host build + stream-import via
docker save <img> | orb -m <machine> sh -c 'cat > /tmp/img.tar && docker load -i /tmp/img.tar && rm /tmp/img.tar'. Works today on v2.1.3. Latency cost: full image archive transferred per rebuild. Acceptance budget: first-launch import under 60 s for a typical 1.5-2 GB role image; subsequent reattach should not re-import. - V2: workspace registry cache integration for layer reuse once Workspace registry cache lands. Image transfer cost should drop to changed layers only.
- V3: machine-local builds for roles where build-time isolation matters. Build context still needs the stream workaround until
orb pushis fixed for isolated machines.
V1 is intentionally honest: runtime isolation improves but the host build path still executes role Dockerfiles, and the stream-import path is awkward enough that operators should expect noticeable first-launch latency. Document both honestly in the launch contract.
Machine Provisioning
Use cloud-init because OrbStack supports it directly with orb create -c.
Provisioning responsibilities:
- create a
jackinuser or use the OrbStack-created user with explicit sudo policy - install Docker engine and Compose where the selected distro does not include them
- create
/jackin/directories for runtime, state, run, host, and agent state - install or copy
jackin-capsule - configure the machine-local Docker daemon
- install basic debugging tools needed for
hardline --inspect - write a backend marker so support logs can identify the instance
All jackin❯-owned paths inside the role container still follow the /jackin/ container convention. Inside the OrbStack machine itself, jackin❯-owned machine state should also live under /jackin/ unless a third-party package forces a standard path.
Mount Transport
OrbStack isolated machines are useful only if jackin❯ uses selective file sharing instead of default full macOS filesystem integration.
Design requirements:
- Every workspace/global mount must become an explicit machine share (
orb create --isolated <name> --mount "<host_abs_path>:<container_path>", repeatable). - Read-only enforcement at the share layer is unconfirmed. The OrbStack docs and release notes are silent on a
:romodifier for--mount. Until verified on a real 2.1.3 install, jackin❯ must enforce read-only at the inner Docker layer (docker run -v src:dst:ro) and report enforcement asguest-enforcedin the launch contract. If OrbStack adds host-layer enforcement later, the contract upgrades tohost-enforced. - Mount destination control remains a jackin❯ feature. OrbStack's
--mount "host_abs:container_path"allows a different container-side path, so jackin❯ can map at the requesteddstdirectly. - Sensitive mount warnings still apply before launch.
- Worktree/clone isolation materializes on the host first today. The machine share then exposes the materialized worktree path. Tension: an isolated-machine premise of "only declared shares" is partly defeated if the worktree's host-side directory leaks structural information (sibling directories, parent path). Resolution: jackin❯ should materialize worktrees inside
~/.jackin/data/<instance>/worktrees/(already the convention) and only share that specific subdirectory, not its parents. Moving worktree materialization inside the machine (V3+) tightens this further.
Potential path model:
host source: /Users/operator/Projects/app
machine share: /Users/operator/Projects/app
role container: /workspace/appFor same-path mounts:
host source: /Users/operator/Projects/app
machine share: /Users/operator/Projects/app
role container: /Users/operator/Projects/appDocker Engine Inside The Machine
The backend must decide when to install/start Docker.
Suggested capability flag:
[runtime.docker]
requires_inner_engine = trueIf absent, use today's compatibility default: true for existing roles until role authors can opt out.
Engine options:
| Option | Fit |
|---|---|
distro docker.io package | Good first prototype; simple cloud-init install. |
| Docker CE apt repo | More current engine, but more bootstrap complexity. |
| rootless Docker inside machine | Stronger defense in depth, but needs testing with role workflows. |
| containerd-only | Future research; less compatible with current role expectations. |
The machine Docker daemon should be private to the machine and role. Do not forward its socket to macOS by default.
Attach and Lifecycle
The Docker backend currently relies on Docker container state for much of launch, reconnect, and cleanup behavior. OrbStack requires a backend-neutral instance registry.
Per-instance metadata should include:
instance_id
backend = "orbstack-isolated"
machine_name
machine_distro
role_container_name
role_image_ref
workspace_name or ad-hoc path
mounts and share handles
agent state handles
inner_engine_enabled
created_at
last_seen_at
cleanup_stateLifecycle mapping:
| jackin❯ operation | OrbStack action |
|---|---|
| launch | create/start machine, provision, import image, run role container. |
| attach | connect to jackin-capsule inside the role container through orb or SSH. |
| inspect | orb info, machine Docker inspect, capsule status, mount/share summary. |
| stop | stop role container, then optionally stop machine. |
| eject | stop role container and machine, remove transient resources. |
| purge | delete machine, remove state, remove imported images if owned by jackin. |
| hardline | restart machine if needed, verify role container, reconnect capsule. |
Open design question: whether one machine maps to one jackin❯ instance, one workspace, or one workspace plus many instances. V1 should use one machine per instance because it is easier to reason about cleanup and containment.
Network Policy
OrbStack release notes say isolated machines can block network connections to host/machines as of v2.1.2. jackin❯ should use that when the operator requests it, but it is not enough for full egress policy.
Network requirements:
- Services started in the machine may be reachable from macOS at
localhost; the session contract must list exposed ports. {machine}.orb.localnames exist; jackin❯ should not assume they are private.host.orb.internalcan reach Mac services in normal machine networking; a strict profile should block or report this path.- The backend should enable the isolated-machine "block host/machines" setting when
block_host_network = true, if OrbStack exposes it through CLI/config. - Domain allowlists and request logs still belong to Network egress policy.
Do not claim host-enforced egress policy until jackin❯ owns a host-side proxy or OrbStack exposes a policy surface that can be inspected and controlled per machine.
Authentication and Host Integration
OrbStack normal machines forward SSH agent access by default, but v2.1.2 release notes say isolated machines have opt-in SSH agent forwarding. jackin❯ must keep that opt-in.
Rules:
- SSH agent forwarding defaults to off for this backend.
- If an operator enables SSH agent forwarding, surface it in the launch summary.
- Do not rely on OrbStack's default Mac command integration for agent workflows.
- Do not let the machine run arbitrary macOS commands through
macas part of normal role execution. - Existing jackin❯ auth forwarding modes still apply to the role container, but stricter profiles should prefer future brokered credentials.
Security Contract
Launch output should say:
backend: orbstack-isolated
provider: OrbStack
machine: jackin-abcd1234
isolation: OrbStack isolated machine, shared-kernel architecture
host filesystem: explicit shares only
inner Docker: enabled, machine-local daemon
host Docker socket: not mounted
host/machine network: blocked | open | unknown
SSH agent forwarding: off | on
network egress policy: open | deny | allowlist | partial
residual risk:
OrbStack machines share a Linux kernel; this is not hypervisor-per-agent
isolation. Runtime build may still happen on host Docker in V1.The "shared-kernel" line is important. It avoids using microVM language for a backend that OrbStack itself documents differently.
Comparison With Docker Backend
| Concern | Docker backend | OrbStack isolated backend |
|---|---|---|
| Default platform | macOS/Linux Docker contexts | macOS only |
| Packaging | Dockerfile/OCI image | Dockerfile/OCI image |
| Runtime boundary | role container on selected Docker engine | role container inside an isolated OrbStack machine |
| Inner Docker | DinD sidecar | machine-local Docker daemon |
| Host filesystem | explicit Docker bind mounts | explicit isolated-machine shares, then inner Docker mounts |
| Host Docker socket | not mounted | not mounted |
| Kernel boundary | shared with Docker VM/Linux host | shared OrbStack Linux kernel |
| Network policy | per-agent network today; egress policy future | isolated-machine host/machine blocking plus future egress policy |
| Startup complexity | low | higher: machine provisioning plus image import |
| Best use | default local dev | stronger macOS local containment without leaving Docker workflows |
Implementation Phases
Phase 0 — discovery prototype
- Verify exact
orb create --isolatedCLI flags and selective share flags. - Verify whether the "block host/machines" setting is scriptable per machine.
- Verify isolated-machine SSH agent forwarding defaults and CLI control.
- Create a machine manually, install Docker, import a jackin❯ role image, and run
jackin-capsuleinside the role container. - Record cold-start, warm-start, image import, and attach latency.
Phase 1 — backend-neutral instance registry
- Extract backend kind/provider fields from Docker-specific naming.
- Persist OrbStack machine handles separately from Docker container names.
- Teach
hardline --inspectto report local manifest state even when the backend is not Docker.
Phase 2 — experimental launch path
- Add
orbstack-isolatedas a hidden or experimental backend. - Shell out to
orbfor machine lifecycle. - Use cloud-init to install Docker and create
/jackin/directories. - Use host-build + image archive import for role images.
- Run the role container inside the machine Docker engine.
Phase 3 — attach, reconnect, eject, purge
- Attach to capsule inside the role container.
- Reconnect to stopped/running machines.
- Cleanly stop/delete machines on eject/purge.
- Preserve isolated worktree cleanup behavior.
Phase 4 — security controls and contract output
- Add launch/session contract output for machine isolation, shares, inner Docker, network host/machine blocking, SSH agent forwarding, and residual risk.
- Connect Docker profile selection to the role container running inside the machine.
- Fail closed when the operator requests isolated behavior but OrbStack cannot enforce it.
Phase 5 — performance and caching
- Integrate with Workspace registry cache or a machine-local image cache.
- Reuse provisioned base machines if doing so does not blur containment.
- Add disk/resource visibility to the console resource panel.
Telemetry Surface
Backend operations should emit debug_log!("orbstack", …) (the existing macro in crates/jackin/src/console/tui.rs) so the firehose under JACKIN_DEBUG=1 reconstructs the full machine lifecycle. Minimum required lines:
orbstack version=<orb --version> isolated_supported=<yes|no>(probed at launch)machine_create name=<name> distro=<distro> isolated=<yes|no> shares=<count>machine_share host=<abs_path> guest=<path> mode=<rw|ro> enforcement=<host|guest>cloud_init source=<path> bytes=<n>image_transfer mode=<stream|orb-push|registry> bytes=<n> elapsed_ms=<n>inner_docker installed=<yes|no> version=<v>network_block host_machines=<on|off|unknown>(when CLI control becomes available)ssh_agent_forward=<on|off>attach transport=<orb-exec|ssh|tunnel> pty=<yes|no>machine_state action=<stop|delete|gc> result=<ok|failure> reason=<…>
Compact line per launch (future clog! tier):
orbstack launch machine=jackin-<id> isolated=yes shares=3 inner_docker=yes block_host_network=on image_import_ms=44230Schema Migration Footprint
This backend introduces these versioned-config additions; each lands with a CURRENT_*_VERSION bump per AGENTS.md:
| Surface | File kind | Type touched | Action |
|---|---|---|---|
[runtime.orbstack] enabled / default_distro / require_isolated / block_host_network / ssh_agent | config.toml | AppConfig | bump CURRENT_CONFIG_VERSION, add fixture under tests/fixtures/migrations/config/from-<predecessor>/. |
[workspaces.X.runtime] backend = "orbstack-isolated" | ~/.config/jackin/workspaces/<name>.toml | WorkspaceConfig | bump CURRENT_WORKSPACE_VERSION. |
[runtime.docker] requires_inner_engine = false (shared with hardening contract) | jackin.role.toml | RoleManifest | bump CURRENT_MANIFEST_VERSION. |
All three are additive. The instance manifest at crates/jackin-instance/src/manifest.rs also needs a backend_kind/provider_kind axis split, which is per-instance metadata (not a versioned schema in the AGENTS.md sense) but still needs a forward-compatible default for existing Docker-only instances.
Decided In This Pass
- Backend name is
orbstack-isolated, notmicrovm-orbstack(OrbStack documents shared-kernel architecture). - One machine per jackin❯ instance for V1 (easier cleanup and containment than per-workspace).
- V1 image flow: host build +
docker save | orb -m <name> sh -c 'cat > /tmp/img.tar && docker load && rm'. Avoids brokenorb pushon isolated machines. - Mount transport:
--mount "host_abs:container_path". Read-only enforced at the inner Docker layer (-v src:dst:ro) and reported asguest-enforceduntil OrbStack documents share-layer enforcement. - SSH agent forwarding default
off;block_host_networkdefaultononce the CLI surface is verified (until then, GUI-set only). - Inner Docker engine: distro
docker.iopackage via cloud-init for V1; rootless Docker is a V2+ research item. - Acceptance: first-launch image import under 60 s for ~1.5-2 GB images; reattach must not re-import.
- Worktree materialization stays at
~/.jackin/data/<instance>/worktrees/on the host; only that specific directory is shared into the machine — sibling/parent directories are not exposed.
Open Before Implementation Can Start
These need answers before Phase 1 code work begins. Several can be resolved in under an hour with an OrbStack 2.1.3 install:
orb create --helpandorb config --helpverification (under 5 minutes on a real install): confirm the exact flag names for--mountro modifier (if any), SSH agent forwarding opt-in, and theblock_host_networkconfig key. Until verified, the design has to assume each is GUI-only.orb -m <name> <cmd>PTY behavior (under 30 minutes empirical test): doesorb execallocate a real PTY? Does it forward SIGWINCH on terminal resize? Does Ctrl+P,Q detach pass through, or get consumed byorb? This is the make-or-break UX question for usingorb execas the attach transport. If PTY behavior is broken or partial, fall back to SSH tunneling.- Attach transport decision (depends on PTY answer):
orb -m ... docker exec, SSH into the machine +docker exec, or a forwarded Unix/TCP control channel for jackin-capsule. SSH gives the most control but adds asshdrequirement to the cloud-init. - Image-import latency budget on real hardware: measure 60 s acceptance against a typical role image on an M-series Mac with v2.1.3 stream-import. If the budget fails, V2 (registry cache) becomes a precondition for shipping rather than a follow-up.
- OrbStack auto-update mid-session behavior: not documented. Empirical test: trigger an in-app update while a jackin❯ machine is running. Document what happens (machine pause, kill, survive) and add a launch-time
clog!warning if a pending update is detected. - GC of orphaned machines: design the failure-mode GC. If
purgeis interrupted, does the nextjackin inspectdiscover and offer to clean orphanedjackin-<id>machines viaorb list? - Per-arch role image strategy: if a role image is amd64-only and the operator is on Apple Silicon, OrbStack runs it under Rosetta or Linux/aarch64 emulation. Decide whether jackin❯ warns, refuses, or transparently uses Rosetta.
Risks and Design Traps
- Accidentally using a normal OrbStack machine and exposing the full Mac filesystem instead of isolated selective shares.
- Calling OrbStack isolated machines "microVMs" and overstating the boundary.
- Forwarding SSH agent or Mac command integration by default.
- Forwarding the machine Docker socket back to macOS and recreating the host Docker socket problem.
- Building images on host Docker while presenting the whole flow as isolated.
- Reusing one machine across unrelated instances and making cleanup/state ownership unclear.
- Treating OrbStack support as a substitute for Linux/Kubernetes backend work.
Related Files
crates/jackin-runtime/src/runtime/launch.rs- launch orchestration that needs a backend split.crates/jackin-runtime/src/runtime/image.rs- role image build path.crates/jackin-docker/src/docker_client.rs- current Docker lifecycle boundary.crates/jackin-instance/src/manifest.rs- instance metadata that needs backend/provider fields.docker/runtime/entrypoint.sh- capsule startup inside the role container.docker/construct/Dockerfile- role base image that should remain reusable.
Related Roadmap Items
| Item | Relationship |
|---|---|
| Docker runtime hardening contract | The Docker profile still applies to the role container inside the OrbStack machine. |
| Selectable sandbox backends | Umbrella for backend selection. |
| Network egress policy | Required for real domain allowlists and connection logs. |
| Session contract and explain mode | Required to explain OrbStack's actual boundary. |
| Workspace registry cache | Potential image-transfer optimization for machine-local Docker. |
| Declarative resource limits | Needs translation to OrbStack machine and inner Docker limits. |