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 +58 -0
- package/Dockerfile +2 -2
- package/claude +0 -0
- package/cli.js +10 -7
- package/package.json +1 -1
- package/test-file.txt +1 -0
- package/test-from-container.txt +1 -0
- package/test-git-push.sh +22 -0
- package/utils/claude-workspace.js +12 -5
- package/utils/isolation.js +71 -2
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
|
105
|
-
const
|
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
package/test-file.txt
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
'test-content'
|
@@ -0,0 +1 @@
|
|
1
|
+
'test from container'
|
package/test-git-push.sh
ADDED
@@ -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
|
-
|
26
|
-
|
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
|
-
|
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
|
}
|
package/utils/isolation.js
CHANGED
@@ -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 {
|