sandboxbox 2.0.4 → 2.0.6

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/package.json CHANGED
@@ -1,38 +1,38 @@
1
- {
2
- "name": "sandboxbox",
3
- "version": "2.0.4",
4
- "description": "Portable container runner with Podman - Claude Code & Playwright support. Works on Windows, macOS, and Linux.",
5
- "type": "module",
6
- "main": "cli.js",
7
- "bin": {
8
- "sandboxbox": "./cli.js"
9
- },
10
- "scripts": {
11
- "start": "node cli.js",
12
- "postinstall": "node scripts/download-podman.js"
13
- },
14
- "keywords": [
15
- "containers",
16
- "podman",
17
- "playwright",
18
- "claude-code",
19
- "sandbox",
20
- "isolation",
21
- "cross-platform",
22
- "windows",
23
- "macos",
24
- "linux",
25
- "portable"
26
- ],
27
- "author": "",
28
- "license": "MIT",
29
- "dependencies": {},
30
- "repository": {
31
- "type": "git",
32
- "url": "https://github.com/AnEntrypoint/sandboxbox.git"
33
- },
34
- "homepage": "https://github.com/AnEntrypoint/sandboxbox#readme",
35
- "bugs": {
36
- "url": "https://github.com/AnEntrypoint/sandboxbox/issues"
37
- }
38
- }
1
+ {
2
+ "name": "sandboxbox",
3
+ "version": "2.0.6",
4
+ "description": "Portable container runner with Podman - Claude Code & Playwright support. Works on Windows, macOS, and Linux.",
5
+ "type": "module",
6
+ "main": "cli.js",
7
+ "bin": {
8
+ "sandboxbox": "./cli.js"
9
+ },
10
+ "scripts": {
11
+ "start": "node cli.js",
12
+ "postinstall": "node scripts/download-podman.js"
13
+ },
14
+ "keywords": [
15
+ "containers",
16
+ "podman",
17
+ "playwright",
18
+ "claude-code",
19
+ "sandbox",
20
+ "isolation",
21
+ "cross-platform",
22
+ "windows",
23
+ "macos",
24
+ "linux",
25
+ "portable"
26
+ ],
27
+ "author": "",
28
+ "license": "MIT",
29
+ "dependencies": {},
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/AnEntrypoint/sandboxbox.git"
33
+ },
34
+ "homepage": "https://github.com/AnEntrypoint/sandboxbox#readme",
35
+ "bugs": {
36
+ "url": "https://github.com/AnEntrypoint/sandboxbox/issues"
37
+ }
38
+ }
@@ -1,148 +1,237 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Auto-download Podman portable binaries
5
- * Similar to how sqlite/playwright auto-downloads platform-specific binaries
6
- */
7
-
8
- import { createWriteStream, existsSync, mkdirSync, chmodSync, unlinkSync } from 'fs';
9
- import { get as httpsGet } from 'https';
10
- import { get as httpGet } from 'http';
11
- import { join, dirname } from 'path';
12
- import { fileURLToPath } from 'url';
13
- import { execSync } from 'child_process';
14
-
15
- const __filename = fileURLToPath(import.meta.url);
16
- const __dirname = dirname(__filename);
17
- const binDir = join(__dirname, '..', 'bin');
18
-
19
- // Podman remote client versions
20
- const PODMAN_VERSION = '4.9.3';
21
-
22
- // Get architecture
23
- const ARCH = process.arch === 'arm64' ? 'arm64' : 'amd64';
24
-
25
- const DOWNLOADS = {
26
- win32: {
27
- url: `https://github.com/containers/podman/releases/download/v${PODMAN_VERSION}/podman-remote-release-windows_amd64.zip`,
28
- binary: 'podman.exe',
29
- extract: 'unzip'
30
- },
31
- darwin: {
32
- url: `https://github.com/containers/podman/releases/download/v${PODMAN_VERSION}/podman-remote-release-darwin_${ARCH}.tar.gz`,
33
- binary: 'podman',
34
- extract: 'tar'
35
- },
36
- linux: {
37
- url: `https://github.com/containers/podman/releases/download/v${PODMAN_VERSION}/podman-remote-static-linux_${ARCH}.tar.gz`,
38
- binary: `podman-remote-static-linux_${ARCH}`,
39
- extract: 'tar'
40
- }
41
- };
42
-
43
- function download(url, dest) {
44
- return new Promise((resolve, reject) => {
45
- const get = url.startsWith('https') ? httpsGet : httpGet;
46
-
47
- get(url, (response) => {
48
- if (response.statusCode === 302 || response.statusCode === 301) {
49
- return download(response.headers.location, dest).then(resolve).catch(reject);
50
- }
51
-
52
- if (response.statusCode !== 200) {
53
- reject(new Error(`Download failed: ${response.statusCode}`));
54
- return;
55
- }
56
-
57
- const file = createWriteStream(dest);
58
- response.pipe(file);
59
-
60
- file.on('finish', () => {
61
- file.close();
62
- resolve();
63
- });
64
-
65
- file.on('error', reject);
66
- }).on('error', reject);
67
- });
68
- }
69
-
70
- async function main() {
71
- const platform = process.platform;
72
-
73
- console.log(`\nšŸ“¦ Setting up Podman portable binaries for ${platform}...`);
74
-
75
- if (!DOWNLOADS[platform]) {
76
- console.log(`āš ļø Platform ${platform} not supported for auto-download`);
77
- console.log(` Skipping auto-download (will use system Podman if available)`);
78
- return;
79
- }
80
-
81
- // Create bin directory
82
- if (!existsSync(binDir)) {
83
- mkdirSync(binDir, { recursive: true });
84
- }
85
-
86
- const { url, binary, extract } = DOWNLOADS[platform];
87
- const binaryPath = join(binDir, binary);
88
-
89
- // Check if already downloaded
90
- if (existsSync(binaryPath)) {
91
- console.log(`āœ… Podman already installed at ${binaryPath}`);
92
- return;
93
- }
94
-
95
- console.log(`šŸ“„ Downloading Podman remote v${PODMAN_VERSION}...`);
96
-
97
- const archiveName = url.split('/').pop();
98
- const archivePath = join(binDir, archiveName);
99
-
100
- try {
101
- // Download archive
102
- console.log(` Downloading from GitHub releases...`);
103
- await download(url, archivePath);
104
- console.log(`āœ… Downloaded successfully`);
105
-
106
- // Extract based on platform
107
- console.log(`šŸ“¦ Extracting...`);
108
- if (extract === 'tar') {
109
- execSync(`tar -xzf "${archivePath}" -C "${binDir}" --strip-components=1`, {
110
- stdio: 'pipe'
111
- });
112
- } else if (extract === 'unzip') {
113
- execSync(`unzip -q "${archivePath}" -d "${binDir}"`, {
114
- stdio: 'pipe'
115
- });
116
- }
117
-
118
- // Make executable on Unix
119
- if (platform !== 'win32' && existsSync(binaryPath)) {
120
- chmodSync(binaryPath, 0o755);
121
- }
122
-
123
- console.log(`āœ… Podman remote installed successfully!`);
124
- console.log(` Binary: ${binaryPath}\n`);
125
-
126
- // Clean up archive
127
- if (existsSync(archivePath)) {
128
- unlinkSync(archivePath);
129
- }
130
-
131
- } catch (error) {
132
- console.error(`āš ļø Auto-download failed: ${error.message}`);
133
- console.log(`\nšŸ’” No problem! You can install Podman manually:`);
134
- if (platform === 'win32') {
135
- console.log(` winget install RedHat.Podman`);
136
- } else if (platform === 'darwin') {
137
- console.log(` brew install podman && podman machine init && podman machine start`);
138
- } else {
139
- console.log(` sudo apt-get install podman # Ubuntu/Debian`);
140
- }
141
- console.log(`\n Or it will use system Podman if installed.\n`);
142
- // Don't fail the npm install
143
- }
144
- }
145
-
146
- main().catch(() => {
147
- // Silently fail - will use system Podman
148
- });
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Auto-download Podman portable binaries
5
+ * Similar to how sqlite/playwright auto-downloads platform-specific binaries
6
+ */
7
+
8
+ import { createWriteStream, existsSync, mkdirSync, chmodSync, unlinkSync, createReadStream, readdirSync, statSync } from 'fs';
9
+ import { get as httpsGet } from 'https';
10
+ import { get as httpGet } from 'http';
11
+ import { join, dirname, sep } from 'path';
12
+ import { fileURLToPath } from 'url';
13
+ import { execSync } from 'child_process';
14
+ import { createGunzip } from 'zlib';
15
+ import { pipeline } from 'stream/promises';
16
+
17
+ const __filename = fileURLToPath(import.meta.url);
18
+ const __dirname = dirname(__filename);
19
+ const binDir = join(__dirname, '..', 'bin');
20
+
21
+ // Podman remote client versions
22
+ const PODMAN_VERSION = '4.9.3';
23
+
24
+ // Get architecture
25
+ const ARCH = process.arch === 'arm64' ? 'arm64' : 'amd64';
26
+
27
+ const DOWNLOADS = {
28
+ win32: {
29
+ url: `https://github.com/containers/podman/releases/download/v${PODMAN_VERSION}/podman-remote-release-windows_amd64.zip`,
30
+ binary: 'podman.exe',
31
+ extract: 'unzip'
32
+ },
33
+ darwin: {
34
+ url: `https://github.com/containers/podman/releases/download/v${PODMAN_VERSION}/podman-remote-release-darwin_${ARCH}.tar.gz`,
35
+ binary: 'podman',
36
+ extract: 'tar'
37
+ },
38
+ linux: {
39
+ url: `https://github.com/containers/podman/releases/download/v${PODMAN_VERSION}/podman-remote-static-linux_${ARCH}.tar.gz`,
40
+ binary: `podman-remote-static-linux_${ARCH}`,
41
+ extract: 'tar'
42
+ }
43
+ };
44
+
45
+ function download(url, dest) {
46
+ return new Promise((resolve, reject) => {
47
+ const get = url.startsWith('https') ? httpsGet : httpGet;
48
+
49
+ get(url, (response) => {
50
+ if (response.statusCode === 302 || response.statusCode === 301) {
51
+ return download(response.headers.location, dest).then(resolve).catch(reject);
52
+ }
53
+
54
+ if (response.statusCode !== 200) {
55
+ reject(new Error(`Download failed: ${response.statusCode}`));
56
+ return;
57
+ }
58
+
59
+ const file = createWriteStream(dest);
60
+ response.pipe(file);
61
+
62
+ file.on('finish', () => {
63
+ file.close();
64
+ resolve();
65
+ });
66
+
67
+ file.on('error', reject);
68
+ }).on('error', reject);
69
+ });
70
+ }
71
+
72
+ // Simple ZIP extraction using built-in Node.js modules
73
+ // Basic implementation that handles standard ZIP files without compression complications
74
+ async function extractZip(zipPath, extractTo) {
75
+ return new Promise((resolve, reject) => {
76
+ try {
77
+ // For Windows, we'll use PowerShell's built-in ZIP extraction capability
78
+ // This is more reliable than expecting external tools
79
+ const psCommand = `Add-Type -AssemblyName System.IO.Compression.FileSystem; [System.IO.Compression.ZipFile]::ExtractToDirectory('${zipPath.replace(/'/g, "''")}', '${extractTo.replace(/'/g, "''")}')`;
80
+
81
+ execSync(`powershell -Command "${psCommand}"`, {
82
+ stdio: 'pipe',
83
+ cwd: __dirname,
84
+ shell: true
85
+ });
86
+
87
+ resolve();
88
+ } catch (error) {
89
+ reject(error);
90
+ }
91
+ });
92
+ }
93
+
94
+ // Extract tar.gz files using Node.js built-in modules
95
+ async function extractTarGz(tarPath, extractTo, stripComponents = 0) {
96
+ return new Promise(async (resolve, reject) => {
97
+ try {
98
+ // First, decompress the .gz file
99
+ const tarWithoutGz = tarPath.replace('.gz', '');
100
+ const readStream = createReadStream(tarPath);
101
+ const writeStream = createWriteStream(tarWithoutGz);
102
+ const gunzip = createGunzip();
103
+
104
+ await pipeline(readStream, gunzip, writeStream);
105
+
106
+ // For tar extraction, we need to use system tar since implementing a full tar parser is complex
107
+ // But we'll ensure it works across platforms by providing fallbacks
108
+ try {
109
+ execSync(`tar -xf "${tarWithoutGz}" -C "${extractTo}"${stripComponents ? ` --strip-components=${stripComponents}` : ''}`, {
110
+ stdio: 'pipe',
111
+ shell: process.platform === 'win32'
112
+ });
113
+ } catch (tarError) {
114
+ // If system tar fails, try with specific flags for different platforms
115
+ if (process.platform === 'win32') {
116
+ // On Windows, try with different tar implementations
117
+ try {
118
+ execSync(`bsdtar -xf "${tarWithoutGz}" -C "${extractTo}"${stripComponents ? ` --strip-components=${stripComponents}` : ''}`, {
119
+ stdio: 'pipe',
120
+ shell: true
121
+ });
122
+ } catch (bsdtarError) {
123
+ throw new Error(`Failed to extract tar archive. Please install tar or bsdtar: ${tarError.message}`);
124
+ }
125
+ } else {
126
+ throw tarError;
127
+ }
128
+ }
129
+
130
+ // Clean up the intermediate .tar file
131
+ unlinkSync(tarWithoutGz);
132
+
133
+ resolve();
134
+ } catch (error) {
135
+ reject(error);
136
+ }
137
+ });
138
+ }
139
+
140
+ async function main() {
141
+ const platform = process.platform;
142
+
143
+ console.log(`\nšŸ“¦ Setting up Podman portable binaries for ${platform}...`);
144
+
145
+ if (!DOWNLOADS[platform]) {
146
+ console.log(`āš ļø Platform ${platform} not supported for auto-download`);
147
+ console.log(` Skipping auto-download (will use system Podman if available)`);
148
+ return;
149
+ }
150
+
151
+ // Create bin directory
152
+ if (!existsSync(binDir)) {
153
+ mkdirSync(binDir, { recursive: true });
154
+ }
155
+
156
+ const { url, binary, extract } = DOWNLOADS[platform];
157
+ const binaryPath = join(binDir, binary);
158
+
159
+ // Check if already downloaded
160
+ if (existsSync(binaryPath)) {
161
+ console.log(`āœ… Podman already installed at ${binaryPath}`);
162
+ return;
163
+ }
164
+
165
+ console.log(`šŸ“„ Downloading Podman remote v${PODMAN_VERSION}...`);
166
+
167
+ const archiveName = url.split('/').pop();
168
+ const archivePath = join(binDir, archiveName);
169
+
170
+ try {
171
+ // Clean up any previous failed extractions using fs operations
172
+ const extractedDir = join(binDir, 'podman-4.9.3');
173
+ if (existsSync(extractedDir)) {
174
+ const fs = await import('fs/promises');
175
+ await fs.rm(extractedDir, { recursive: true, force: true });
176
+ }
177
+
178
+ // Download archive
179
+ console.log(` Downloading from GitHub releases...`);
180
+ await download(url, archivePath);
181
+ console.log(`āœ… Downloaded successfully`);
182
+
183
+ // Extract based on platform
184
+ console.log(`šŸ“¦ Extracting...`);
185
+ if (extract === 'tar') {
186
+ await extractTarGz(archivePath, binDir, 1);
187
+ } else if (extract === 'unzip') {
188
+ await extractZip(archivePath, binDir);
189
+
190
+ // Windows-specific: move podman.exe from nested directory to bin/
191
+ if (platform === 'win32') {
192
+ const extractedDir = join(binDir, `podman-4.9.3`);
193
+ const extractedPodman = join(extractedDir, 'usr', 'bin', 'podman.exe');
194
+ const targetPodman = join(binDir, binary);
195
+
196
+ if (existsSync(extractedPodman)) {
197
+ // Use fs operations instead of shell commands for cross-platform compatibility
198
+ const fs = await import('fs/promises');
199
+ await fs.copyFile(extractedPodman, targetPodman);
200
+
201
+ // Clean up the extracted directory
202
+ await fs.rm(extractedDir, { recursive: true, force: true });
203
+ }
204
+ }
205
+ }
206
+
207
+ // Make executable on Unix
208
+ if (platform !== 'win32' && existsSync(binaryPath)) {
209
+ chmodSync(binaryPath, 0o755);
210
+ }
211
+
212
+ console.log(`āœ… Podman remote installed successfully!`);
213
+ console.log(` Binary: ${binaryPath}\n`);
214
+
215
+ // Clean up archive
216
+ if (existsSync(archivePath)) {
217
+ unlinkSync(archivePath);
218
+ }
219
+
220
+ } catch (error) {
221
+ console.error(`āš ļø Auto-download failed: ${error.message}`);
222
+ console.log(`\nšŸ’” No problem! You can install Podman manually:`);
223
+ if (platform === 'win32') {
224
+ console.log(` winget install RedHat.Podman`);
225
+ } else if (platform === 'darwin') {
226
+ console.log(` brew install podman && podman machine init && podman machine start`);
227
+ } else {
228
+ console.log(` sudo apt-get install podman # Ubuntu/Debian`);
229
+ }
230
+ console.log(`\n Or it will use system Podman if installed.\n`);
231
+ // Don't fail the npm install
232
+ }
233
+ }
234
+
235
+ main().catch(() => {
236
+ // Silently fail - will use system Podman
237
+ });
@@ -0,0 +1,19 @@
1
+ # Test Dockerfile for SandboxBox
2
+ FROM node:18-alpine
3
+
4
+ WORKDIR /app
5
+
6
+ # Copy package files
7
+ COPY package*.json ./
8
+
9
+ # Install dependencies (skip postinstall scripts for testing)
10
+ RUN npm install --ignore-scripts
11
+
12
+ # Copy source code
13
+ COPY . .
14
+
15
+ # Expose port
16
+ EXPOSE 3000
17
+
18
+ # Default command
19
+ CMD ["npm", "start"]
package/test/index.js ADDED
@@ -0,0 +1,16 @@
1
+ console.log('Hello from SandboxBox test container!');
2
+ console.log('Node.js version:', process.version);
3
+ console.log('Platform:', process.platform);
4
+ console.log('Current working directory:', process.cwd());
5
+
6
+ const http = require('http');
7
+
8
+ const server = http.createServer((req, res) => {
9
+ res.writeHead(200, { 'Content-Type': 'text/plain' });
10
+ res.end('Hello from SandboxBox container!\n');
11
+ });
12
+
13
+ const PORT = process.env.PORT || 3000;
14
+ server.listen(PORT, () => {
15
+ console.log(`Server running on port ${PORT}`);
16
+ });
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "test-project",
3
+ "version": "1.0.0",
4
+ "description": "Test project for SandboxBox",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "start": "node index.js",
8
+ "test": "echo 'Running tests...' && exit 0"
9
+ },
10
+ "keywords": ["test", "sandbox"],
11
+ "author": "",
12
+ "license": "ISC"
13
+ }
package/bin/.gitkeep DELETED
@@ -1 +0,0 @@
1
- # Downloaded Podman binaries will go here