bx-mac 0.3.0 → 0.4.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 +31 -11
- package/dist/bx.js +20 -2
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -14,6 +14,12 @@ bx ~/work/my-project
|
|
|
14
14
|
|
|
15
15
|
That's it. 🎉 VSCode opens with full access to `~/work/my-project` and nothing else.
|
|
16
16
|
|
|
17
|
+
Need multiple directories? No problem:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
bx ~/work/my-project ~/work/shared-lib
|
|
21
|
+
```
|
|
22
|
+
|
|
17
23
|
## ✅ What it does
|
|
18
24
|
|
|
19
25
|
- 🔒 Blocks `~/Documents`, `~/Desktop`, `~/Downloads`, and all other personal folders
|
|
@@ -21,8 +27,9 @@ That's it. 🎉 VSCode opens with full access to `~/work/my-project` and nothing
|
|
|
21
27
|
- 🛡️ Protects sensitive dotdirs like `~/.ssh`, `~/.gnupg`, `~/.docker`, `~/.cargo`
|
|
22
28
|
- ⚙️ Keeps VSCode, extensions, shell, Node.js, and other tooling fully functional
|
|
23
29
|
- 🔍 Generates sandbox rules dynamically based on your actual `$HOME` contents
|
|
24
|
-
- 📝 Supports `.bxignore` to hide secrets like `.env` files within a project
|
|
30
|
+
- 📝 Supports `.bxignore` files (searched recursively) to hide secrets like `.env` files within a project
|
|
25
31
|
- 📂 Supports `~/.bxallow` to grant access to shared utility directories
|
|
32
|
+
- 🗂️ Supports multiple working directories in a single sandbox
|
|
26
33
|
|
|
27
34
|
## 🚫 What it doesn't do
|
|
28
35
|
|
|
@@ -54,13 +61,13 @@ pnpm link -g
|
|
|
54
61
|
|
|
55
62
|
| Command | What it launches |
|
|
56
63
|
|---|---|
|
|
57
|
-
| `bx [workdir]` | 🖥️ VSCode (default) |
|
|
58
|
-
| `bx code [workdir]` | 🖥️ VSCode (explicit) |
|
|
59
|
-
| `bx term [workdir]` | 💻 Sandboxed login shell (`$SHELL -l`) |
|
|
60
|
-
| `bx claude [workdir]` | 🤖 Claude Code CLI |
|
|
61
|
-
| `bx exec [workdir] -- cmd` | ⚡ Any command you want |
|
|
64
|
+
| `bx [workdir...]` | 🖥️ VSCode (default) |
|
|
65
|
+
| `bx code [workdir...]` | 🖥️ VSCode (explicit) |
|
|
66
|
+
| `bx term [workdir...]` | 💻 Sandboxed login shell (`$SHELL -l`) |
|
|
67
|
+
| `bx claude [workdir...]` | 🤖 Claude Code CLI |
|
|
68
|
+
| `bx exec [workdir...] -- cmd` | ⚡ Any command you want |
|
|
62
69
|
|
|
63
|
-
If no directory is given, the current directory is used.
|
|
70
|
+
If no directory is given, the current directory is used. All modes accept multiple directories.
|
|
64
71
|
|
|
65
72
|
### Examples
|
|
66
73
|
|
|
@@ -68,6 +75,9 @@ If no directory is given, the current directory is used.
|
|
|
68
75
|
# 🖥️ VSCode with sandbox protection
|
|
69
76
|
bx ~/work/my-project
|
|
70
77
|
|
|
78
|
+
# 📂 Multiple working directories
|
|
79
|
+
bx ~/work/my-project ~/work/shared-lib
|
|
80
|
+
|
|
71
81
|
# 💻 Work on a project in a sandboxed terminal
|
|
72
82
|
bx term ~/work/my-project
|
|
73
83
|
|
|
@@ -90,7 +100,7 @@ bx --verbose ~/work/my-project
|
|
|
90
100
|
|
|
91
101
|
## 📝 Configuration
|
|
92
102
|
|
|
93
|
-
bx uses three optional config files — one entry per line, `#` for comments.
|
|
103
|
+
bx uses three optional config files — one entry per line, `#` for comments. Project `.bxignore` files are discovered recursively.
|
|
94
104
|
|
|
95
105
|
### `~/.bxallow`
|
|
96
106
|
|
|
@@ -119,7 +129,7 @@ These are blocked **in addition** to the built-in protected list:
|
|
|
119
129
|
|
|
120
130
|
### `<project>/.bxignore`
|
|
121
131
|
|
|
122
|
-
Block paths within the working directory. Supports glob patterns.
|
|
132
|
+
Block paths within the working directory. Supports glob patterns. bx searches for `.bxignore` files **recursively** through the entire project tree (skipping `.`-prefixed dirs and `node_modules`), so you can place them in subdirectories to hide secrets close to where they live.
|
|
123
133
|
|
|
124
134
|
```gitignore
|
|
125
135
|
.env
|
|
@@ -129,15 +139,25 @@ secrets/
|
|
|
129
139
|
**/*.key
|
|
130
140
|
```
|
|
131
141
|
|
|
142
|
+
For example, a monorepo might have:
|
|
143
|
+
|
|
144
|
+
```text
|
|
145
|
+
my-project/.bxignore # top-level rules
|
|
146
|
+
my-project/services/api/.bxignore # API-specific secrets
|
|
147
|
+
my-project/deploy/.bxignore # deployment credentials
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Each `.bxignore` resolves its patterns relative to its own directory.
|
|
151
|
+
|
|
132
152
|
## 🔧 How it works
|
|
133
153
|
|
|
134
154
|
bx generates a macOS sandbox profile at launch time:
|
|
135
155
|
|
|
136
156
|
1. **Scan** `$HOME` for non-hidden directories
|
|
137
157
|
2. **Block** each one individually with `(deny file* (subpath ...))`
|
|
138
|
-
3. **Skip**
|
|
158
|
+
3. **Skip** all working directories, `~/Library`, dotfiles, and `~/.bxallow` paths
|
|
139
159
|
4. **Descend** into parent directories of allowed paths to block only siblings (because SBPL deny rules always override allow rules)
|
|
140
|
-
5. **Append** deny rules for protected dotdirs and `.bxignore`
|
|
160
|
+
5. **Append** deny rules for protected dotdirs, `~/.bxignore`, and `.bxignore` files found recursively in each working directory
|
|
141
161
|
6. **Write** the profile to `/tmp`, launch the app via `sandbox-exec`, clean up on exit
|
|
142
162
|
|
|
143
163
|
### Why not a simple deny-all + allow?
|
package/dist/bx.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const __VERSION__ = "0.
|
|
2
|
+
const __VERSION__ = "0.4.0";
|
|
3
3
|
import { accessSync, constants, cpSync, existsSync, globSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { dirname, join, resolve } from "node:path";
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
@@ -27,6 +27,23 @@ function checkVSCodeTerminal() {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
|
+
* Abort if any workdir IS $HOME or is not inside $HOME.
|
|
31
|
+
*/
|
|
32
|
+
function checkWorkDirs(workDirs, home) {
|
|
33
|
+
for (const dir of workDirs) {
|
|
34
|
+
if (dir === home) {
|
|
35
|
+
console.error("sandbox: ERROR — working directory cannot be $HOME itself.");
|
|
36
|
+
console.error("sandbox: Sandboxing your entire home directory is not supported. Aborting.");
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
if (!dir.startsWith(home + "/")) {
|
|
40
|
+
console.error(`sandbox: ERROR — working directory is outside $HOME: ${dir}`);
|
|
41
|
+
console.error("sandbox: Only directories inside $HOME are supported. Aborting.");
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
30
47
|
* Detect if we're inside an unknown sandbox by probing well-known
|
|
31
48
|
* directories that exist on every Mac but would be blocked.
|
|
32
49
|
*/
|
|
@@ -232,7 +249,7 @@ function buildCommand(mode, workDirs, home, profileSandbox, execCmd) {
|
|
|
232
249
|
};
|
|
233
250
|
case "claude": return {
|
|
234
251
|
bin: "claude",
|
|
235
|
-
args: [
|
|
252
|
+
args: []
|
|
236
253
|
};
|
|
237
254
|
case "exec": return {
|
|
238
255
|
bin: execCmd[0],
|
|
@@ -278,6 +295,7 @@ checkExternalSandbox();
|
|
|
278
295
|
const { mode, workArgs, verbose, profileSandbox, execCmd } = parseArgs();
|
|
279
296
|
const HOME = process.env.HOME;
|
|
280
297
|
const WORK_DIRS = workArgs.map((a) => resolve(a));
|
|
298
|
+
checkWorkDirs(WORK_DIRS, HOME);
|
|
281
299
|
if (mode === "code" && profileSandbox) setupVSCodeProfile(HOME);
|
|
282
300
|
const blockedDirs = collectBlockedDirs(HOME, HOME, __dirname, parseAllowedDirs(HOME, WORK_DIRS));
|
|
283
301
|
const ignoredPaths = collectIgnoredPaths(HOME, WORK_DIRS);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bx-mac",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Launch apps in a macOS sandbox — only the project directory is accessible",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
],
|
|
12
12
|
"scripts": {
|
|
13
13
|
"build": "rolldown -c",
|
|
14
|
+
"test": "vitest run",
|
|
14
15
|
"prepublishOnly": "npm run build",
|
|
15
16
|
"post:release": "./scripts/release.sh"
|
|
16
17
|
},
|
|
@@ -25,7 +26,8 @@
|
|
|
25
26
|
"license": "MIT",
|
|
26
27
|
"devDependencies": {
|
|
27
28
|
"@types/node": "^25.5.0",
|
|
28
|
-
"rolldown": "^1.0.0-rc.12"
|
|
29
|
+
"rolldown": "^1.0.0-rc.12",
|
|
30
|
+
"vitest": "^4.1.2"
|
|
29
31
|
},
|
|
30
32
|
"engines": {
|
|
31
33
|
"node": ">=22"
|