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 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 Sequoia 15), Node.js >= 22
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
- | `--verbose` | Print the generated sandbox profile to stderr |
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
- bx uses two optional config files — one entry per line, `#` for comments. Project `.bxignore` files are discovered recursively.
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