sandboxbox 2.3.0 → 2.3.2

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/cli.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  /**
4
4
  * SandboxBox CLI - Portable Container Runner with Podman
@@ -10,7 +10,7 @@ import { color } from './utils/colors.js';
10
10
  import { showBanner, showHelp } from './utils/ui.js';
11
11
  import { buildCommand, runCommand, shellCommand, claudeCommand, versionCommand } from './utils/commands/index.js';
12
12
 
13
- async function main() {
13
+ function main() {
14
14
  const args = process.argv.slice(2);
15
15
  showBanner();
16
16
 
@@ -71,10 +71,4 @@ async function main() {
71
71
  }
72
72
  }
73
73
 
74
- main().catch(error => {
75
- console.error(color('red', 'āŒ SandboxBox failed:'));
76
- console.error(color('red', error.message));
77
- console.error('');
78
- console.error(color('yellow', 'šŸ’” Try: npx sandboxbox --help'));
79
- process.exit(1);
80
- });
74
+ main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sandboxbox",
3
- "version": "2.3.0",
3
+ "version": "2.3.2",
4
4
  "description": "Portable container runner with Podman - Claude Code & Playwright support. Works on Windows, macOS, and Linux.",
5
5
  "type": "module",
6
6
  "main": "cli.js",
@@ -3,7 +3,7 @@ import { execSync } from 'child_process';
3
3
  import { resolve, dirname } from 'path';
4
4
  import { fileURLToPath } from 'url';
5
5
  import { color } from '../colors.js';
6
- import { checkPodman, ensureBackend, getPodmanPath } from '../podman.js';
6
+ import { checkPodman, setupBackendNonBlocking, getPodmanPath } from '../podman.js';
7
7
  import { buildClaudeContainerCommand, createClaudeDockerfile } from '../claude-workspace.js';
8
8
  import { createIsolatedEnvironment, setupCleanupHandlers, buildContainerMounts } from '../isolation.js';
9
9
 
@@ -42,7 +42,7 @@ export function claudeCommand(projectDir, command = 'claude') {
42
42
 
43
43
  const buildPodman = checkPodman();
44
44
  if (!buildPodman) return false;
45
- if (!ensureBackend(buildPodman)) return false;
45
+ if (!setupBackendNonBlocking(buildPodman)) return false;
46
46
 
47
47
  try {
48
48
  const { tempProjectDir, cleanup } = createIsolatedEnvironment(projectDir);
@@ -73,7 +73,7 @@ function buildClaudeContainer() {
73
73
 
74
74
  const podmanPath = checkPodman();
75
75
  if (!podmanPath) return false;
76
- if (!ensureBackend(podmanPath)) return false;
76
+ if (!setupBackendNonBlocking(podmanPath)) return false;
77
77
 
78
78
  try {
79
79
  execSync(`"${podmanPath}" build -f "${dockerfilePath}" -t sandboxbox-local:latest .`, {
@@ -2,7 +2,7 @@ import { existsSync } from 'fs';
2
2
  import { execSync } from 'child_process';
3
3
  import { dirname } from 'path';
4
4
  import { color } from '../colors.js';
5
- import { checkPodman, ensureBackend } from '../podman.js';
5
+ import { checkPodman, setupBackendNonBlocking } from '../podman.js';
6
6
  import { createIsolatedEnvironment, setupCleanupHandlers, buildContainerMounts } from '../isolation.js';
7
7
 
8
8
  export function buildCommand(dockerfilePath) {
@@ -16,7 +16,7 @@ export function buildCommand(dockerfilePath) {
16
16
 
17
17
  const podmanPath = checkPodman();
18
18
  if (!podmanPath) return false;
19
- if (!ensureBackend(podmanPath)) return false;
19
+ if (!setupBackendNonBlocking(podmanPath)) return false;
20
20
 
21
21
  try {
22
22
  execSync(`"${podmanPath}" build -f "${dockerfilePath}" -t sandboxbox:latest .`, {
@@ -45,7 +45,7 @@ export function runCommand(projectDir, cmd = 'bash') {
45
45
 
46
46
  const podmanPath = checkPodman();
47
47
  if (!podmanPath) return false;
48
- if (!ensureBackend(podmanPath)) return false;
48
+ if (!setupBackendNonBlocking(podmanPath)) return false;
49
49
 
50
50
  try {
51
51
  const { tempProjectDir, cleanup } = createIsolatedEnvironment(projectDir);
@@ -78,7 +78,7 @@ export function shellCommand(projectDir) {
78
78
 
79
79
  const podmanPath = checkPodman();
80
80
  if (!podmanPath) return false;
81
- if (!ensureBackend(podmanPath)) return false;
81
+ if (!setupBackendNonBlocking(podmanPath)) return false;
82
82
 
83
83
  try {
84
84
  const { tempProjectDir, cleanup } = createIsolatedEnvironment(projectDir);
package/utils/podman.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { existsSync } from 'fs';
2
- import { execSync } from 'child_process';
2
+ import { execSync, spawn } from 'child_process';
3
3
  import { resolve, dirname } from 'path';
4
4
  import { fileURLToPath } from 'url';
5
5
  import { color } from './colors.js';
@@ -26,7 +26,7 @@ export function getPodmanPath() {
26
26
  return 'podman';
27
27
  }
28
28
 
29
- export function ensureBackend(podmanPath) {
29
+ export function setupBackendNonBlocking(podmanPath) {
30
30
  if (process.platform === 'linux') return true;
31
31
 
32
32
  const execOptions = { encoding: 'utf-8', stdio: 'pipe', shell: true };
@@ -35,9 +35,11 @@ export function ensureBackend(podmanPath) {
35
35
  execSync(`"${podmanPath}" info`, execOptions);
36
36
  return true;
37
37
  } catch (infoError) {
38
- if (!infoError.message.includes('Cannot connect to Podman')) throw infoError;
38
+ if (!infoError.message.includes('Cannot connect to Podman')) {
39
+ return false;
40
+ }
39
41
 
40
- console.log(color('yellow', '\nšŸ”§ Initializing Podman backend (first run, takes 2-3 minutes)...'));
42
+ console.log(color('yellow', '\nšŸ”§ Initializing Podman backend (one-time setup, takes 2-3 minutes)...'));
41
43
 
42
44
  try {
43
45
  const machineListOutput = execSync(`"${podmanPath}" machine list --format json`, execOptions);
@@ -48,17 +50,58 @@ export function ensureBackend(podmanPath) {
48
50
  const initCmd = process.platform === 'win32'
49
51
  ? `"${podmanPath}" machine init --rootful=false`
50
52
  : `"${podmanPath}" machine init`;
51
- execSync(initCmd, { stdio: 'inherit', shell: true });
53
+
54
+ execSync(initCmd, {
55
+ stdio: 'inherit',
56
+ shell: true,
57
+ timeout: 120000 // 2 minutes
58
+ });
52
59
  }
53
60
 
54
61
  console.log(color('cyan', ' Starting Podman machine...'));
55
- execSync(`"${podmanPath}" machine start`, { stdio: 'inherit', shell: true });
56
- console.log(color('green', 'āœ… Podman backend ready\n'));
62
+ execSync(`"${podmanPath}" machine start`, {
63
+ stdio: 'inherit',
64
+ shell: true,
65
+ timeout: 60000 // 1 minute
66
+ });
67
+
68
+ console.log(color('green', '\nāœ… Podman backend setup completed!\n'));
57
69
  return true;
58
- } catch (backendError) {
59
- console.log(color('red', `\nāŒ Backend setup failed: ${backendError.message}`));
70
+ } catch (setupError) {
71
+ if (setupError.signal === 'SIGTERM') {
72
+ console.log(color('red', '\nāŒ Setup timed out. Please run manually:'));
73
+ } else {
74
+ console.log(color('red', `\nāŒ Setup failed: ${setupError.message}`));
75
+ }
76
+
77
+ const manualCmd = process.platform === 'win32'
78
+ ? `"${podmanPath}" machine init --rootful=false && "${podmanPath}" machine start`
79
+ : `"${podmanPath}" machine init && "${podmanPath}" machine start`;
80
+ console.log(color('cyan', ` Manual setup: ${manualCmd}`));
81
+ return false;
82
+ }
83
+ }
84
+ }
85
+
86
+ export function checkBackend(podmanPath) {
87
+ if (process.platform === 'linux') return true;
88
+
89
+ const execOptions = { encoding: 'utf-8', stdio: 'pipe', shell: true };
90
+
91
+ try {
92
+ execSync(`"${podmanPath}" info`, execOptions);
93
+ return true;
94
+ } catch (infoError) {
95
+ if (infoError.message.includes('Cannot connect to Podman')) {
96
+ console.log(color('red', '\nāŒ Podman backend not running'));
97
+ console.log(color('yellow', '\nšŸ“‹ One-time setup required:'));
98
+ console.log(color('cyan', process.platform === 'win32'
99
+ ? ' Run: podman machine init --rootful=false && podman machine start'
100
+ : ' Run: podman machine init && podman machine start'));
101
+ console.log(color('yellow', '\nā±ļø This takes 2-3 minutes, then works instantly forever.\n'));
60
102
  return false;
61
103
  }
104
+ throw infoError;
62
105
  }
63
106
  }
64
107