pi-microsandbox 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,48 +2,71 @@
2
2
 
3
3
  **Let your agents work. Stop babysitting every command.**
4
4
 
5
- Give an agent a task and get on with your day. Give a few agents different tasks
6
- and let them work in parallel. Come back to review the results.
7
-
8
- pi-microsandbox uses [Microsandbox](https://microsandbox.dev/) to run
5
+ Give an agent a task and get on with your day. pi-microsandbox uses
6
+ [Microsandbox](https://microsandbox.dev/) to run
9
7
  [Pi](https://github.com/earendil-works/pi)'s file and shell tools in lightweight
10
8
  microVMs. Microsandbox is an open-source, local-first runtime for isolating
11
9
  untrusted workloads, with a separate Linux kernel for each sandbox.
12
10
 
13
- In Git mode, each separate Pi session gets its own workspace instead of editing
14
- your host checkout. Each project can define its own environment and safety
15
- boundaries. Set them up once, then let the agents get to work.
11
+ Each project can define its own environment and safety boundaries. Set them up
12
+ once, then let the agent get to work.
16
13
 
17
14
  [Get started](#get-started) · [Documentation](#documentation) · [Releases](https://github.com/hcohe/pi-microsandbox/releases)
18
15
 
16
+ ## Try it
17
+
18
+ Run Pi with pi-microsandbox for one session, without installing it:
19
+
20
+ ```sh
21
+ pi -e npm:pi-microsandbox
22
+ ```
23
+
19
24
  ## Less supervision. More work getting done.
20
25
 
21
- - Run multiple agents in separate Pi sessions. Git mode keeps their workspaces apart, so ordinary sandboxed edits don't collide in your host checkout.
22
- - Let routine file and shell work happen inside the sandbox. Host execution stays an explicit escape, with approval required while the sandbox is active.
23
- - Step away without throwing away the work. Git-mode files survive sandbox shutdown, ready when you resume the matching session.
24
- - If the sandbox can't start, routed tools stop by default. They don't quietly run on your host instead.
26
+ - Let routine file and shell work happen inside the sandbox. Host execution
27
+ stays an explicit escape, with approval required while the sandbox is active.
28
+ - Work at the same path inside and outside the VM. Sandboxed writes appear in
29
+ the host checkout immediately, with no export step.
30
+ - If the sandbox cannot start, routed tools stop by default. They do not quietly
31
+ run on your host instead.
32
+
33
+ You still review what the agent produces. The point is to spend your attention
34
+ on the results rather than supervise every step along the way.
35
+
36
+ ## One workspace behavior
25
37
 
26
- You still review what the agents produce. The point is to spend your attention
27
- on the results, rather than supervise every step along the way.
38
+ There are no workspace modes. If Pi starts inside a Git worktree,
39
+ pi-microsandbox mounts the whole worktree root read/write at the same lexical
40
+ path in the guest. If Pi starts outside Git, it mounts the current working
41
+ directory itself. Commands start in the original current working directory.
42
+
43
+ This is a VM boundary, not checkout isolation. The selected root is fully
44
+ visible, including `.git`, secrets such as `.env`, untracked files, and sibling
45
+ directories. Writes change the host immediately. Multiple sessions using the
46
+ same checkout share those files and can conflict; use separate host worktrees
47
+ or checkouts when you need independent changes. Containers started inside the
48
+ microVM can also reach the mounted workspace.
49
+
50
+ [Understand workspace storage and legacy-volume recovery →](docs/storage.md)
28
51
 
29
52
  ## Every project gets its own boundaries
30
53
 
31
- Your frontend app and your internal service don't need the same sandbox.
54
+ Your frontend app and your internal service do not need the same sandbox.
32
55
  Choose a [published variant or custom image](docs/images.md) with the tools a
33
56
  project needs, allow only the network hosts it should reach, and configure its
34
- file mounts and secrets. Another project can have a completely different setup,
57
+ extra file mounts and secrets. Another project can have a different setup,
35
58
  including no network access.
36
59
 
37
- Keep your everyday defaults in global config and project-specific settings in
60
+ Keep everyday defaults in global config and project-specific settings in
38
61
  `.pi-msb.toml`. Trusted project config layers over those defaults; environment
39
- variables and session overrides let you adjust a particular run without
40
- rewriting the project's setup.
62
+ variables and session overrides let you adjust a run without rewriting the
63
+ project setup.
41
64
 
42
65
  The agent gets an environment built for the job. Image cohorts built from this
43
66
  version include Docker Engine 29.8.0, Buildx 0.37.1, and Compose 5.5.1. The
44
- daemon and its containers run inside the microVM; pi-microsandbox never connects them to the
45
- host Docker socket. You don't have to make the same decisions every time you
46
- start it.
67
+ daemon and its containers run inside the microVM; pi-microsandbox never connects
68
+ them to the host Docker socket. Nested containers can still access the mounted
69
+ workspace and remain subject to the outer network policy.
47
70
 
48
71
  [Configure your project's sandbox →](docs/configuration.md)
49
72
 
@@ -73,46 +96,36 @@ binary with `MSB_PATH`. See the official
73
96
  installation and runtime troubleshooting. The documentation in this repository
74
97
  covers the Pi integration.
75
98
 
76
- From a Git repository, start Pi with its own isolated workspace:
99
+ Start Pi from the directory where you want to work:
77
100
 
78
101
  ```sh
79
- PI_MSB_MODE=git pi
102
+ cd /path/to/project
103
+ pi
80
104
  ```
81
105
 
82
- Git mode starts from committed `HEAD`. Commit any changes you want the agent to
83
- see first; untracked files such as `.env` and uncommitted edits stay out of the
84
- initial copy. An existing retained workspace is reused for a matching session.
85
-
86
- Once you're in Pi:
106
+ Once you're in Pi, inspect the selected workspace root:
87
107
 
88
108
  ```text
89
109
  /msb status
90
110
  ```
91
111
 
92
- Give Pi a task. To work on another task in parallel, start a separate Pi session
93
- with the same command in another terminal. Each session gets its own Git-mode
94
- workspace.
95
-
96
- When you're ready to review an agent's work, export a file to a new destination:
97
-
98
- ```text
99
- /msb export src/example.ts --to ../sandbox-review
100
- ```
101
-
102
- Exports ask for confirmation and won't overwrite existing destinations.
103
- See [storage and retained work](docs/storage.md) for the details.
112
+ > **Host execution is separate.** `/msb off` explicitly hands tools to the
113
+ > host. `fallback_mode = "host"` opts into automatic host execution after a
114
+ > sandbox failure. Neither control changes the workspace mount, and neither is
115
+ > sandboxed. The default fallback blocks tools when startup fails.
104
116
 
105
- > **Choose your boundary.** The default storage mode is `direct`, which writes
106
- > to your host directory. The command above explicitly selects `git` isolation.
107
- > `/msb off` turns sandboxing off; `fallback_mode = "host"` opts into automatic
108
- > host execution after a failure. Neither is sandboxed.
117
+ Upgrading from a release that used named Git volumes requires a manual recovery
118
+ check. Before upgrading, use the old `/msb volumes` and `/msb export` commands
119
+ to inventory and copy retained work. After upgrading, use Microsandbox's own
120
+ tooling to recover or remove legacy volumes; they are never deleted
121
+ automatically. See [workspace storage](docs/storage.md).
109
122
 
110
123
  ## Documentation
111
124
 
112
125
  | When you want to… | Read |
113
126
  | --- | --- |
114
127
  | Install or check host support | [Getting started](docs/getting-started.md) |
115
- | Choose a workspace mode or recover retained work | [Storage](docs/storage.md) |
128
+ | Understand the workspace mount or recover legacy volumes | [Storage](docs/storage.md) |
116
129
  | Choose an image variant or build a custom image | [Images](docs/images.md) |
117
130
  | Set up networking, secrets, mounts, or other options | [Configuration](docs/configuration.md) |
118
131
  | Look up an `/msb` command | [Command reference](docs/commands.md) |
package/SECURITY.md CHANGED
@@ -26,7 +26,7 @@ public channel.
26
26
  A useful report includes the affected pi-microsandbox version or commit, Pi and
27
27
  Node.js versions, host operating system and architecture, virtualization setup,
28
28
  impact, and minimal reproduction steps. State whether the behavior requires a
29
- particular storage mode, network policy, fallback setting, or host-execution
29
+ particular workspace layout, network policy, fallback setting, or host-execution
30
30
  approval.
31
31
 
32
32
  ## Keep sensitive data out of reports
@@ -39,13 +39,17 @@ not include:
39
39
  - resolved secret values from `$ENV:` or `$FILE:` references;
40
40
  - complete sandbox logs, configuration dumps, session files, or command output
41
41
  that may contain secrets;
42
- - retained-volume contents, source code, `.env` files, or other private user
43
- data that is not essential to the report.
44
-
45
- If a real secret may have been exposed, revoke or rotate it first. Use synthetic
46
- values in the reproduction and describe omitted material rather than attaching
47
- it. Remember that GitHub advisory participants can read uploaded artifacts, so
48
- a private report is not a reason to include unnecessary secrets.
42
+ - workspace or legacy-volume contents, source code, `.env` files, or other
43
+ private user data that is not essential to the report.
44
+
45
+ If a real secret may have been exposed, revoke or rotate it first. The selected
46
+ workspace is mounted read/write: inside Git it includes the entire worktree,
47
+ including `.git`, secrets, untracked files, and sibling directories; outside
48
+ Git it is the current directory. Writes reach the host immediately, concurrent
49
+ sessions share the checkout, and nested containers can access the mount. Use
50
+ synthetic values in the reproduction and describe omitted material rather than
51
+ attaching it. Remember that GitHub advisory participants can read uploaded
52
+ artifacts, so a private report is not a reason to include unnecessary secrets.
49
53
 
50
54
  ## What happens next
51
55
 
package/docs/commands.md CHANGED
@@ -8,9 +8,6 @@ The extension registers `/msb`:
8
8
  /msb status
9
9
  /msb on | off | reload
10
10
  /msb prune
11
- /msb volumes ls
12
- /msb volumes rm <managed-name> [--yes]
13
- /msb export <paths...> [--to dir] [--yes]
14
11
  /msb logs [tail-lines]
15
12
  /msb config
16
13
  /msb set <key> <value>
@@ -23,17 +20,23 @@ The extension registers `/msb`:
23
20
  /msb help
24
21
  ```
25
22
 
26
- `/msb status` reports the full sandbox name, mode, image, PID, age, Docker
27
- mode/readiness/version/storage driver, branch/SHA, and retained volume metadata
28
- when available. Six-character IDs in UI text are
29
- display abbreviations only. `/msb prune` walks all SDK list pages and reports
30
- removed, kept, and error entries; **volumes are never pruned**.
23
+ `/msb status` reports the full sandbox name, mounted workspace root, image, PID,
24
+ age, and Docker mode, readiness, version, and storage driver. Six-character IDs
25
+ in UI text are display abbreviations only. There are no workspace modes.
31
26
 
32
- Volume removal is the sole destructive volume path. It requires a managed,
33
- unmounted volume and an owner lock. Confirmation displays path, branch, last
34
- commit, and dirty-count metadata; use `--yes` only when the command is running
35
- without UI and the target has already been verified. Export rejects paths outside
36
- the project and existing destinations; it also requires confirmation or
37
- `--yes`.
27
+ `/msb prune` walks all SDK list pages and reports removed, kept, and error
28
+ entries. It can remove guarded stale sandboxes, including old-schema managed
29
+ sandboxes, but it never removes legacy named volumes.
38
30
 
39
- For the narrow exceptions to sandboxed file reads, see [host-read exceptions](safety.md#host-read-exceptions).
31
+ `/msb off` explicitly switches to unsandboxed host execution. It is separate
32
+ from `fallback_mode = "host"`, which opts into automatic host execution after a
33
+ sandbox failure. With the default blocking fallback, startup failures fail
34
+ closed and routed tools do not silently run on the host.
35
+
36
+ The former `/msb volumes` and `/msb export` commands are not available. Files in
37
+ the current workspace already live on the host. Legacy named volumes from older
38
+ releases require manual inspection, recovery, and removal with Microsandbox's
39
+ own tooling; see [workspace storage](storage.md#upgrading-from-named-git-volumes).
40
+
41
+ For the narrow exceptions to sandboxed file reads, see
42
+ [host-read exceptions](safety.md#host-read-exceptions).
@@ -7,14 +7,14 @@ CLI overrides. Global configuration is `$XDG_CONFIG_HOME/pi-msb/config.toml`
7
7
  (or `~/.config/pi-msb/config.toml`) plus the optional `PI_MSB_CONFIG_FILE` in
8
8
  the same layer. A trusted project may use the nearest `.pi-msb.toml` or
9
9
  `<Pi CONFIG_DIR_NAME>/msb.toml`, stopping at the Git root. Untrusted project
10
- configuration is ignored with a warning.
10
+ configuration is ignored with a warning, except that removed workspace settings
11
+ still stop startup before any direct host write can occur.
11
12
 
12
13
  TOML uses snake_case; environment variables use `PI_MSB_` with `__` for nesting.
13
14
  The following is a small project example:
14
15
 
15
16
  ```toml
16
17
  # .pi-msb.toml
17
- mode = "git"
18
18
  image = "ghcr.io/hcohe/pi-microsandbox:1.1.0@sha256:ab4e99d4232f827b3f295ff3210437e01446dbb672ef0d0c78358566170ac86c"
19
19
  pull_policy = "if-missing"
20
20
  bootstrap_tools = "auto"
@@ -41,15 +41,22 @@ allow_hosts = ["registry.npmjs.org"]
41
41
 
42
42
  Important configuration behavior:
43
43
 
44
+ - There are no workspace modes or storage selection settings. Inside a Git
45
+ worktree, the whole worktree root is mounted read/write at the same lexical
46
+ guest path; elsewhere, the current directory is mounted. Commands retain the
47
+ original cwd, and writes reach the host immediately. The removed `mode`,
48
+ `clone_branch`, `clone_depth`, `shallow_archive`, and `volume_quota_mib`
49
+ settings, including `PI_MSB_MODE`, are startup errors rather than ignored
50
+ compatibility options.
44
51
  - `show_footer = true` uses Pi's single custom-footer slot so the MSB status can
45
52
  appear in the upper-right corner. It replaces Pi's built-in footer (or another
46
53
  extension's custom footer), preserves the standard location, usage, model,
47
54
  and shared status fields, but cannot show Pi-only indicators such as the
48
55
  auto-compaction and experimental-feature markers.
49
- - The default image is the complete Node.js, Python, Rust, and Go `1.0.0`
56
+ - The default image is the complete Node.js, Python, Rust, and Go `1.1.0`
50
57
  variant, pinned to its immutable multi-platform digest. Image releases have
51
- an independent version stream; the initial package remains `0.1.0`. The
52
- default `pull_policy = "if-missing"` pulls only when that exact reference is
58
+ an independent version stream from package releases. The default
59
+ `pull_policy = "if-missing"` pulls only when that exact reference is
53
60
  absent from the Microsandbox cache. `"always"` and `"never"` are also
54
61
  supported.
55
62
  See [Images](images.md) for all published variants, exact tag patterns,
@@ -84,8 +91,9 @@ Important configuration behavior:
84
91
  `BASH_ENV`, and `LD_PRELOAD` cannot be forwarded with `host_env` or injected
85
92
  as secrets.
86
93
  - Directory/file mounts have absolute guest paths. Project mounts outside the
87
- repository must be read-only unless a global/session policy authorizes the
88
- write. Mounts may not overlap or shadow the project mount, reserved `/tmp`,
94
+ selected workspace root must be read-only unless a global/session policy
95
+ authorizes the write. Mounts may not overlap or shadow the project mount,
96
+ reserved `/tmp`,
89
97
  protected guest system trees such as `/usr`, `/bin`, `/proc`, and `/sys`, or
90
98
  Docker runtime paths such as `/run`, `/var/run`, and `/var/lib/docker`.
91
99
  Host mount sources are canonicalized before use; socket targets, including
@@ -97,7 +105,6 @@ Useful environment controls include:
97
105
 
98
106
  ```sh
99
107
  PI_MSB_DISABLE=1 # explicit host/off mode
100
- PI_MSB_MODE=none # nested scalar example
101
108
  PI_MSB_PULL_POLICY=always # recheck mutable custom image tags on creation
102
109
  PI_MSB_NETWORK__MODE=deny # nested environment key
103
110
  PI_MSB_DOCKER__MODE=require # require a working guest Docker daemon
@@ -103,9 +103,9 @@ just test-boot-speed
103
103
  ```
104
104
 
105
105
  The tool performs one unmeasured warm-up, then three fresh boots using the
106
- default prepared image. It forces direct mode, disables guest networking and
107
- stale-resource pruning, and sets `bootstrap_tools = false` so the result
108
- measures repeat boot and readiness rather than an image pull or package install.
106
+ default prepared image. It disables guest networking and stale-resource
107
+ pruning, and sets `bootstrap_tools = false` so the result measures repeat boot
108
+ and readiness rather than an image pull or package install.
109
109
  The p95 must be at most 2,000 ms. Every sandbox is shut down and removed. If
110
110
  lifecycle cleanup fails, the test fails and retains its reported `.tmp` directory
111
111
  for recovery instead of claiming success.
@@ -127,9 +127,9 @@ as the live matrix.
127
127
  ## Live test matrix
128
128
 
129
129
  From a source checkout, the live matrix is opt-in because it can pull an image,
130
- start VMs, create retained resources, and use network and disk capacity. Run it
131
- only from a trusted checkout on a disposable test host after reviewing the
132
- script:
130
+ start VMs, write through the host workspace mount, and use network and disk
131
+ capacity. Run it only from a trusted checkout on a disposable test host after
132
+ reviewing the script:
133
133
 
134
134
  ```sh
135
135
  PI_MSB_LIVE_TEST=1 ./scripts/e2e-smoke.sh
@@ -149,10 +149,14 @@ The prepared-image scenario boots all six latest variant tags under
149
149
  legacy singular `PI_MSB_LIVE_PREPARED_IMAGE` to test one image. The live matrix
150
150
  uses `pull_policy = "always"` intentionally so mutable development tags cannot
151
151
  remain stale on the self-hosted runner. Review the output to confirm that every scenario reports `PASS`, not `SKIP`.
152
- Docker release validation must cover daemon readiness, bridge DNS and HTTPS,
153
- user-defined networking, Buildx, Compose, idle wake, double port publishing,
154
- and nested-container enforcement for deny and allowlist policies. A skipped
155
- Docker scenario is not release evidence.
152
+ The workspace scenarios must show that a Git subdirectory mounts the whole
153
+ worktree, a non-Git cwd mounts itself, and routed writes appear immediately on
154
+ the host. They also cover off/on and reload, stale-sandbox pruning, fail-closed
155
+ boot errors, and approved host execution. Docker release validation must cover
156
+ daemon readiness, bridge DNS and HTTPS, user-defined networking, Buildx,
157
+ Compose, idle wake, double port publishing, nested-container access to the
158
+ workspace, and network enforcement for deny and allowlist policies. A skipped
159
+ scenario is not release evidence.
156
160
 
157
161
  ## Image development
158
162
 
@@ -64,7 +64,19 @@ blocks routed tools rather than silently running them on the host. Keep that
64
64
  default for a fail-closed setup. `fallback_mode = "host"` is an explicit,
65
65
  visibly labelled opt-in to automatic unsandboxed execution.
66
66
 
67
- The public package is named `pi-microsandbox`. Existing technical interfaces
68
- retain the shorter `msb` name for compatibility, including `/msb`,
69
- `PI_MSB_*`, `.pi-msb.toml`, configuration directories, and managed-resource
70
- labels. Existing configuration and retained resources therefore keep working.
67
+ The public package is named `pi-microsandbox`. Current technical interfaces
68
+ retain the shorter `msb` name, including `/msb`, `PI_MSB_*`, `.pi-msb.toml`,
69
+ configuration directories, and managed-resource labels.
70
+
71
+ There are no workspace modes. Starting inside Git mounts the entire worktree
72
+ root read/write; starting elsewhere mounts the cwd. The mount uses the same
73
+ lexical guest path, commands retain their original cwd, and writes reach the
74
+ host immediately. This exposes `.git`, secrets, untracked files, and sibling
75
+ directories. Concurrent sessions share a checkout, and nested containers can
76
+ reach the mount.
77
+
78
+ Before upgrading from a release with named Git workspaces, use its `/msb
79
+ volumes` and `/msb export` commands to inventory and copy retained work. The new
80
+ release neither reconnects nor deletes legacy volumes. Recover or remove them
81
+ manually with Microsandbox tooling after confirming their contents. Removed
82
+ settings such as `mode` and `PI_MSB_MODE` are errors, not compatibility aliases.
package/docs/images.md CHANGED
@@ -66,12 +66,13 @@ can install current packages at runtime.
66
66
 
67
67
  ## Build a custom image
68
68
 
69
- A custom image must provide `bash`, `sh`, `git`, `rg`, `file`, `cat`, `mkdir`,
70
- and `rm`. Docker is optional for custom images. The default `docker.mode =
71
- "auto"` records it as missing and continues; use `docker.mode = "require"` when
72
- the image contract must include a working daemon. pi-microsandbox does not
73
- install Docker during sandbox startup. Install CA certificates if the guest
74
- will use Git over HTTPS. With
69
+ A custom image must provide `bash`, `sh`, `rg`, `file`, `cat`, `mkdir`, and
70
+ `rm`. Git is a useful developer tool and remains in the published images, but
71
+ workspace setup no longer requires it inside the guest. Docker is optional for
72
+ custom images. The default `docker.mode = "auto"` records it as missing and
73
+ continues; use `docker.mode = "require"` when the image contract must include a
74
+ working daemon. pi-microsandbox does not install Docker during sandbox startup.
75
+ Install Git and CA certificates if guest commands need Git over HTTPS. With
75
76
  `bootstrap_tools = "auto"`, pi-microsandbox can install missing required
76
77
  commands through `apt-get` when the network policy permits it. A prepared image
77
78
  is required when bootstrap is disabled or package repositories are unavailable.
package/docs/safety.md CHANGED
@@ -4,24 +4,35 @@
4
4
 
5
5
  The default is fail-closed:
6
6
 
7
- - A valid, trusted project configuration is resolved before a sandbox is
8
- started. A boot or image/tool failure blocks the seven routed tools (`read`,
9
- `write`, `edit`, `ls`, `find`, `grep`, and `bash`).
10
- - `mode = "auto"` is retained as an alias for `"direct"`; both use a
11
- same-absolute-path read/write bind. `mode = "git"`, `"direct"`, and
12
- `"none"` select those behaviors explicitly.
7
+ - A valid, trusted project configuration is resolved before a sandbox starts. A
8
+ boot, image, configuration, or tool failure blocks the seven routed tools
9
+ (`read`, `write`, `edit`, `ls`, `find`, `grep`, and `bash`). Failure never
10
+ silently falls back to host execution.
13
11
  - `execution_target = "host"` is an opt-in escape for routed tool calls. While
14
- a sandbox is active it requires an interactive approval for the exact tool,
15
- working directory, and recursively sorted arguments. It is not available in
12
+ a sandbox is active it requires interactive approval for the exact tool,
13
+ working directory, and recursively sorted arguments. It is unavailable in
16
14
  headless operation and is never silently selected.
17
15
  - `/msb off` is an explicit host-mode handoff and does not prompt. This is
18
16
  different from `fallback_mode = "host"`, which automatically uses host tools
19
- after a sandbox failure and is shown as `MSB host fallback`.
17
+ after a sandbox failure and is shown as `MSB host fallback`. Both are
18
+ unsandboxed controls, not workspace settings.
20
19
  - A project cannot replace another process's sandbox: ownership is a
21
- non-blocking kernel `flock` acquired before any sandbox or volume mutation.
22
- The small bundled POSIX addon is loaded lazily, has no install script, and
23
- never falls back to a racy PID check. Stale sandbox pruning never removes
24
- volumes.
20
+ non-blocking kernel `flock` acquired before sandbox mutation. The small
21
+ bundled POSIX addon is loaded lazily, has no install script, and never falls
22
+ back to a racy PID check.
23
+
24
+ There are no workspace modes. Inside a Git worktree, pi-microsandbox
25
+ bind-mounts the entire worktree root read/write at the same lexical guest path.
26
+ Outside Git, it bind-mounts the current directory. Commands start in the
27
+ original current directory, but their path boundary is the selected root.
28
+
29
+ This mount deliberately exposes host files. A Git worktree mount includes
30
+ `.git`, untracked files, secrets such as `.env`, and sibling directories even
31
+ when Pi starts in a subdirectory. Writes are immediately visible on the host,
32
+ and separate sessions using the same checkout can read or overwrite one
33
+ another's work. Use separate host worktrees or checkouts for isolation between
34
+ sessions. Unsafe root mappings fail startup rather than falling back to a
35
+ narrower mount.
25
36
 
26
37
  The extension entry point does not import the native SDK or load the flock
27
38
  addon. Unsupported hosts can still load Pi and remain blocked or explicitly
@@ -35,15 +46,15 @@ socket. Access to that socket is root-equivalent inside the guest, not on the
35
46
  host. Readiness probes explicitly select that socket and reject unverified
36
47
  socket ownership. Docker and process-control environment variables are cleared
37
48
  for preparation, and configuration cannot forward them. Mounts that shadow
38
- protected guest executables or Docker runtime paths are rejected. The extension never mounts the host Docker
39
- socket, starts a host daemon, or copies host Docker configuration and registry
40
- credentials into the guest.
49
+ protected guest executables or Docker runtime paths are rejected. The extension
50
+ never mounts the host Docker socket, starts a host daemon, or copies host Docker
51
+ configuration and registry credentials into the guest.
41
52
 
42
- A container can still reach anything already mounted into the microVM. In
43
- `direct` mode that includes the host project directory; in Git mode it includes
44
- the retained workspace; explicitly configured mounts are visible too. Treat a
45
- Dockerfile or Compose file as guest-root code and use read-only mounts where
46
- possible. Container egress remains behind the Microsandbox network policy.
53
+ A nested container can still reach anything mounted into the microVM, including
54
+ the entire selected workspace and explicitly configured mounts. Treat a
55
+ Dockerfile or Compose file as guest-root code and use read-only extra mounts
56
+ where possible. Container egress remains behind the Microsandbox network
57
+ policy.
47
58
 
48
59
  ## Host-read exceptions
49
60
 
@@ -56,4 +67,5 @@ become readable.
56
67
 
57
68
  ## Reporting vulnerabilities
58
69
 
59
- Report suspected vulnerabilities privately. See the [security policy](../SECURITY.md); do not open a public issue.
70
+ Report suspected vulnerabilities privately. See the
71
+ [security policy](../SECURITY.md); do not open a public issue.
package/docs/storage.md CHANGED
@@ -1,19 +1,31 @@
1
- # Storage modes and retained work
1
+ # Workspace storage
2
2
 
3
3
  [Back to README](../README.md)
4
4
 
5
- ## Storage modes
5
+ ## One read/write workspace
6
6
 
7
- | Mode | Guest view | Host effect of routed writes |
8
- | --- | --- | --- |
9
- | `git` | A named volume at the repository root, with the same absolute path | Volume only |
10
- | `direct` | The current directory bind-mounted at the same absolute path | Host directory |
11
- | `none` | An empty tmpfs at the same absolute path | No host files; changes disappear with the sandbox |
12
- | `auto` | Same as `direct` | Host directory |
7
+ There are no workspace modes. pi-microsandbox selects one workspace root when
8
+ it starts:
13
9
 
14
- `direct` is intentionally a warning-level escape from the Git isolation model:
15
- routed edits modify the live host directory. `none` is useful for testing path
16
- behavior and starts empty; it is not a retained workspace.
10
+ - If the current working directory is inside a Git worktree, it mounts the
11
+ entire worktree root.
12
+ - Otherwise, it mounts the current working directory itself.
13
+
14
+ The selected root is bind-mounted read/write at the same lexical path inside
15
+ the guest. Commands still start in the original current working directory.
16
+ Writes are immediately visible in the host directory; there is no export or
17
+ synchronization step.
18
+
19
+ Starting Pi below a Git worktree root does not narrow the boundary. The sandbox
20
+ can see the whole worktree, including `.git`, untracked files, sibling
21
+ directories, and files such as `.env`. Separate Pi sessions that use the same
22
+ checkout also use the same files, so their edits can conflict. Use separate
23
+ host worktrees or checkouts when tasks need independent workspaces.
24
+
25
+ The extension creates one project bind mount. Linked-worktree or submodule Git
26
+ metadata stored outside the selected worktree root is not mounted separately.
27
+ An unsupported path or symlink layout fails startup instead of silently
28
+ mounting a narrower directory.
17
29
 
18
30
  ## Inner Docker state
19
31
 
@@ -21,51 +33,38 @@ Docker stores images, layers, containers, and build cache under
21
33
  `/var/lib/docker` on the sandbox root filesystem. It uses the `vfs` storage
22
34
  driver because nested overlay filesystems and project-backed mounts cannot be
23
35
  assumed to support `overlay2`. This state disappears when the sandbox is
24
- removed. It is not written to the project mount or retained Git volume, and
25
- separate sessions do not share an inner Docker cache.
26
-
27
- A stopped sandbox may retain that state until it is restarted or removed, but a
28
- retained Git workspace does not preserve it. Do not move Docker's data root
29
- onto the Git volume. A persistent Docker cache would need a separate managed
30
- volume and cleanup policy.
31
-
32
- ## Git and retained volumes
33
-
34
- Git mode never bind-mounts the host checkout. On boot, pi-microsandbox captures the
35
- committed `HEAD` (and selected branch) into a temporary verified Git bundle,
36
- copies it into the guest, and seeds a named volume mounted at the repository's
37
- absolute root. Untracked files, including `.env`, and working-tree edits are
38
- not in that bundle. The temporary host and guest bundle files are removed after
39
- seeding, including failure paths.
40
-
41
- Edits and commits made in Git mode land in the retained volume. The host
42
- checkout is not changed by ordinary routed tools. A normal Pi session shutdown
43
- removes the sandbox but keeps the managed volume; the next boot reuses it only
44
- when the complete session/schema/mode/cwd identity matches. A copied or forked
45
- session state is rejected by the full session ID and gets a different resource
46
- identity.
47
-
48
- The SDK's `VolumeHandle` returned by `Volume.get()` does not expose a host
49
- path. pi-microsandbox therefore refuses to fabricate one: a newly created volume
50
- may show its path, while a later retained-volume lookup may not support
51
- `/msb volumes ls` or volume enrichment. The volume remains mountable by name
52
- and is never automatically deleted. Use the path recorded at creation time or
53
- the microsandbox volume tooling when host-side inspection is required.
54
-
55
- To manually synchronize a retained checkout, use a host-side fetch deliberately
56
- (the command is not performed automatically by pi-microsandbox):
36
+ removed and is not written to the project mount. Separate sessions do not share
37
+ an inner Docker cache.
38
+
39
+ Containers started inside the microVM can reach the mounted workspace. Treat
40
+ Dockerfiles and Compose files as code with access to the entire selected root.
41
+
42
+ ## Upgrading from named Git volumes
43
+
44
+ Older releases could keep Git workspaces in named `pi-msb-vol-*` volumes. The
45
+ new workspace behavior does not reconnect, migrate, or delete those volumes.
46
+ They may contain the only copy of unexported work.
47
+
48
+ Before upgrading, while the old `/msb volumes` and `/msb export` commands are
49
+ still available, inventory every retained volume and export or copy any work
50
+ you need. After upgrading, use Microsandbox itself:
51
+
52
+ ```sh
53
+ msb volume ls
54
+ mkdir -p ./legacy-workspace-recovery
55
+ msb run --name pi-msb-recovery \
56
+ --mount-named pi-msb-vol-REPLACE_ME:/legacy:ro \
57
+ --mount-dir "$PWD/legacy-workspace-recovery:/recovery:rw" \
58
+ alpine -- sh -c 'cp -a /legacy/. /recovery/'
59
+ msb rm pi-msb-recovery
60
+ ```
61
+
62
+ Verify the copied files, then remove the old volume with:
57
63
 
58
64
  ```sh
59
- REPO=/absolute/path/to/checkout
60
- VOLUME_PATH=/path/returned-for-the-managed-volume
61
- BRANCH=$(git -C "$REPO" branch --show-current)
62
-
63
- git -C "$VOLUME_PATH" remote remove host 2>/dev/null || true
64
- git -C "$VOLUME_PATH" remote add host "$REPO"
65
- git -C "$VOLUME_PATH" fetch --no-tags host "$BRANCH"
66
- # Review before changing the retained checkout:
67
- git -C "$VOLUME_PATH" log --oneline --decorate --all -10
65
+ msb volume rm pi-msb-vol-REPLACE_ME
68
66
  ```
69
67
 
70
- The host repository is an input to this explicit sync operation. Do not add a
71
- host checkout bind mount to Git mode.
68
+ Copy the exact name from `msb volume ls`: a mistyped named mount can create a
69
+ new empty volume. Choose an already-cached recovery image if `alpine` is
70
+ unavailable. pi-microsandbox no longer lists, removes, or exports volumes.