sandboxbox 2.1.0 → 2.1.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/CLAUDE.md CHANGED
@@ -41,6 +41,21 @@ All `execSync()` calls must include:
41
41
  }
42
42
  ```
43
43
 
44
+ ### Windows Command Interpretation
45
+ - **Avoid Unix-specific syntax**: `|| true` doesn't work on Windows
46
+ - **Use platform-specific error handling**:
47
+ ```javascript
48
+ if (process.platform === 'win32') {
49
+ try {
50
+ execSync(`git remote remove origin`, { stdio: 'pipe', shell: true });
51
+ } catch (e) {
52
+ // Ignore if origin doesn't exist
53
+ }
54
+ } else {
55
+ execSync(`git remote remove origin 2>/dev/null || true`, { stdio: 'pipe', shell: true });
56
+ }
57
+ ```
58
+
44
59
  ### Auto Podman Machine Management
45
60
  ```javascript
46
61
  // cli.js checkPodman() function
@@ -177,6 +192,49 @@ All commands automatically mount git identity:
177
192
  -v "$HOME/.ssh:/root/.ssh:ro" # SSH keys for git operations
178
193
  ```
179
194
 
195
+ ### Host Repository Git Remote Setup
196
+ For git push functionality from isolated containers:
197
+ ```bash
198
+ # Mount host repository as accessible remote
199
+ -v "/path/to/host/repo:/host-repo:rw"
200
+
201
+ # Configure git remote to point to mounted host repository
202
+ git remote add origin /host-repo
203
+ git branch --set-upstream-to=origin/main main
204
+ ```
205
+
206
+ ### Git Push Workflow Limitations
207
+ - **Windows command quoting**: Complex git commands with spaces require bash wrapper
208
+ - **Interactive shells**: Use `bash -c 'command'` for complex operations
209
+ - **Command chaining**: Multiple git operations work better in single container session
210
+ - **Bash command execution**: Commands like `bash -c 'command'` may start interactive shell instead of executing
211
+
212
+ ### Git Remote Setup Requirements
213
+ - **Automatic remote configuration**: `git remote add origin /host-repo`
214
+ - **Upstream branch setup**: Use `git push -u origin master` instead of manual upstream configuration
215
+ - **Host repository mounting**: Must mount original project as `/host-repo:rw` in container
216
+ - **Git identity transfer**: Requires `.gitconfig` and `.ssh` directory mounting
217
+ - **Windows path normalization**: Critical for cross-platform compatibility:
218
+ ```javascript
219
+ // Normalize paths for cross-platform compatibility
220
+ const normalizedTempDir = tempProjectDir.replace(/\\/g, '/');
221
+ ```
222
+ - **Git safe directory configuration**: Required for mounted repositories:
223
+ ```bash
224
+ git config --global --add safe.directory /workspace
225
+ git config --global --add safe.directory /host-repo
226
+ git config --global --add safe.directory /host-repo/.git
227
+ ```
228
+ - **Host repository push configuration**: Allow pushes to checked-out branch:
229
+ ```bash
230
+ git config receive.denyCurrentBranch ignore
231
+ ```
232
+ - **Git identity setup**: Container requires explicit git user configuration:
233
+ ```bash
234
+ git config --global user.email "user@example.com"
235
+ git config --global user.name "User Name"
236
+ ```
237
+
180
238
  ### Claude Code MCP Integration
181
239
  The claude command includes MCP servers and settings:
182
240
  ```bash
package/Dockerfile CHANGED
@@ -81,8 +81,8 @@ RUN sh -c "$(wget -O- https://github.com/deluan/zsh-in-docker/releases/download/
81
81
  # Install Claude
82
82
  RUN npm install -g @anthropic-ai/claude-code@${CLAUDE_CODE_VERSION}
83
83
 
84
- # Install playwright deps
85
- RUN npx --yes playwright install-deps
84
+ # Install playwright deps (commented out due to build issues)
85
+ # RUN npx --yes playwright install-deps
86
86
 
87
87
  RUN npm i -g @playwright/mcp
88
88
 
package/claude ADDED
File without changes
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
@@ -101,8 +101,11 @@ function runClaudeWorkspace(projectDir, command = 'claude') {
101
101
  // Set up cleanup handlers
102
102
  setupCleanupHandlers(cleanup);
103
103
 
104
- // Build container command with isolated project directory
105
- const containerCommand = buildClaudeContainerCommand(tempProjectDir, podmanPath, command);
104
+ // Build container mounts with git identity and host remote
105
+ const mounts = buildContainerMounts(tempProjectDir, projectDir);
106
+
107
+ // Build claude-specific container command with mounts
108
+ const containerCommand = buildClaudeContainerCommand(tempProjectDir, podmanPath, command, mounts);
106
109
  execSync(containerCommand, {
107
110
  stdio: 'inherit',
108
111
  shell: process.platform === 'win32'
@@ -189,8 +192,8 @@ async function main() {
189
192
  // Set up cleanup handlers
190
193
  setupCleanupHandlers(cleanup);
191
194
 
192
- // Build container mounts with git identity
193
- const mounts = buildContainerMounts(tempProjectDir);
195
+ // Build container mounts with git identity and host remote
196
+ const mounts = buildContainerMounts(tempProjectDir, projectDir);
194
197
 
195
198
  // Run the command in isolated container with temporary directory and git identity
196
199
  execSync(`"${runPodman}" run --rm -it ${mounts.join(' ')} -w /workspace sandboxbox:latest ${cmd}`, {
@@ -236,8 +239,8 @@ async function main() {
236
239
  // Set up cleanup handlers
237
240
  setupCleanupHandlers(cleanup);
238
241
 
239
- // Build container mounts with git identity
240
- const mounts = buildContainerMounts(tempProjectDir);
242
+ // Build container mounts with git identity and host remote
243
+ const mounts = buildContainerMounts(tempProjectDir, shellProjectDir);
241
244
 
242
245
  // Start interactive shell in isolated container with temporary directory and git identity
243
246
  execSync(`"${shellPodman}" run --rm -it ${mounts.join(' ')} -w /workspace sandboxbox:latest /bin/bash`, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sandboxbox",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
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",
package/test-file.txt ADDED
@@ -0,0 +1 @@
1
+ 'test-content'
@@ -0,0 +1 @@
1
+ 'test from container'
@@ -0,0 +1,22 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ echo "=== Git Remote Check ==="
5
+ git remote -v
6
+
7
+ echo "=== File Creation ==="
8
+ echo "test content from container" > test-file.txt
9
+
10
+ echo "=== Git Status ==="
11
+ git status
12
+
13
+ echo "=== Git Add ==="
14
+ git add test-file.txt
15
+
16
+ echo "=== Git Commit ==="
17
+ git commit -m "Test commit from container"
18
+
19
+ echo "=== Git Push ==="
20
+ git push -u origin master
21
+
22
+ echo "=== Done ==="
@@ -14,7 +14,7 @@ export function getClaudeEnvironment() {
14
14
  return envVars;
15
15
  }
16
16
 
17
- export function buildClaudeContainerCommand(projectPath, podmanPath, command = 'claude') {
17
+ export function buildClaudeContainerCommand(projectPath, podmanPath, command = 'claude', customMounts = null) {
18
18
  const envVars = getClaudeEnvironment();
19
19
  const envArgs = Object.entries(envVars)
20
20
  .map(([key, value]) => `-e ${key}="${value}"`)
@@ -22,8 +22,16 @@ export function buildClaudeContainerCommand(projectPath, podmanPath, command = '
22
22
 
23
23
  const homeDir = process.platform === 'win32' ? process.env.USERPROFILE : process.env.HOME;
24
24
 
25
- // Build base mounts from isolation utility (includes git identity)
26
- const baseMounts = buildContainerMounts(projectPath);
25
+ let allMounts = [];
26
+
27
+ if (customMounts) {
28
+ // Use provided custom mounts (includes git identity and host remote)
29
+ allMounts = customMounts;
30
+ } else {
31
+ // Build base mounts from isolation utility (includes git identity)
32
+ const baseMounts = buildContainerMounts(projectPath);
33
+ allMounts = baseMounts;
34
+ }
27
35
 
28
36
  // Add Claude-specific mounts
29
37
  const claudeMounts = [
@@ -31,8 +39,7 @@ export function buildClaudeContainerCommand(projectPath, podmanPath, command = '
31
39
  `-v "${process.cwd()}/claude-settings.json:/root/.claude/settings.json:ro"`
32
40
  ];
33
41
 
34
- // Combine all mounts
35
- const allMounts = [...baseMounts, ...claudeMounts];
42
+ allMounts = [...allMounts, ...claudeMounts];
36
43
 
37
44
  return `${podmanPath} run --rm -it ${allMounts.join(' ')} ${envArgs} --env HOME=/root sandboxbox-local:latest ${command}`;
38
45
  }
@@ -4,13 +4,17 @@ import { join } from 'path';
4
4
  import { execSync } from 'child_process';
5
5
 
6
6
  /**
7
- * Builds container volume mounts with git identity
7
+ * Builds container volume mounts with git identity and host remote
8
8
  * @param {string} tempProjectDir - Temporary project directory
9
+ * @param {string} originalProjectDir - Original host project directory
9
10
  * @returns {Array} - Array of volume mount strings
10
11
  */
11
- export function buildContainerMounts(tempProjectDir) {
12
+ export function buildContainerMounts(tempProjectDir, originalProjectDir) {
12
13
  const mounts = [`-v "${tempProjectDir}:/workspace:rw"`];
13
14
 
15
+ // Add host repository as git remote
16
+ mounts.push(`-v "${originalProjectDir}:/host-repo:rw"`);
17
+
14
18
  // Add git identity mounts
15
19
  const homeDir = process.platform === 'win32' ? process.env.USERPROFILE : process.env.HOME;
16
20
 
@@ -72,6 +76,71 @@ export function createIsolatedEnvironment(projectDir) {
72
76
  });
73
77
  }
74
78
 
79
+ // Configure git remote to point to mounted host repository
80
+ try {
81
+ // Normalize paths for cross-platform compatibility
82
+ const normalizedTempDir = tempProjectDir.replace(/\\/g, '/');
83
+ const normalizedOriginalDir = projectDir.replace(/\\/g, '/');
84
+
85
+ // Configure git to allow operations in mounted directories
86
+ execSync(`git config --global --add safe.directory /workspace`, {
87
+ stdio: 'pipe',
88
+ shell: true
89
+ });
90
+
91
+ // Configure host repository to accept pushes to checked-out branch
92
+ if (process.platform === 'win32') {
93
+ try {
94
+ execSync(`cd "${normalizedOriginalDir}" && git config receive.denyCurrentBranch ignore`, {
95
+ stdio: 'pipe',
96
+ shell: true
97
+ });
98
+ } catch (e) {
99
+ // Ignore if git config fails
100
+ }
101
+ } else {
102
+ execSync(`cd "${normalizedOriginalDir}" && git config receive.denyCurrentBranch ignore`, {
103
+ stdio: 'pipe',
104
+ shell: true
105
+ });
106
+ }
107
+
108
+ // Remove any existing origin first (Windows-compatible)
109
+ if (process.platform === 'win32') {
110
+ try {
111
+ execSync(`cd "${normalizedTempDir}" && git remote remove origin`, {
112
+ stdio: 'pipe',
113
+ shell: true
114
+ });
115
+ } catch (e) {
116
+ // Ignore if origin doesn't exist
117
+ }
118
+ } else {
119
+ execSync(`cd "${normalizedTempDir}" && git remote remove origin 2>/dev/null || true`, {
120
+ stdio: 'pipe',
121
+ shell: true
122
+ });
123
+ }
124
+
125
+ // Add origin pointing to mounted host repository (accessible from container)
126
+ execSync(`cd "${normalizedTempDir}" && git remote add origin /host-repo`, {
127
+ stdio: 'pipe',
128
+ shell: true
129
+ });
130
+
131
+ // Set up upstream tracking for current branch (use push -u to set upstream)
132
+ const currentBranch = execSync(`cd "${normalizedTempDir}" && git branch --show-current`, {
133
+ encoding: 'utf8',
134
+ stdio: 'pipe'
135
+ }).trim();
136
+
137
+ // Note: Upstream will be set automatically on first push with -u flag
138
+ // No need to set up upstream manually as it may not exist yet
139
+ } catch (error) {
140
+ // Log git remote setup errors for debugging
141
+ console.error(`Git remote setup failed: ${error.message}`);
142
+ }
143
+
75
144
  // Ensure cleanup on exit
76
145
  const cleanup = () => {
77
146
  try {