bx-mac 0.6.0 → 0.8.1
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 +100 -6
- package/dist/bx-native +0 -0
- package/dist/bx.js +1325 -180
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -37,6 +37,7 @@ bx ~/work/my-project ~/work/shared-lib
|
|
|
37
37
|
- **No process isolation** — this is file-level sandboxing, not a container
|
|
38
38
|
- **No protection against root/sudo** — the sandbox applies to the user-level process
|
|
39
39
|
- **macOS only** — relies on `sandbox-exec` (Apple-specific)
|
|
40
|
+
- **Not dynamic** — the sandbox profile is a snapshot of `$HOME` at launch time; directories or files created later are **not** automatically blocked
|
|
40
41
|
- **Not a vault** — `sandbox-exec` is undocumented; treat this as a safety net, not a guarantee
|
|
41
42
|
|
|
42
43
|
## 📥 Install
|
|
@@ -55,20 +56,30 @@ pnpm install && pnpm build
|
|
|
55
56
|
pnpm link -g
|
|
56
57
|
```
|
|
57
58
|
|
|
58
|
-
**Requirements:** macOS (tested on
|
|
59
|
+
**Requirements:** macOS (only tested on Tahoe 26.4, feedback welcome), Node.js >= 22
|
|
59
60
|
|
|
60
61
|
## 🚀 Modes
|
|
61
62
|
|
|
62
63
|
| Command | What it launches |
|
|
63
|
-
|
|
64
|
+
| --- | --- |
|
|
64
65
|
| `bx [workdir...]` | 🖥️ VSCode (default) |
|
|
65
66
|
| `bx code [workdir...]` | 🖥️ VSCode (explicit) |
|
|
67
|
+
| `bx xcode [workdir...] [-- project-or-workspace]` | 🛠️ Xcode |
|
|
66
68
|
| `bx term [workdir...]` | 💻 Sandboxed login shell (`$SHELL -l`) |
|
|
67
69
|
| `bx claude [workdir...]` | 🤖 Claude Code CLI |
|
|
68
70
|
| `bx exec [workdir...] -- cmd` | ⚡ Any command you want |
|
|
71
|
+
| `bx <app> [workdir...] [-- app-args...]` | 🔌 Any app from `~/.bxconfig.toml` |
|
|
69
72
|
|
|
70
73
|
If no directory is given, the current directory is used. All modes accept multiple directories.
|
|
71
74
|
|
|
75
|
+
For app modes, values before `--` define the sandbox scope (`workdir...`). Values after `--` are passed to the app as launch arguments.
|
|
76
|
+
|
|
77
|
+
For `xcode`, this distinction is important: the sandbox workdir is **not** passed as an Xcode open argument. Use `--` if you want to open a specific `.xcworkspace` or `.xcodeproj`.
|
|
78
|
+
|
|
79
|
+
This behavior is configurable per app via `passWorkdirs` in `~/.bxconfig.toml` (default: `true`, built-in `xcode` default: `false`).
|
|
80
|
+
|
|
81
|
+
GUI app modes are activated in the foreground on launch (best effort), so the opened app should become the frontmost app.
|
|
82
|
+
|
|
72
83
|
### Examples
|
|
73
84
|
|
|
74
85
|
```bash
|
|
@@ -84,9 +95,22 @@ bx term ~/work/my-project
|
|
|
84
95
|
# 🤖 Let Claude Code work on a project — nothing else visible
|
|
85
96
|
bx claude ~/work/my-project
|
|
86
97
|
|
|
98
|
+
# 🛠️ Xcode (built-in) — sandbox only, open picker/restore state
|
|
99
|
+
bx xcode ~/work/my-ios-app
|
|
100
|
+
|
|
101
|
+
# 🛠️ Xcode with explicit project/workspace to open
|
|
102
|
+
bx xcode ~/work/my-ios-app -- MyApp.xcworkspace
|
|
103
|
+
|
|
104
|
+
# 🔌 Custom apps from ~/.bxconfig.toml
|
|
105
|
+
bx cursor ~/work/my-project
|
|
106
|
+
bx zed ~/work/my-project
|
|
107
|
+
|
|
87
108
|
# ⚡ Run a script in a sandbox
|
|
88
109
|
bx exec ~/work/my-project -- python train.py
|
|
89
110
|
|
|
111
|
+
# 🔍 Preview what will be protected (no launch)
|
|
112
|
+
bx --dry ~/work/my-project
|
|
113
|
+
|
|
90
114
|
# 🔍 See the generated sandbox profile
|
|
91
115
|
bx --verbose ~/work/my-project
|
|
92
116
|
```
|
|
@@ -94,13 +118,61 @@ bx --verbose ~/work/my-project
|
|
|
94
118
|
## ⚙️ Options
|
|
95
119
|
|
|
96
120
|
| Option | Description |
|
|
97
|
-
|
|
98
|
-
| `--
|
|
121
|
+
| --- | --- |
|
|
122
|
+
| `--dry` | Show a tree of all protected, read-only, and accessible paths — don't launch anything |
|
|
123
|
+
| `--verbose` | Print the generated sandbox profile plus launch details (binary, arguments, cwd, focus command) |
|
|
99
124
|
| `--profile-sandbox` | Use an isolated VSCode profile (separate extensions/settings, `code` mode only) |
|
|
100
125
|
|
|
126
|
+
On normal runs, bx also prints a short policy summary (number of workdirs, blocked directories, hidden paths, and read-only directories).
|
|
127
|
+
|
|
101
128
|
## 📝 Configuration
|
|
102
129
|
|
|
103
|
-
|
|
130
|
+
### `~/.bxconfig.toml`
|
|
131
|
+
|
|
132
|
+
App definitions in TOML format. Each `[apps.<name>]` section becomes a CLI mode — use it as `bx <name> [workdir...]`. Built-in apps (`code`, `xcode`) are always available and can be overridden.
|
|
133
|
+
|
|
134
|
+
```toml
|
|
135
|
+
# Add Cursor (auto-discovered via macOS Spotlight)
|
|
136
|
+
[apps.cursor]
|
|
137
|
+
bundle = "com.todesktop.230313mzl4w4u92"
|
|
138
|
+
binary = "Contents/MacOS/Cursor"
|
|
139
|
+
args = ["--no-sandbox"]
|
|
140
|
+
|
|
141
|
+
# Add Zed (explicit path, no discovery)
|
|
142
|
+
[apps.zed]
|
|
143
|
+
path = "/Applications/Zed.app/Contents/MacOS/zed"
|
|
144
|
+
|
|
145
|
+
# Override built-in VSCode path
|
|
146
|
+
[apps.code]
|
|
147
|
+
path = "/usr/local/bin/code"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
| Field | Description |
|
|
151
|
+
| --- | --- |
|
|
152
|
+
| `bundle` | macOS bundle identifier — used with `mdfind` to find the app automatically |
|
|
153
|
+
| `binary` | Relative path to the executable inside the `.app` bundle |
|
|
154
|
+
| `path` | Absolute path to the executable **or** `.app` bundle (highest priority, skips discovery) |
|
|
155
|
+
| `fallback` | Absolute fallback path if `mdfind` discovery fails |
|
|
156
|
+
| `args` | Extra arguments always passed to the app |
|
|
157
|
+
| `passWorkdirs` | Whether `workdir...` is forwarded as app launch args (`true`/`false`) |
|
|
158
|
+
| `workdirs` | Default working directories when none are given on the CLI (supports `~/` paths) |
|
|
159
|
+
|
|
160
|
+
**Resolution order:** `path` → `mdfind` by `bundle` + `binary` → `fallback`
|
|
161
|
+
|
|
162
|
+
`passWorkdirs` controls launch argument behavior and is independent of sandbox scope. Even with `passWorkdirs = false`, the provided `workdir...` still defines what the sandbox can access.
|
|
163
|
+
|
|
164
|
+
**Preconfigured workdirs** let you define your usual environment per app:
|
|
165
|
+
|
|
166
|
+
```toml
|
|
167
|
+
[apps.code]
|
|
168
|
+
workdirs = ["~/work/my-project", "~/work/shared-lib"]
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Running `bx code` (without arguments) will then open VSCode with both directories sandboxed. CLI arguments always override configured workdirs.
|
|
172
|
+
|
|
173
|
+
When overriding a built-in app, only the specified fields are replaced — unset fields keep their defaults. See [`bxconfig.example.toml`](bxconfig.example.toml) for a complete reference.
|
|
174
|
+
|
|
175
|
+
> **💡 Finding a bundle ID:** Run `osascript -e 'id of app "AppName"'` to get the bundle ID of any installed app. Using `bundle` instead of `path` is recommended — it survives app updates, relocations, and name changes.
|
|
104
176
|
|
|
105
177
|
### `~/.bxignore`
|
|
106
178
|
|
|
@@ -131,7 +203,7 @@ Deny rules are applied **in addition** to the built-in protected list:
|
|
|
131
203
|
Block paths within the working directory. Uses [`.gitignore`-style pattern matching](https://git-scm.com/docs/gitignore#_pattern_format):
|
|
132
204
|
|
|
133
205
|
| Pattern | Matches | Why |
|
|
134
|
-
|
|
206
|
+
| --- | --- | --- |
|
|
135
207
|
| `.env` | `.env` at any depth | No `/` → recursive |
|
|
136
208
|
| `.env.*` | `.env.local`, `sub/.env.production` | No `/` → recursive |
|
|
137
209
|
| `*.pem` | `key.pem`, `sub/deep/cert.pem` | No `/` → recursive |
|
|
@@ -192,6 +264,27 @@ bx detects and prevents problematic scenarios:
|
|
|
192
264
|
- **🔄 Sandbox nesting:** If `CODEBOX_SANDBOX=1` is set (auto-propagated), bx refuses to start — nested sandboxes cause silent failures.
|
|
193
265
|
- **🔍 Unknown sandbox:** On startup, bx probes `~/Documents`, `~/Desktop`, `~/Downloads`. If any return `EPERM`, another sandbox is active — bx aborts.
|
|
194
266
|
- **⚠️ VSCode terminal:** If `VSCODE_PID` is set, bx warns that it will launch a *new* instance, not sandbox the current one.
|
|
267
|
+
- **🧩 App already sandboxed:** For GUI app modes, bx inspects app entitlements (best effort) and warns if Apple App Sandbox is enabled, since nested sandboxing can cause startup/access issues.
|
|
268
|
+
- **🔁 App already running:** If the target app is already running, bx warns that the new workspace would open in the existing (unsandboxed) instance and asks for confirmation. This is important because Electron apps like VSCode, Cursor, etc. always reuse the running process — `sandbox-exec` has no effect on the already-running instance.
|
|
269
|
+
|
|
270
|
+
### Single-instance apps
|
|
271
|
+
|
|
272
|
+
Most GUI editors (VSCode, Cursor, Xcode, Zed) are **single-instance apps** — launching them a second time just sends the path to the running process. This means you **cannot run two separately sandboxed instances** of the same app.
|
|
273
|
+
|
|
274
|
+
**To work on multiple projects**, specify all directories at launch:
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
bx code ~/work/project-a ~/work/project-b
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Or preconfigure them in `~/.bxconfig.toml`:
|
|
281
|
+
|
|
282
|
+
```toml
|
|
283
|
+
[apps.code]
|
|
284
|
+
workdirs = ["~/work/project-a", "~/work/project-b"]
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
For VSCode specifically, `--profile-sandbox` forces a separate Electron process via an isolated `--user-data-dir`, but this means separate extensions and settings.
|
|
195
288
|
|
|
196
289
|
## 💡 Tips
|
|
197
290
|
|
|
@@ -206,6 +299,7 @@ cat ./src/index.ts # ✅ Works!
|
|
|
206
299
|
|
|
207
300
|
## ⚠️ Known limitations
|
|
208
301
|
|
|
302
|
+
- **⚠️ Sandbox profile is static:** The sandbox rules are generated **once at launch** by scanning the current state of `$HOME`. Directories or files created **after** the sandbox starts are **not protected** — for example, if a tool creates `~/new-project/` while the sandbox is running, that directory will be fully accessible. Similarly, project-level `.bxignore` patterns only match files that exist at launch time; files matching a blocked pattern (e.g. `.env`) that are created later will **not** be denied. Re-run `bx` to pick up changes.
|
|
209
303
|
- **File watcher warnings:** VSCode may log `EPERM` for `fs.watch()` on some paths — cosmetic only
|
|
210
304
|
- **SQLite warnings:** `state.vscdb` errors may appear in logs — extensions still work
|
|
211
305
|
- **`sandbox-exec` is undocumented:** Apple could change behavior with OS updates
|
package/dist/bx-native
CHANGED
|
Binary file
|