windows-development-sandbox 1.17.0 → 1.17.3

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
@@ -12,9 +12,10 @@
12
12
 
13
13
  </div>
14
14
 
15
- Run it in a project folder and you get a clean [Windows Sandbox](https://learn.microsoft.com/windows/security/application-security/application-isolation/windows-sandbox/windows-sandbox-overview)
16
- where that folder is the workspace, the tools and databases the project needs install themselves, and nothing else
17
- on your PC is reachable. Close it and it's gone. Your project, tools, databases and logins are kept for next time.
15
+ Run it in a project folder to get a clean
16
+ [Windows Sandbox](https://learn.microsoft.com/windows/security/application-security/application-isolation/windows-sandbox/windows-sandbox-overview).
17
+ The folder is the workspace, the tools and databases it needs install themselves, and the rest of your PC is out of
18
+ reach. Close it and it is gone. Your project, tools, databases and logins are kept for next time.
18
19
 
19
20
  ## Install
20
21
 
@@ -22,130 +23,129 @@ on your PC is reachable. Close it and it's gone. Your project, tools, databases
22
23
  irm https://github.com/JoshDiDuca/windows-development-sandbox/releases/latest/download/install.ps1 | iex
23
24
  ```
24
25
 
25
- It checks your PC, offers to turn on Windows Sandbox, and asks **1) Just me** or **2) Everyone on this PC** (needs
26
- admin). It brings its own private copy of Node.js; nothing else is installed system-wide, and no Start menu shortcut
27
- unless you ask for one. `sandbox update` installs newer versions (and can do it by itself), even while a sandbox runs:
28
- the sandbox keeps its version until it restarts. A version that fails to start is rolled back automatically, and
29
- `sandbox update --rollback` goes back one by hand.
26
+ The installer checks your PC, offers to turn on Windows Sandbox, and asks **1) Just me** or **2) Everyone on this PC**
27
+ (needs admin). It brings its own copy of Node.js and installs nothing else system-wide. It adds no Start menu shortcut
28
+ unless you ask.
30
29
 
31
- Needs Windows 10/11 **Pro, Enterprise or Education**. Have Node.js 20+? `npm install -g windows-development-sandbox`
32
- works too. [Scopes, options (`-Version`, `-StartMenuShortcut` ...), upgrading, uninstall](docs/install.md)
30
+ - `sandbox update` installs a newer version, and can do it by itself. A running sandbox keeps its version until it
31
+ restarts.
32
+ - A new version that fails to start is rolled back for you. `sandbox update --rollback` goes back one version by hand.
33
+
34
+ Needs Windows 10/11 **Pro, Enterprise or Education**. With Node.js 20+, `npm install -g windows-development-sandbox`
35
+ works too. More: [install options, upgrading, uninstall](docs/install.md).
33
36
 
34
37
  ## Use
35
38
 
36
39
  ```powershell
37
40
  cd C:\code\my-app
38
41
 
39
- sandbox # the menu: agents, sessions, apps, every setting, diagnostics ...
42
+ sandbox # the menu: agents, sessions, apps, settings, health ...
40
43
  sandbox claude # Claude Code in a sandbox for this folder (or: claude-sandbox)
41
- sandbox claude -t # ... in this terminal (Ctrl+] detaches, the session keeps running)
42
- sandbox start # just the sandbox, no agent
44
+ sandbox claude -t # ... in this terminal (Ctrl+] detaches; the session keeps running)
45
+ sandbox start # the sandbox, no agent
43
46
  sandbox opencode # any supported agent by name
44
47
  sandbox web open # (Beta) the web UI in your browser, signed in
45
48
  ```
46
49
 
47
- The first start downloads what the project needs (a few minutes, once). After that, starts take seconds.
50
+ The first start downloads what the project needs (a few minutes, once). Later starts take seconds.
48
51
 
49
- > `claude-sbx`, `codex-sbx`, `gemini-sbx` and `agent-sandbox` are the old command names. They still work for now; use
50
- > `sandbox <agent>` / `claude-sandbox` and `sandbox` instead.
52
+ > The old names `claude-sbx`, `codex-sbx`, `gemini-sbx` and `agent-sandbox` still work for now. Use `sandbox <agent>`
53
+ > (or `claude-sandbox`) and `sandbox` instead.
51
54
 
52
55
  ## What you get
53
56
 
54
- | | |
55
- |---|---|
56
- | **Safe by default** | The agent sees only your project folder. Credentials are stripped before anything is copied in, your LAN is blocked, and nothing the sandbox writes can run on your PC. |
57
- | **Languages** | Node, Python, Rust, C/C++ (GCC or MSVC), .NET (incl. .NET Framework targeting), Go, Java, Ruby, PHP, Deno, Bun, PowerShell 7, with pnpm, yarn, Volta, uv, pyenv, Maven, Gradle, Composer, gh ... |
58
- | **Apps and tools** | VS Code (set up for your languages, with their extensions) and Windows Terminal, plus 60 optional apps and tools by category: DBeaver, pgAdmin, Bruno, Godot, Blender, kubectl, jq, ripgrep ... and programs of your own. Agent add-ons too: rtk and Headroom (fewer tokens), ccusage, Playwright and Context7 MCP servers, claude-mem, REA. Playwright works out of the box with Edge |
59
- | **Databases** | PostgreSQL, MySQL, MongoDB, Redis and DynamoDB Local with a web UI, started when the project uses them, or any time with `--database` / `sandbox db` |
60
- | **Agents** | Claude Code, Codex, Gemini, opencode, Qwen, Crush, Copilot, Kilo, Amp, Cline, Continue, Kimi, Aider, DeepSeek agents |
61
- | **Smart** | Detects what the project needs from its files, respects version files, installs in parallel and reuses everything |
62
- | **Several projects** | `sandbox claude` from another project joins the running sandbox: its own folder, tools, versions, databases and environment, set up on demand. Start several agents at once (`--session claude@A --session codex@B`, or the menu) and attach to any of them from any terminal |
63
- | **Picks up where you left off** | After a crash or a restart, `sandbox resume` reopens the last sessions; `sandbox restart` restarts the agents in place and they continue their conversation |
64
- | **Leaves nothing behind** | When an agent's session ends, everything it started ends with it, background servers included. The web UI's server stops when no browser uses it, and nothing of this tool keeps running on your PC once the sandbox is closed |
65
- | **GitHub, safely** | Give sandboxes a fine-grained GitHub token you made for them (`sandbox github login`, `github.shareToken`): `gh` and `git push` work inside, and the token never lands in the sandbox's files |
66
- | **Feels like home** | Your desktop look, Claude settings, MCP servers and conversation history come along; history syncs back. Logins you save (`sandbox account`) are kept encrypted for your Windows user |
57
+ | | |
58
+ | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
59
+ | **Safe by default** | The agent sees only your project folder. Credentials are stripped before anything is copied in, your LAN is blocked, and nothing the sandbox writes can run on your PC. |
60
+ | **Languages** | Node, Python, Rust, C/C++ (GCC or MSVC), .NET (with .NET Framework targeting), Go, Java, Ruby, PHP, Deno, Bun, PowerShell 7, Unreal Engine tools. Also pnpm, yarn, Volta, uv, pyenv, Maven, Gradle, Composer, gh ... |
61
+ | **Apps and tools** | VS Code (set up for your languages) and Windows Terminal, plus about 80 optional apps by category: DBeaver, pgAdmin, Bruno, Godot, Blender, Ghidra, kubectl, jq, ripgrep ... and your own programs. Agent add-ons: rtk and Headroom (fewer tokens), ccusage, Playwright and Context7 MCP servers, claude-mem, REA. Playwright works with Edge out of the box. |
62
+ | **Databases** | PostgreSQL, MySQL, MongoDB, Redis and DynamoDB Local (with a web UI). They start when the project uses them, or any time with `--database` or `sandbox db`. |
63
+ | **Agents** | Claude Code, Codex, Gemini, opencode, Qwen, Crush, Copilot, Kilo, Amp, Cline, Continue, Kimi, Aider and two DeepSeek agents. |
64
+ | **Smart setup** | Finds what the project needs from its files, follows its version files, installs in parallel and reuses everything. |
65
+ | **Several projects** | `sandbox claude` from another project joins the running sandbox, with that project's own folder, tools, versions, databases and environment. Start several agents at once (`--session claude@A --session codex@B`, or the menu) and attach to any of them from any terminal. |
66
+ | **Pick up again** | After a crash or restart, `sandbox resume` reopens the last sessions. `sandbox restart` restarts the agents in place, and they continue their conversations. |
67
+ | **Leaves nothing behind** | When an agent's session ends, everything it started ends too, background servers included. Nothing of this tool keeps running on your PC once the sandbox is closed. |
68
+ | **GitHub, safely** | Give sandboxes a fine-grained GitHub token made just for them (`sandbox github login`, `github.shareToken`). `gh` and `git push` then work inside, and the token is never written to the sandbox's files. |
69
+ | **Feels like home** | Your desktop look, Claude settings, MCP servers and conversation history come along, and history syncs back. Saved logins (`sandbox account`) are encrypted for your Windows user. |
67
70
 
68
71
  ## Built for heavy workloads
69
72
 
70
- The sandbox behaves like a well-run PC of its own size: under load it slows down, it does not fail, and it never takes
71
- your PC down with it. Nothing needs setting up.
72
-
73
- - **Sized to what your PC can hold.** The sandbox gets only the memory your PC can keep in RAM for it, with room kept
74
- for your PC itself (and more with vGPU on).
75
- - **Builds within a budget.** Agents see the processors and memory they may really use, and every session gets a
76
- matching number of build jobs and links, written to `run\budget.json` for agents to plan with.
77
- - **Graduated throttling.** As memory fills, a governor in the sandbox turns one dial in steps: build programs get
78
- lower CPU and memory priority, then a smaller share of the CPU, then compilers take turns while the waiting ones move
79
- to the paging file. Builds get slower; nothing is stopped or killed, and agents, shells and Windows are never touched.
80
- - **Your PC has a say.** A watchdog on your PC watches its memory, CPU and disks and asks the sandbox to ease off, at
81
- once and all the way when your PC is nearly out of memory.
82
- - **A last resort that only protects.** Only at the very edge of the sandbox's own memory limit, where Windows inside
83
- it would otherwise start failing, is a build refused memory so that the sandbox stays up.
84
- - **Answers after the fact.** `sandbox doctor` checks your paging file, and `sandbox logs --crash` explains a past
85
- freeze or crash: the gap, blue screens, hardware and memory events, and whether vGPU was on.
86
-
87
- Details and settings: [troubleshooting](docs/troubleshooting.md#the-sandbox-closes-under-heavy-load) and
88
- [configuration](docs/configuration.md#cpu-ram-and-gpu).
73
+ Under load the sandbox slows down instead of failing, and it never takes your PC down with it. Nothing needs setting
74
+ up.
75
+
76
+ - **Sized to fit.** The sandbox gets only the memory your PC can keep in RAM for it, with room left for your PC.
77
+ - **A build budget.** Agents see the CPUs and memory they may really use. Each session gets a matching number of build
78
+ jobs, written to `run\budget.json` for agents to plan with.
79
+ - **Slows down in steps.** As memory fills, build programs get lower priority, then less CPU, then compilers take
80
+ turns. Builds get slower, but nothing is killed, and agents, shells and Windows are never touched.
81
+ - **Your PC has a say.** A watchdog on your PC asks the sandbox to ease off when your PC runs short of memory, CPU or
82
+ disk.
83
+ - **A last resort.** Only at the very edge of the sandbox's memory limit is a build refused memory, so the sandbox
84
+ stays up.
85
+ - **Answers afterwards.** `sandbox doctor` checks your paging file. `sandbox logs --crash` explains a past freeze or
86
+ crash.
87
+
88
+ Details: [heavy load](docs/troubleshooting.md#the-sandbox-closes-under-heavy-load) and
89
+ [CPU, RAM and GPU settings](docs/configuration.md#cpu-ram-and-gpu).
89
90
 
90
91
  ## Commands
91
92
 
92
- | Command | |
93
- |---|---|
94
- | `sandbox` | the menu, a full-screen app with a left navigation: start agents, attach to sessions, pick apps, edit every setting (yours and the project's), all commands, with search |
95
- | `sandbox <agent>`, `claude-sandbox` | start an agent; `-t` for this terminal, `--headless` for no window |
96
- | `sandbox start` | the sandbox without an agent |
97
- | `sandbox attach` / `sessions` / `status` | work with a running sandbox (this folder's project first) |
98
- | `sandbox shell` / `close <id>` | open PowerShell (or cmd) in a project as a session you can attach to; end a session |
99
- | `sandbox restart` / `resume` | restart the agents in place; reopen the last sessions |
100
- | `sandbox projects` | the projects a sandbox can open without a restart: roots, `all`, exclude |
101
- | `sandbox db [start\|stop <name>]` | list, start or stop databases (`sbx-db` inside) |
102
- | `sandbox exec -- <cmd>` | run a command inside |
103
- | `sandbox config get\|set\|reset\|list` | read and change any setting from the command line (`export` / `import` to share them) |
104
- | `sandbox account` | save, switch and rename agent logins |
105
- | `sandbox github` / `vpn` | the GitHub token for sandboxes; the VPN login and status |
106
- | `sandbox web` | (Beta) the web UI: start, stop, status, open |
107
- | `sandbox stop` / `hide` / `show` | shut down, hide or show the window |
108
- | `sandbox data` / `storage` | what's stored and how big, freeing space, moving the data folder |
109
- | `sandbox setup` / `doctor` / `repair` | check this PC, see what will be installed, fix common problems |
110
- | `sandbox engine` | the engines and what each can do on this PC; `engine clean` stops HCS systems left running |
111
- | `sandbox logs [-f] [--crash]` | the sandbox log, or the report of the last crash |
112
- | `sandbox update [--rollback]` / `--version` | update (or go back one version); the installed version |
113
-
114
- All commands and options: [docs/commands.md](docs/commands.md)
93
+ | Command | |
94
+ | ---------------------------------------- | --------------------------------------------------------------------------------- |
95
+ | `sandbox` | the menu: start agents, attach to sessions, pick apps, change any setting, search |
96
+ | `sandbox <agent>`, `claude-sandbox` | start an agent; `-t` for this terminal, `--headless` for no window |
97
+ | `sandbox start` | the sandbox without an agent |
98
+ | `sandbox attach` / `sessions` / `status` | work with a running sandbox (this folder's project first) |
99
+ | `sandbox shell` / `close <id>` | open PowerShell or cmd in a project as a session; end a session |
100
+ | `sandbox restart` / `resume` | restart the agents in place; reopen the last sessions |
101
+ | `sandbox projects` | which projects a sandbox can open without a restart |
102
+ | `sandbox db [start\|stop <name>]` | list, start or stop databases (`sbx-db` inside) |
103
+ | `sandbox exec -- <cmd>` | run a command inside |
104
+ | `sandbox config get\|set\|reset\|list` | read and change settings (`export` / `import` to share them) |
105
+ | `sandbox account` | save, switch and rename agent logins |
106
+ | `sandbox github` / `vpn` | the GitHub token for sandboxes; the VPN login and status |
107
+ | `sandbox web` | (Beta) the web UI: start, stop, status, open |
108
+ | `sandbox stop` / `hide` / `show` | shut down; hide or show the window |
109
+ | `sandbox data` / `storage` | what is stored and how big; free space; move the data folder |
110
+ | `sandbox setup` / `doctor` / `repair` | check this PC, see what will be installed, fix common problems |
111
+ | `sandbox engine` | (Alpha) the engines and what each can do on this PC |
112
+ | `sandbox logs [-f] [--crash]` | the sandbox log, or the report of the last crash |
113
+ | `sandbox update [--rollback]` | update, or go back one version (`--version` shows the installed one) |
114
+
115
+ Every command and option: [docs/commands.md](docs/commands.md).
115
116
 
116
117
  ## Beta and alpha features
117
118
 
118
- These are off until you turn them on, and one setting turns each off again. Windows Sandbox stays the default and
119
- keeps every feature it has.
119
+ These are off until you turn them on, and one setting turns each off again. Windows Sandbox stays the default engine
120
+ and keeps all its features.
120
121
 
121
- | Feature | Status | |
122
- |---|---|---|
123
- | **Web UI** (`sandbox web`, `web.enabled`) | Beta | Agents, sessions with live terminals, the sandbox's status, apps, accounts and every setting in your browser, with search (Ctrl+K) and a folder picker; on this PC only (loopback, signed in with a token). `web.openOnLaunch` opens it with every sandbox. [web-ui.md](docs/web-ui.md) |
124
- | **Agent commands** (`sandbox agent-commands on`) | Beta | Typing `claude`, `codex` ... in any folder starts it in a hidden sandbox and attaches your terminal |
125
- | **Contained storage** (`sandbox storage contained on`) | Beta | Tools, logins and logs in one disk image per data set, mounted only while a sandbox runs. One admin prompt per launch. [engines](docs/design/engines.md) |
126
- | **VPN** (`sandbox vpn`, `vpn.enabled`) | Alpha | The sandbox's traffic through NordVPN, your own OpenVPN profile or a WireGuard config, with a kill switch that is checked with a real connection. The first real try fixed the install and the kill switch; a tunnel carrying traffic is not confirmed yet: read [vpn.md](docs/vpn.md) first |
127
- | **HCS engine** (`sandbox.engine: hcs`, `sandbox engine`) | Alpha | Headless agents in a Hyper-V isolated Server Core container. `sandbox engine check hcs` shows what your PC lacks; starting it is not enabled yet. Its create, start and stop steps pass on GitHub's Windows Server 2022 and 2025 runners |
122
+ | Feature | Status | What it does |
123
+ | ------------------------------------------------------ | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
124
+ | **Web UI** (`sandbox web`, `web.enabled`) | Beta | Agents, live terminals, status, apps, accounts and settings in your browser, with search (Ctrl+K). This PC only, signed in with a token; devices on your network if you allow them. [web-ui.md](docs/web-ui.md) |
125
+ | **Agent commands** (`sandbox agent-commands on`) | Beta | Typing `claude`, `codex` ... in any folder starts that agent in a hidden sandbox and attaches your terminal. |
126
+ | **Contained storage** (`sandbox storage contained on`) | Beta | Tools, logins and logs in one disk image, mounted only while a sandbox runs. One admin prompt per launch. [Details](docs/configuration.md#contained-storage-beta) |
127
+ | **VPN** (`sandbox vpn`, `vpn.enabled`) | Alpha | The sandbox's traffic through NordVPN, your own OpenVPN profile or a WireGuard config, with a kill switch. A tunnel carrying traffic is not confirmed yet: read [vpn.md](docs/vpn.md) first. |
128
+ | **HCS engine** (`sandbox.engine: hcs`) | Alpha | Headless agents in a Hyper-V isolated Server Core container. `sandbox engine check hcs` shows what your PC lacks. Starting it is not enabled yet. |
128
129
 
129
130
  ## Known gaps
130
131
 
131
- - Adding a folder to a RUNNING sandbox needs Windows 11 24H2+ with the updated Windows Sandbox (`wsb share`,
132
- untested). On older Windows, folders inside a project root open at once and anything else offers a restart.
133
- [Details, and how to get `wsb`](docs/projects.md#adding-folders-to-a-running-sandbox-wsb-share). A way for older
134
- Windows through HCS is designed and waiting for a test on a real PC ([design](docs/design/hcs-live-folders.md)).
135
- - Windows Sandbox runs one sandbox at a time per PC; every project and agent shares it.
132
+ - Adding a folder to a **running** sandbox needs Windows 11 24H2+ with the updated Windows Sandbox (`wsb share`,
133
+ untested). On older Windows, folders inside a project root open at once, and anything else offers a restart.
134
+ [Details](docs/projects.md#adding-a-project-to-a-running-sandbox).
135
+ - Windows Sandbox runs one sandbox per PC. Every project and agent shares it.
136
136
  - What is planned next: [roadmap](docs/roadmap.md).
137
137
 
138
138
  ## Documentation
139
139
 
140
- All docs, with one line each: [docs/README.md](docs/README.md). The main ones:
140
+ All docs, one line each: [docs/README.md](docs/README.md). The main ones:
141
141
 
142
- - [Install](docs/install.md): requirements, other ways to install, upgrading, rolling back
143
- - [Commands](docs/commands.md): every command and option, the menu, sessions and attaching
144
- - [Tools and databases](docs/toolchains.md): languages, package managers, databases, agents, what is tested
142
+ - [Install](docs/install.md): requirements, other ways to install, updating, uninstalling
143
+ - [Commands](docs/commands.md): every command and option, the menu, sessions
144
+ - [Tools and databases](docs/toolchains.md): languages, apps, databases, agents
145
145
  - [Configuration](docs/configuration.md): settings, project files, paths, accounts, hooks
146
- - [Several projects](docs/projects.md): project roots, adding a project to a running sandbox, what each agent can see
146
+ - [Several projects](docs/projects.md): project roots, joining a running sandbox, what each agent can see
147
147
  - [Security](docs/security.md): how your PC is protected, secrets, git access
148
148
  - [Web UI](docs/web-ui.md) (Beta) and [VPN](docs/vpn.md) (Alpha)
149
- - [Troubleshooting](docs/troubleshooting.md): common problems, freezes and crash reports
150
- - [Changelog](CHANGELOG.md) and [roadmap](docs/roadmap.md): what shipped, what is next
149
+ - [Troubleshooting](docs/troubleshooting.md): common problems, heavy load, crash reports
150
+ - [Changelog](CHANGELOG.md) and [roadmap](docs/roadmap.md)
151
151
  - [Development](docs/development.md): building, testing, releasing (code layout in [CLAUDE.md](CLAUDE.md))
@@ -48,6 +48,12 @@ export declare function bootResetPaths(agents: Readonly<Record<string, Harness>>
48
48
  agent: string;
49
49
  path: string;
50
50
  }[];
51
+ /**
52
+ * Codex's config.toml with its own command sandbox off, or null when it already says which one to use. Inside Windows
53
+ * Sandbox that inner sandbox only costs: its setup re-grants ACLs over the whole profile at every boot (minutes), and
54
+ * every command hangs until it is done. A `sandbox_mode` the user set (before the first [table]) is kept.
55
+ */
56
+ export declare function codexConfigWithoutSandbox(toml: string): string | null;
51
57
  /** A SQLite database file or one of its -wal / -shm siblings. */
52
58
  export declare const isDatabaseFile: (name: string) => boolean;
53
59
  /** Files that make a consistent copy: the databases and their -wal (the -shm is rebuilt by SQLite). */
@@ -61,6 +61,20 @@ export function localStateEntries(agents, stateDir, localRoot) {
61
61
  export function bootResetPaths(agents, stateDir) {
62
62
  return Object.entries(agents).flatMap(([agent, harness]) => (harness.bootReset ?? []).map((rel) => ({ agent, path: path.join(stateDir, agent, rel) })));
63
63
  }
64
+ /**
65
+ * Codex's config.toml with its own command sandbox off, or null when it already says which one to use. Inside Windows
66
+ * Sandbox that inner sandbox only costs: its setup re-grants ACLs over the whole profile at every boot (minutes), and
67
+ * every command hangs until it is done. A `sandbox_mode` the user set (before the first [table]) is kept.
68
+ */
69
+ export function codexConfigWithoutSandbox(toml) {
70
+ const firstTable = toml.search(/^\s*\[/m);
71
+ const topLevel = firstTable < 0 ? toml : toml.slice(0, firstTable);
72
+ if (/^\s*sandbox_mode\s*=/m.test(topLevel))
73
+ return null;
74
+ return ('# Set by the sandbox: Windows Sandbox already contains Codex, its own command sandbox would only slow it down.\n' +
75
+ 'sandbox_mode = "danger-full-access"\n' +
76
+ (toml ? '\n' + toml : ''));
77
+ }
64
78
  /** A SQLite database file or one of its -wal / -shm siblings. */
65
79
  export const isDatabaseFile = (name) => /\.(sqlite3?|db)(-wal|-shm)?$/i.test(name);
66
80
  /** Files that make a consistent copy: the databases and their -wal (the -shm is rebuilt by SQLite). */
@@ -5,6 +5,8 @@ export declare function agentLocalStates(): LocalState[];
5
5
  export declare function localStateVars(): Record<string, string>;
6
6
  /** Boot: what an agent sealed to the last sandbox (bootReset) is deleted, so it sets it up again. Links are left. */
7
7
  export declare function resetMachineBound(): void;
8
+ /** Boot: Codex runs its commands without its own sandbox (codexConfigWithoutSandbox), unless the user picked one. */
9
+ export declare function codexWithoutInnerSandbox(): void;
8
10
  /** Boot: the saved databases of every configured agent are copied to the sandbox's disk, where the agent runs them. */
9
11
  export declare function restoreLocalState(): void;
10
12
  /**
@@ -10,7 +10,7 @@ import { execOutput } from '../runtime/process.js';
10
10
  import { log, warn } from '../runtime/log.js';
11
11
  import { session, stateDir } from '../runtime/session.js';
12
12
  import { errMsg } from '../../core/util/errors.js';
13
- import { bootResetPaths, isCopyableDatabaseFile, isDatabaseFile, localStateEntries, } from './agent-files.js';
13
+ import { bootResetPaths, codexConfigWithoutSandbox, isCopyableDatabaseFile, isDatabaseFile, localStateEntries, } from './agent-files.js';
14
14
  const SQLITE_HEADER = 'SQLite format 3\0';
15
15
  /** The sandbox-disk folder that holds the working copies. */
16
16
  const localRoot = () => path.join(localDir, 'agent-state');
@@ -102,6 +102,18 @@ export function resetMachineBound() {
102
102
  }
103
103
  }
104
104
  }
105
+ /** Boot: Codex runs its commands without its own sandbox (codexConfigWithoutSandbox), unless the user picked one. */
106
+ export function codexWithoutInnerSandbox() {
107
+ if (dryRun || !session.agents?.codex)
108
+ return;
109
+ const file = path.join(stateDir, 'codex', 'config.toml');
110
+ const updated = codexConfigWithoutSandbox(exists(file) ? fs.readFileSync(file, 'utf8') : '');
111
+ if (updated === null)
112
+ return;
113
+ mkdirp(path.dirname(file));
114
+ fs.writeFileSync(file, updated, 'utf8');
115
+ log('codex: its own command sandbox is off (sandbox_mode = "danger-full-access" in config.toml).');
116
+ }
105
117
  /** Boot: the saved databases of every configured agent are copied to the sandbox's disk, where the agent runs them. */
106
118
  export function restoreLocalState() {
107
119
  if (dryRun)
@@ -6,7 +6,7 @@ import { writeGuides } from './guide.js';
6
6
  import { setupToolchains } from '../toolchains/index.js';
7
7
  import { agents } from '../agents/agent-installer.js';
8
8
  import { agentShims, sbxAgentText, shimText } from '../agents/agent-files.js';
9
- import { resetMachineBound, restoreLocalState } from '../agents/local-state.js';
9
+ import { codexWithoutInnerSandbox, resetMachineBound, restoreLocalState } from '../agents/local-state.js';
10
10
  import { installShellPath } from '../setup/shell-path.js';
11
11
  import { linkProfileDirs } from '../agents/profile-links.js';
12
12
  import { restoreClaudeMem } from '../setup/claude-mem.js';
@@ -249,6 +249,7 @@ export class Boot {
249
249
  await soft('Agent databases restore', restoreLocalState);
250
250
  // Agent add-ons: MCP servers in the sandbox's Claude Code, and the Headroom proxy before the managed settings point
251
251
  // Claude Code at it (the guide reads them back, so it comes last).
252
+ await soft('Codex without its own sandbox', codexWithoutInnerSandbox);
252
253
  let headroom = null;
253
254
  await soft('MCP servers from Apps', writeAddonMcpServers);
254
255
  await soft('Headroom proxy', async () => {
@@ -39,6 +39,11 @@ export const UNREAL_COMPONENTS = [
39
39
  const OK_EXIT_CODES = [0, 3010];
40
40
  /** Free room the offline copy needs before it is made (it grows to about 10 GB). */
41
41
  const LAYOUT_ROOM_BYTES = 15 * 1024 ** 3;
42
+ /**
43
+ * Free room on the sandbox's own disk before Visual Studio goes on it: it takes about 7 GB, and the disk (about 40 GB)
44
+ * also holds the paging file and every build, so it is installed only when about 13 GB stay free after it.
45
+ */
46
+ const INSTALL_ROOM_BYTES = 20 * 1024 ** 3;
42
47
  const ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,199}$/;
43
48
  const VS_DIR = tool('visualstudio');
44
49
  const BOOTSTRAPPER = path.join(VS_DIR, 'vs_community.exe');
@@ -174,8 +179,15 @@ export async function setupUnreal(env, config) {
174
179
  log('(dry run) would install Visual Studio Community 2022 with ' + ids.join(', ') + ' and DirectX');
175
180
  return;
176
181
  }
177
- if (!installedVs())
182
+ if (!installedVs()) {
183
+ const programFiles = process.env.ProgramFiles ?? 'C:\\Program Files';
184
+ const free = freeBytes(programFiles);
185
+ if (free < INSTALL_ROOM_BYTES)
186
+ throw new Error('not installing Visual Studio: the sandbox disk has ' +
187
+ (free / 1024 ** 3).toFixed(1) +
188
+ ' GB free and it needs 20 GB (7 GB for Visual Studio, the rest for builds and the paging file)');
178
189
  await installVisualStudio(config, ids);
190
+ }
179
191
  await installDirectX();
180
192
  const vs = installedVs();
181
193
  env.summary.push('unreal: Visual Studio Community ' +
@@ -31021,6 +31021,7 @@ var UNREAL_COMPONENTS = [
31021
31021
  ];
31022
31022
  var OK_EXIT_CODES2 = [0, 3010];
31023
31023
  var LAYOUT_ROOM_BYTES = 15 * 1024 ** 3;
31024
+ var INSTALL_ROOM_BYTES = 20 * 1024 ** 3;
31024
31025
  var ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,199}$/;
31025
31026
  var VS_DIR = tool("visualstudio");
31026
31027
  var BOOTSTRAPPER = path55.join(VS_DIR, "vs_community.exe");
@@ -31156,7 +31157,15 @@ async function setupUnreal(env, config2) {
31156
31157
  log("(dry run) would install Visual Studio Community 2022 with " + ids.join(", ") + " and DirectX");
31157
31158
  return;
31158
31159
  }
31159
- if (!installedVs()) await installVisualStudio(config2, ids);
31160
+ if (!installedVs()) {
31161
+ const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
31162
+ const free = freeBytes(programFiles);
31163
+ if (free < INSTALL_ROOM_BYTES)
31164
+ throw new Error(
31165
+ "not installing Visual Studio: the sandbox disk has " + (free / 1024 ** 3).toFixed(1) + " GB free and it needs 20 GB (7 GB for Visual Studio, the rest for builds and the paging file)"
31166
+ );
31167
+ await installVisualStudio(config2, ids);
31168
+ }
31160
31169
  await installDirectX();
31161
31170
  const vs = installedVs();
31162
31171
  env.summary.push(
@@ -30327,6 +30327,7 @@ var UNREAL_COMPONENTS = [
30327
30327
  ];
30328
30328
  var OK_EXIT_CODES2 = [0, 3010];
30329
30329
  var LAYOUT_ROOM_BYTES = 15 * 1024 ** 3;
30330
+ var INSTALL_ROOM_BYTES = 20 * 1024 ** 3;
30330
30331
  var ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,199}$/;
30331
30332
  var VS_DIR = tool("visualstudio");
30332
30333
  var BOOTSTRAPPER = path44.join(VS_DIR, "vs_community.exe");
@@ -30462,7 +30463,15 @@ async function setupUnreal(env, config2) {
30462
30463
  log("(dry run) would install Visual Studio Community 2022 with " + ids.join(", ") + " and DirectX");
30463
30464
  return;
30464
30465
  }
30465
- if (!installedVs()) await installVisualStudio(config2, ids);
30466
+ if (!installedVs()) {
30467
+ const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
30468
+ const free = freeBytes(programFiles);
30469
+ if (free < INSTALL_ROOM_BYTES)
30470
+ throw new Error(
30471
+ "not installing Visual Studio: the sandbox disk has " + (free / 1024 ** 3).toFixed(1) + " GB free and it needs 20 GB (7 GB for Visual Studio, the rest for builds and the paging file)"
30472
+ );
30473
+ await installVisualStudio(config2, ids);
30474
+ }
30466
30475
  await installDirectX();
30467
30476
  const vs = installedVs();
30468
30477
  env.summary.push(
@@ -33003,6 +33012,12 @@ function bootResetPaths(agents2, stateDir2) {
33003
33012
  ([agent, harness]) => (harness.bootReset ?? []).map((rel) => ({ agent, path: path53.join(stateDir2, agent, rel) }))
33004
33013
  );
33005
33014
  }
33015
+ function codexConfigWithoutSandbox(toml) {
33016
+ const firstTable = toml.search(/^\s*\[/m);
33017
+ const topLevel = firstTable < 0 ? toml : toml.slice(0, firstTable);
33018
+ if (/^\s*sandbox_mode\s*=/m.test(topLevel)) return null;
33019
+ return '# Set by the sandbox: Windows Sandbox already contains Codex, its own command sandbox would only slow it down.\nsandbox_mode = "danger-full-access"\n' + (toml ? "\n" + toml : "");
33020
+ }
33006
33021
  var isDatabaseFile = (name) => /\.(sqlite3?|db)(-wal|-shm)?$/i.test(name);
33007
33022
  var isCopyableDatabaseFile = (name) => isDatabaseFile(name) && !/-shm$/i.test(name);
33008
33023
 
@@ -33065,6 +33080,15 @@ function resetMachineBound() {
33065
33080
  }
33066
33081
  }
33067
33082
  }
33083
+ function codexWithoutInnerSandbox() {
33084
+ if (dryRun || !session.agents?.codex) return;
33085
+ const file3 = path54.join(stateDir, "codex", "config.toml");
33086
+ const updated = codexConfigWithoutSandbox(exists(file3) ? fs43.readFileSync(file3, "utf8") : "");
33087
+ if (updated === null) return;
33088
+ mkdirp(path54.dirname(file3));
33089
+ fs43.writeFileSync(file3, updated, "utf8");
33090
+ log('codex: its own command sandbox is off (sandbox_mode = "danger-full-access" in config.toml).');
33091
+ }
33068
33092
  function restoreLocalState() {
33069
33093
  if (dryRun) return;
33070
33094
  for (const s of agentLocalStates()) {
@@ -36177,6 +36201,7 @@ var Boot = class {
36177
36201
  await soft("claude-mem restore", restoreClaudeMem);
36178
36202
  await soft("Agent files of the last sandbox", resetMachineBound);
36179
36203
  await soft("Agent databases restore", restoreLocalState);
36204
+ await soft("Codex without its own sandbox", codexWithoutInnerSandbox);
36180
36205
  let headroom = null;
36181
36206
  await soft("MCP servers from Apps", writeAddonMcpServers);
36182
36207
  await soft("Headroom proxy", async () => {
@@ -5,7 +5,7 @@ import path from 'node:path';
5
5
  import { DEFAULTS, mergeConfig, validateConfig } from '../core/config/index.js';
6
6
  import { isWin } from '../core/util/index.js';
7
7
  import { SYSTEM } from '../shared/system.js';
8
- import { agentCommand, agentShims, bootResetPaths, isCopyableDatabaseFile, isDatabaseFile, localStateEntries, shimText, } from '../guest/agents/agent-files.js';
8
+ import { agentCommand, agentShims, bootResetPaths, codexConfigWithoutSandbox, isCopyableDatabaseFile, isDatabaseFile, localStateEntries, shimText, } from '../guest/agents/agent-files.js';
9
9
  import { appendMissing, expandVars, isPinnedNodeDir, parseRegPath, pathKey, planPath, rebuildPath, splitPath, } from '../guest/setup/path-plan.js';
10
10
  import { withReloadEnvironment } from '../host/tools/index.js';
11
11
  import { HarnessSchema } from '../core/schema/index.js';
@@ -58,6 +58,17 @@ export const agentPathsSuite = {
58
58
  ], "codex's DPAPI-sealed sandbox users and setup marker are removed at boot (CryptUnprotectData otherwise)");
59
59
  t.check(HarnessSchema.safeParse({ ...DEFAULTS.harnesses.codex, bootReset: ['..\\login'] }).success === false &&
60
60
  HarnessSchema.safeParse({ ...DEFAULTS.harnesses.codex, bootReset: ['C:\\Windows'] }).success === false, 'bootReset takes only plain paths below the agent state folder');
61
+ t.section('codex without its own command sandbox');
62
+ const userToml = '[tui]\nscreen_reader_detection_done = true\n\n[windows]\nsandbox = "elevated"\n';
63
+ const off = codexConfigWithoutSandbox(userToml) ?? '';
64
+ t.check(off.split('\n').find((l) => !l.startsWith('#')) === 'sandbox_mode = "danger-full-access"' &&
65
+ off.endsWith(userToml), 'sandbox_mode goes above the first table, the rest of the file is kept');
66
+ t.check(codexConfigWithoutSandbox('') === off.slice(0, off.indexOf('\n\n') + 1), 'a missing config.toml gets just the setting');
67
+ t.equal([
68
+ codexConfigWithoutSandbox(off),
69
+ codexConfigWithoutSandbox('model = "o3"\nsandbox_mode = "workspace-write"\n[windows]\n'),
70
+ ], [null, null], 'a sandbox_mode already set (by the sandbox or by the user) is left alone');
71
+ t.check(codexConfigWithoutSandbox('[profiles.x]\nsandbox_mode = "read-only"\n') !== null, 'a sandbox_mode inside a table does not count as the top-level one');
61
72
  t.section('PATH planner');
62
73
  const present = new Set(['c:\\a', 'c:\\b', 'c:\\c\\d', 'c:\\nvm\\v24.1.0']);
63
74
  const exists = (f) => present.has(pathKey(f));
@@ -8,9 +8,9 @@ using System.Runtime.InteropServices;
8
8
  [assembly: AssemblyCompany("windows-development-sandbox (open source)")]
9
9
  [assembly: AssemblyProduct("Windows Development Sandbox")]
10
10
  [assembly: AssemblyCopyright("MIT License, windows-development-sandbox contributors")]
11
- [assembly: AssemblyVersion("1.17.0.0")]
12
- [assembly: AssemblyFileVersion("1.17.0.0")]
13
- [assembly: AssemblyInformationalVersion("1.17.0")]
11
+ [assembly: AssemblyVersion("1.17.3.0")]
12
+ [assembly: AssemblyFileVersion("1.17.3.0")]
13
+ [assembly: AssemblyInformationalVersion("1.17.3")]
14
14
  [assembly: ComVisible(false)]
15
15
  // computecore.dll and computestorage.dll are not KnownDLLs: load them from System32 only, never from the exe's folder.
16
16
  [assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
@@ -8,7 +8,7 @@ using System.Runtime.InteropServices;
8
8
  [assembly: AssemblyCompany("windows-development-sandbox (open source)")]
9
9
  [assembly: AssemblyProduct("Windows Development Sandbox")]
10
10
  [assembly: AssemblyCopyright("MIT License, windows-development-sandbox contributors")]
11
- [assembly: AssemblyVersion("1.17.0.0")]
12
- [assembly: AssemblyFileVersion("1.17.0.0")]
13
- [assembly: AssemblyInformationalVersion("1.17.0")]
11
+ [assembly: AssemblyVersion("1.17.3.0")]
12
+ [assembly: AssemblyFileVersion("1.17.3.0")]
13
+ [assembly: AssemblyInformationalVersion("1.17.3")]
14
14
  [assembly: ComVisible(false)]
@@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
9
9
  [assembly: AssemblyCompany("windows-development-sandbox (open source)")]
10
10
  [assembly: AssemblyProduct("Windows Development Sandbox")]
11
11
  [assembly: AssemblyCopyright("MIT License, windows-development-sandbox contributors")]
12
- [assembly: AssemblyVersion("1.17.0.0")]
13
- [assembly: AssemblyFileVersion("1.17.0.0")]
14
- [assembly: AssemblyInformationalVersion("1.17.0")]
12
+ [assembly: AssemblyVersion("1.17.3.0")]
13
+ [assembly: AssemblyFileVersion("1.17.3.0")]
14
+ [assembly: AssemblyInformationalVersion("1.17.3")]
15
15
  [assembly: ComVisible(false)]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "windows-development-sandbox",
3
- "version": "1.17.0",
3
+ "version": "1.17.3",
4
4
  "description": "A disposable Windows Sandbox for development, with or without an AI agent (Claude Code, Codex, Gemini, opencode, ...): the folder you run it from is the workspace, toolchains and databases for your project install themselves, and nothing else on your PC is reachable.",
5
5
  "type": "module",
6
6
  "license": "MIT",