sandboxbox 3.0.2 โ 3.0.4
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/.vexify.db +0 -0
- package/0.60 +0 -0
- package/CLAUDE.md +69 -35
- package/Dockerfile +0 -0
- package/Dockerfile.claude +0 -0
- package/Dockerfile.local-workspace +0 -0
- package/Dockerfile.simple +0 -0
- package/README.md +0 -0
- package/claude +0 -0
- package/claude-settings.json +0 -0
- package/cli.js +77 -77
- package/{C:devtest-echo โ devtest-echo}/test.js +0 -0
- package/direct-test-result.txt +0 -0
- package/file.txt +0 -0
- package/launch-sandboxbox.bat +0 -0
- package/launch-sandboxbox.sh +0 -0
- package/package.json +1 -1
- package/podman.zip +0 -0
- package/sandboxbox-2.2.2.tgz +0 -0
- package/test/Dockerfile +0 -0
- package/test/index.js +0 -0
- package/test/package.json +0 -0
- package/utils/colors.js +0 -0
- package/utils/commands/claude.js +182 -19
- package/utils/commands/container.js +1 -1
- package/utils/commands/index.js +0 -0
- package/utils/sandbox.js +141 -49
- package/utils/ui.js +0 -0
- package/npx-test/package.json +0 -1
- package/npx-test-sandboxbox/package.json +0 -12
- package/test-cross-platform.sh +0 -78
- package/test-echo/test.js +0 -1
- package/test-echo-output.txt +0 -49
- package/test-file.txt +0 -1
- package/test-from-container.txt +0 -1
- package/test-git-push.sh +0 -22
- package/test-merge-workflow.sh +0 -58
- package/test-npx-run/my-project/test.js +0 -1
- package/test-sandbox-workflow.sh +0 -45
- package/testproject/Dockerfile +0 -3
package/.vexify.db
CHANGED
|
File without changes
|
package/0.60
CHANGED
|
File without changes
|
package/CLAUDE.md
CHANGED
|
@@ -100,35 +100,23 @@ cleanup();
|
|
|
100
100
|
## Git Integration
|
|
101
101
|
|
|
102
102
|
### Git Identity Transfer
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
### Git Remote Setup
|
|
109
|
-
```bash
|
|
110
|
-
# Mount host repository as accessible remote
|
|
111
|
-
-v "/path/to/host/repo:/host-repo:rw"
|
|
112
|
-
|
|
113
|
-
# Configure remote in container
|
|
114
|
-
git remote add origin /host-repo
|
|
115
|
-
```
|
|
103
|
+
Automatically transfers host git identity to sandbox after cloning:
|
|
104
|
+
```javascript
|
|
105
|
+
const userName = execSync('git config --global user.name', { encoding: 'utf8' }).trim();
|
|
106
|
+
const userEmail = execSync('git config --global user.email', { encoding: 'utf8' }).trim();
|
|
107
|
+
const colorUi = execSync('git config --global color.ui', { encoding: 'utf8' }).trim();
|
|
116
108
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
git config
|
|
120
|
-
git config --global --add safe.directory /host-repo
|
|
121
|
-
git config --global --add safe.directory /host-repo/.git
|
|
109
|
+
execSync(`git config user.name "${userName}"`, { cwd: workspaceDir });
|
|
110
|
+
execSync(`git config user.email "${userEmail}"`, { cwd: workspaceDir });
|
|
111
|
+
execSync(`git config color.ui "${colorUi}"`, { cwd: workspaceDir });
|
|
122
112
|
```
|
|
123
113
|
|
|
124
|
-
|
|
125
|
-
```bash
|
|
126
|
-
# Host repository - allow pushes to checked-out branch
|
|
127
|
-
git config receive.denyCurrentBranch ignore
|
|
114
|
+
Git identity and color config auto-inherit from ~/.gitconfig (user.name, user.email, color.ui). For sandbox-to-host workflows, host repo needs `receive.denyCurrentBranch=updateInstead` and clean working directory.
|
|
128
115
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
git config --global
|
|
116
|
+
### Git Safe Directory Configuration
|
|
117
|
+
```javascript
|
|
118
|
+
execSync(`git config --global --add safe.directory "${projectDir}"`);
|
|
119
|
+
execSync(`git config --global --add safe.directory "${projectDir}/.git"`);
|
|
132
120
|
```
|
|
133
121
|
|
|
134
122
|
### Windows Path Normalization
|
|
@@ -136,22 +124,68 @@ git config --global user.name "User Name"
|
|
|
136
124
|
const normalizedTempDir = tempProjectDir.replace(/\\/g, '/');
|
|
137
125
|
```
|
|
138
126
|
|
|
127
|
+
### Environment Variable Transfer
|
|
128
|
+
Host bash session environment variables automatically carry through to sandboxes:
|
|
129
|
+
```javascript
|
|
130
|
+
// Terminal
|
|
131
|
+
TERM: process.env.TERM || 'xterm-256color',
|
|
132
|
+
LS_COLORS: process.env.LS_COLORS,
|
|
133
|
+
|
|
134
|
+
// Locale
|
|
135
|
+
LANG: process.env.LANG,
|
|
136
|
+
LC_ALL: process.env.LC_ALL,
|
|
137
|
+
|
|
138
|
+
// User
|
|
139
|
+
SHELL: process.env.SHELL,
|
|
140
|
+
USER: process.env.USER,
|
|
141
|
+
LOGNAME: process.env.LOGNAME,
|
|
142
|
+
|
|
143
|
+
// Tools
|
|
144
|
+
EDITOR: process.env.EDITOR,
|
|
145
|
+
VISUAL: process.env.VISUAL,
|
|
146
|
+
PAGER: process.env.PAGER,
|
|
147
|
+
LESS: process.env.LESS,
|
|
148
|
+
LESSOPEN: process.env.LESSOPEN,
|
|
149
|
+
LESSCLOSE: process.env.LESSCLOSE,
|
|
150
|
+
|
|
151
|
+
// Display
|
|
152
|
+
DISPLAY: process.env.DISPLAY,
|
|
153
|
+
WAYLAND_DISPLAY: process.env.WAYLAND_DISPLAY,
|
|
154
|
+
|
|
155
|
+
// Authentication
|
|
156
|
+
SSH_AUTH_SOCK: process.env.SSH_AUTH_SOCK,
|
|
157
|
+
SSH_AGENT_PID: process.env.SSH_AGENT_PID,
|
|
158
|
+
GPG_AGENT_INFO: process.env.GPG_AGENT_INFO
|
|
159
|
+
```
|
|
160
|
+
|
|
139
161
|
## Claude Code Integration
|
|
140
162
|
|
|
141
163
|
### Authentication
|
|
142
|
-
|
|
143
|
-
-v "$HOME/.claude:/root/.claude"
|
|
144
|
-
-e "ANTHROPIC_AUTH_TOKEN=..."
|
|
145
|
-
-e "CLAUDECODE=1"
|
|
146
|
-
```
|
|
164
|
+
Uses host HOME directory for Claude Code authentication. Workspace is isolated in sandbox but credentials remain on host.
|
|
147
165
|
|
|
148
|
-
###
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
166
|
+
### Tool Allow List
|
|
167
|
+
Automatically configured with 25 allowed tools:
|
|
168
|
+
- Core: Task, Bash, Glob, Grep, Read, Edit, Write, NotebookEdit, WebFetch, TodoWrite, WebSearch, BashOutput, KillShell, SlashCommand, ExitPlanMode
|
|
169
|
+
- MCP: glootie (execute, ast_tool, caveat), playwright (navigate, snapshot, click, type, evaluate, close), vexify (search_code)
|
|
170
|
+
|
|
171
|
+
### Streaming Output
|
|
172
|
+
Uses `--verbose -p --output-format stream-json` for real-time JSON streaming. Output parser extracts text content, tool usage, session info, and cost metrics from JSON stream.
|
|
173
|
+
|
|
174
|
+
### Playwright MCP Profile Transfer
|
|
175
|
+
Automatically copies persistent MCP profiles from host to sandbox:
|
|
176
|
+
```javascript
|
|
177
|
+
const playwrightCacheDir = platform() === 'darwin'
|
|
178
|
+
? join(homedir(), 'Library', 'Caches', 'ms-playwright')
|
|
179
|
+
: platform() === 'win32'
|
|
180
|
+
? join(homedir(), 'AppData', 'Local', 'ms-playwright')
|
|
181
|
+
: join(homedir(), '.cache', 'ms-playwright');
|
|
182
|
+
|
|
183
|
+
// Copies mcp-chrome-profile, mcp-chromium-profile, mcp-firefox-profile, mcp-webkit-profile
|
|
184
|
+
cpSync(hostProfile, join(sandboxDir, '.cache', 'ms-playwright', profileName), { recursive: true });
|
|
153
185
|
```
|
|
154
186
|
|
|
187
|
+
Environment variable `XDG_CACHE_HOME` set to `${sandboxDir}/.cache` for Playwright profile access.
|
|
188
|
+
|
|
155
189
|
## Cleanup
|
|
156
190
|
|
|
157
191
|
### Container Cleanup
|
package/Dockerfile
CHANGED
|
File without changes
|
package/Dockerfile.claude
CHANGED
|
File without changes
|
|
File without changes
|
package/Dockerfile.simple
CHANGED
|
File without changes
|
package/README.md
CHANGED
|
File without changes
|
package/claude
CHANGED
|
File without changes
|
package/claude-settings.json
CHANGED
|
File without changes
|
package/cli.js
CHANGED
|
@@ -1,79 +1,79 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* SandboxBox CLI - Process Containment Sandbox
|
|
5
|
-
* Lightweight process isolation for CLI tools
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { resolve } from 'path';
|
|
9
|
-
import { color } from './utils/colors.js';
|
|
10
|
-
import { showBanner, showHelp } from './utils/ui.js';
|
|
11
|
-
import { buildCommand, runCommand, shellCommand, claudeCommand, versionCommand } from './utils/commands/index.js';
|
|
12
|
-
|
|
13
|
-
async function main() {
|
|
14
|
-
const args = process.argv.slice(2);
|
|
15
|
-
showBanner();
|
|
16
|
-
|
|
17
|
-
if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
|
|
18
|
-
showHelp();
|
|
19
|
-
process.exit(0);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const command = args[0].toLowerCase();
|
|
23
|
-
const commandArgs = args.slice(1);
|
|
24
|
-
|
|
25
|
-
try {
|
|
26
|
-
switch (command) {
|
|
27
|
-
case 'build':
|
|
28
|
-
const dockerfilePath = commandArgs[0]
|
|
29
|
-
if (!buildCommand(dockerfilePath)) process.exit(1);
|
|
30
|
-
break;
|
|
31
|
-
|
|
32
|
-
case 'run':
|
|
33
|
-
if (commandArgs.length === 0) {
|
|
34
|
-
console.log(color('red', 'โ Please specify a project directory'));
|
|
35
|
-
console.log(color('yellow', 'Usage: npx sandboxbox run <project-dir> [command]'));
|
|
36
|
-
process.exit(1);
|
|
37
|
-
}
|
|
38
|
-
const projectDir = resolve(process.cwd(), commandArgs[0]);
|
|
39
|
-
const cmd = commandArgs.slice(1).join(' ')
|
|
40
|
-
if (!(await runCommand(projectDir, cmd))) process.exit(1);
|
|
41
|
-
break;
|
|
42
|
-
|
|
43
|
-
case 'shell':
|
|
44
|
-
if (commandArgs.length === 0) {
|
|
45
|
-
console.log(color('red', 'โ Please specify a project directory'));
|
|
46
|
-
console.log(color('yellow', 'Usage: npx sandboxbox shell <project-dir>'));
|
|
47
|
-
process.exit(1);
|
|
48
|
-
}
|
|
49
|
-
const shellProjectDir = resolve(process.cwd(), commandArgs[0]);
|
|
50
|
-
if (!(await shellCommand(shellProjectDir))) process.exit(1);
|
|
51
|
-
break;
|
|
52
|
-
|
|
53
|
-
case 'claude':
|
|
54
|
-
if (commandArgs.length === 0) {
|
|
55
|
-
console.log(color('red', 'โ Please specify a project directory'));
|
|
56
|
-
console.log(color('yellow', 'Usage: npx sandboxbox claude <project-dir>'));
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
|
-
const claudeProjectDir = resolve(process.cwd(), commandArgs[0]);
|
|
60
|
-
const
|
|
61
|
-
if (!(await claudeCommand(claudeProjectDir,
|
|
62
|
-
break;
|
|
63
|
-
|
|
64
|
-
case 'version':
|
|
65
|
-
if (!versionCommand()) process.exit(1);
|
|
66
|
-
break;
|
|
67
|
-
|
|
68
|
-
default:
|
|
69
|
-
console.log(color('red', `โ Unknown command: ${command}`));
|
|
70
|
-
console.log(color('yellow', 'Use --help for usage information'));
|
|
71
|
-
process.exit(1);
|
|
72
|
-
}
|
|
73
|
-
} catch (error) {
|
|
74
|
-
console.log(color('red', `\nโ Fatal error: ${error.message}`));
|
|
75
|
-
process.exit(1);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SandboxBox CLI - Process Containment Sandbox
|
|
5
|
+
* Lightweight process isolation for CLI tools
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { resolve } from 'path';
|
|
9
|
+
import { color } from './utils/colors.js';
|
|
10
|
+
import { showBanner, showHelp } from './utils/ui.js';
|
|
11
|
+
import { buildCommand, runCommand, shellCommand, claudeCommand, versionCommand } from './utils/commands/index.js';
|
|
12
|
+
|
|
13
|
+
async function main() {
|
|
14
|
+
const args = process.argv.slice(2);
|
|
15
|
+
showBanner();
|
|
16
|
+
|
|
17
|
+
if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
|
|
18
|
+
showHelp();
|
|
19
|
+
process.exit(0);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const command = args[0].toLowerCase();
|
|
23
|
+
const commandArgs = args.slice(1);
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
switch (command) {
|
|
27
|
+
case 'build':
|
|
28
|
+
const dockerfilePath = commandArgs[0];
|
|
29
|
+
if (!buildCommand(dockerfilePath)) process.exit(1);
|
|
30
|
+
break;
|
|
31
|
+
|
|
32
|
+
case 'run':
|
|
33
|
+
if (commandArgs.length === 0) {
|
|
34
|
+
console.log(color('red', 'โ Please specify a project directory'));
|
|
35
|
+
console.log(color('yellow', 'Usage: npx sandboxbox run <project-dir> [command]'));
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
const projectDir = resolve(process.cwd(), commandArgs[0]);
|
|
39
|
+
const cmd = commandArgs.slice(1).join(' ');
|
|
40
|
+
if (!(await runCommand(projectDir, cmd))) process.exit(1);
|
|
41
|
+
break;
|
|
42
|
+
|
|
43
|
+
case 'shell':
|
|
44
|
+
if (commandArgs.length === 0) {
|
|
45
|
+
console.log(color('red', 'โ Please specify a project directory'));
|
|
46
|
+
console.log(color('yellow', 'Usage: npx sandboxbox shell <project-dir>'));
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
const shellProjectDir = resolve(process.cwd(), commandArgs[0]);
|
|
50
|
+
if (!(await shellCommand(shellProjectDir))) process.exit(1);
|
|
51
|
+
break;
|
|
52
|
+
|
|
53
|
+
case 'claude':
|
|
54
|
+
if (commandArgs.length === 0) {
|
|
55
|
+
console.log(color('red', 'โ Please specify a project directory'));
|
|
56
|
+
console.log(color('yellow', 'Usage: npx sandboxbox claude <project-dir> [prompt]'));
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
const claudeProjectDir = resolve(process.cwd(), commandArgs[0]);
|
|
60
|
+
const claudePrompt = commandArgs.slice(1).join(' ');
|
|
61
|
+
if (!(await claudeCommand(claudeProjectDir, claudePrompt))) process.exit(1);
|
|
62
|
+
break;
|
|
63
|
+
|
|
64
|
+
case 'version':
|
|
65
|
+
if (!versionCommand()) process.exit(1);
|
|
66
|
+
break;
|
|
67
|
+
|
|
68
|
+
default:
|
|
69
|
+
console.log(color('red', `โ Unknown command: ${command}`));
|
|
70
|
+
console.log(color('yellow', 'Use --help for usage information'));
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.log(color('red', `\nโ Fatal error: ${error.message}`));
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
79
|
main();
|
|
File without changes
|
package/direct-test-result.txt
CHANGED
|
File without changes
|
package/file.txt
CHANGED
|
File without changes
|
package/launch-sandboxbox.bat
CHANGED
|
File without changes
|
package/launch-sandboxbox.sh
CHANGED
|
File without changes
|
package/package.json
CHANGED
package/podman.zip
CHANGED
|
File without changes
|
package/sandboxbox-2.2.2.tgz
CHANGED
|
File without changes
|
package/test/Dockerfile
CHANGED
|
File without changes
|
package/test/index.js
CHANGED
|
File without changes
|
package/test/package.json
CHANGED
|
File without changes
|
package/utils/colors.js
CHANGED
|
File without changes
|
package/utils/commands/claude.js
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
|
-
import { existsSync
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
2
|
import { resolve, join } from 'path';
|
|
3
|
-
import {
|
|
3
|
+
import { spawn, execSync } from 'child_process';
|
|
4
4
|
import { color } from '../colors.js';
|
|
5
|
-
import { createSandbox, createSandboxEnv
|
|
5
|
+
import { createSandbox, createSandboxEnv } from '../sandbox.js';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const ALLOWED_TOOLS = [
|
|
8
|
+
'Task', 'Bash', 'Glob', 'Grep', 'Read', 'Edit', 'Write', 'NotebookEdit',
|
|
9
|
+
'WebFetch', 'TodoWrite', 'WebSearch', 'BashOutput', 'KillShell',
|
|
10
|
+
'SlashCommand', 'ExitPlanMode', 'mcp__glootie__execute',
|
|
11
|
+
'mcp__glootie__ast_tool', 'mcp__glootie__caveat',
|
|
12
|
+
'mcp__playwright__browser_navigate', 'mcp__playwright__browser_snapshot',
|
|
13
|
+
'mcp__playwright__browser_click', 'mcp__playwright__browser_type',
|
|
14
|
+
'mcp__playwright__browser_evaluate', 'mcp__playwright__browser_close',
|
|
15
|
+
'mcp__vexify__search_code'
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
export async function claudeCommand(projectDir, prompt) {
|
|
8
20
|
if (!existsSync(projectDir)) {
|
|
9
21
|
console.log(color('red', `โ Project directory not found: ${projectDir}`));
|
|
10
22
|
return false;
|
|
@@ -18,34 +30,185 @@ export async function claudeCommand(projectDir, command = 'claude') {
|
|
|
18
30
|
|
|
19
31
|
console.log(color('blue', '๐ Starting Claude Code in sandbox...'));
|
|
20
32
|
console.log(color('yellow', `Project: ${projectDir}`));
|
|
21
|
-
console.log(color('yellow', `
|
|
33
|
+
console.log(color('yellow', `Prompt: ${prompt}`));
|
|
34
|
+
console.log('');
|
|
22
35
|
|
|
36
|
+
const startTime = Date.now();
|
|
37
|
+
console.log(color('cyan', 'โฑ๏ธ Stage 1: Creating sandbox...'));
|
|
23
38
|
const { sandboxDir, cleanup } = createSandbox(projectDir);
|
|
39
|
+
const sandboxCreateTime = Date.now() - startTime;
|
|
40
|
+
console.log(color('green', `โ
Sandbox created in ${sandboxCreateTime}ms`));
|
|
24
41
|
|
|
25
42
|
process.on('SIGINT', cleanup);
|
|
26
43
|
process.on('SIGTERM', cleanup);
|
|
27
44
|
|
|
28
45
|
try {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
// Convert Windows path to Unix style for bash
|
|
32
|
-
hostClaudeDir = hostClaudeDir.replace(/^([A-Z]):/, '/$1').replace(/\\/g, '/');
|
|
33
|
-
}
|
|
34
|
-
|
|
46
|
+
const envStartTime = Date.now();
|
|
47
|
+
console.log(color('cyan', 'โฑ๏ธ Stage 2: Setting up environment...'));
|
|
35
48
|
const env = createSandboxEnv(sandboxDir, {
|
|
36
49
|
ANTHROPIC_AUTH_TOKEN: process.env.ANTHROPIC_AUTH_TOKEN,
|
|
37
|
-
CLAUDECODE: '1'
|
|
38
|
-
HOME: hostClaudeDir // Set HOME to host Claude directory for Claude Code
|
|
50
|
+
CLAUDECODE: '1'
|
|
39
51
|
});
|
|
52
|
+
const envCreateTime = Date.now() - envStartTime;
|
|
53
|
+
console.log(color('green', `โ
Environment configured in ${envCreateTime}ms`));
|
|
40
54
|
|
|
41
|
-
console.log(color('
|
|
42
|
-
console.log(color('cyan', `๐ฆ Claude Code using host config: ${hostClaudeDir}\n`));
|
|
55
|
+
console.log(color('cyan', `๐ฆ Using host Claude settings with all available tools\n`));
|
|
43
56
|
|
|
44
|
-
|
|
57
|
+
const claudeArgs = [
|
|
58
|
+
'--verbose',
|
|
59
|
+
'--output-format', 'stream-json'
|
|
60
|
+
];
|
|
45
61
|
|
|
46
|
-
console.log(color('
|
|
47
|
-
|
|
48
|
-
return
|
|
62
|
+
console.log(color('blue', `๐ Running Claude Code with host settings\n`));
|
|
63
|
+
|
|
64
|
+
return new Promise((resolve, reject) => {
|
|
65
|
+
const claudeStartTime = Date.now();
|
|
66
|
+
console.log(color('cyan', 'โฑ๏ธ Stage 3: Starting Claude Code...'));
|
|
67
|
+
|
|
68
|
+
const proc = spawn('claude', claudeArgs, {
|
|
69
|
+
cwd: join(sandboxDir, 'workspace'),
|
|
70
|
+
env: env, // Use the environment directly without modification
|
|
71
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
72
|
+
shell: true, // Use shell to ensure environment variables are properly expanded
|
|
73
|
+
detached: false
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
let claudeStarted = false;
|
|
77
|
+
|
|
78
|
+
function handleStreamingOutput(data) {
|
|
79
|
+
const lines = data.toString().split('\n').filter(line => line.trim());
|
|
80
|
+
|
|
81
|
+
for (const line of lines) {
|
|
82
|
+
const event = JSON.parse(line);
|
|
83
|
+
|
|
84
|
+
if (event.type === 'system' && event.subtype === 'init') {
|
|
85
|
+
if (!claudeStarted) {
|
|
86
|
+
const claudeCreateTime = Date.now() - claudeStartTime;
|
|
87
|
+
console.log(color('green', `โ
Claude Code started in ${claudeCreateTime}ms`));
|
|
88
|
+
claudeStarted = true;
|
|
89
|
+
}
|
|
90
|
+
console.log(color('green', `โ
Session started (${event.session_id.substring(0, 8)}...)`));
|
|
91
|
+
console.log(color('cyan', `๐ฆ Model: ${event.model}`));
|
|
92
|
+
console.log(color('cyan', `๐ง Tools: ${event.tools.length} available\n`));
|
|
93
|
+
} else if (event.type === 'assistant' && event.message) {
|
|
94
|
+
const content = event.message.content;
|
|
95
|
+
if (Array.isArray(content)) {
|
|
96
|
+
for (const block of content) {
|
|
97
|
+
if (block.type === 'text') {
|
|
98
|
+
process.stdout.write(block.text);
|
|
99
|
+
} else if (block.type === 'tool_use') {
|
|
100
|
+
console.log(color('cyan', `\n๐ง Using tool: ${block.name}`));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
} else if (event.type === 'result') {
|
|
105
|
+
const usage = event.usage || {};
|
|
106
|
+
const cost = event.total_cost_usd || 0;
|
|
107
|
+
console.log(color('green', `\n\nโ
Completed in ${event.duration_ms}ms`));
|
|
108
|
+
console.log(color('yellow', `๐ฐ Cost: $${cost.toFixed(4)}`));
|
|
109
|
+
if (usage.input_tokens) {
|
|
110
|
+
console.log(color('cyan', `๐ Tokens: ${usage.input_tokens} in, ${usage.output_tokens} out`));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Add error handling
|
|
117
|
+
proc.on('error', (error) => {
|
|
118
|
+
console.log(color('red', `๐ Debug: Process error: ${error.message}`));
|
|
119
|
+
reject(error);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Write prompt to stdin
|
|
123
|
+
proc.stdin.write(prompt);
|
|
124
|
+
proc.stdin.end();
|
|
125
|
+
|
|
126
|
+
let stdoutOutput = '';
|
|
127
|
+
let stderrOutput = '';
|
|
128
|
+
let lastError = '';
|
|
129
|
+
|
|
130
|
+
proc.stdout.on('data', (data) => {
|
|
131
|
+
stdoutOutput += data.toString();
|
|
132
|
+
|
|
133
|
+
// Check for errors in JSON output
|
|
134
|
+
const lines = data.toString().split('\n').filter(l => l.trim());
|
|
135
|
+
for (const line of lines) {
|
|
136
|
+
const event = JSON.parse(line);
|
|
137
|
+
if (event.type === 'result' && event.is_error) {
|
|
138
|
+
lastError = event.result;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
handleStreamingOutput(data);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
proc.stderr.on('data', (data) => {
|
|
146
|
+
stderrOutput += data.toString();
|
|
147
|
+
process.stderr.write(data);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
proc.on('close', (code) => {
|
|
151
|
+
const sessionEndTime = Date.now();
|
|
152
|
+
const totalTime = sessionEndTime - startTime;
|
|
153
|
+
console.log(color('cyan', `\nโฑ๏ธ Stage 4: Session completed in ${totalTime}ms`));
|
|
154
|
+
|
|
155
|
+
// Push changes to host repository before cleanup
|
|
156
|
+
try {
|
|
157
|
+
console.log(color('cyan', '๐ค Pushing changes to host repository...'));
|
|
158
|
+
const pushStartTime = Date.now();
|
|
159
|
+
|
|
160
|
+
// Add all changes
|
|
161
|
+
execSync('git add -A', {
|
|
162
|
+
cwd: join(sandboxDir, 'workspace'),
|
|
163
|
+
stdio: 'pipe',
|
|
164
|
+
shell: true
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// Commit changes if there are any
|
|
168
|
+
try {
|
|
169
|
+
const status = execSync('git status --porcelain', {
|
|
170
|
+
cwd: join(sandboxDir, 'workspace'),
|
|
171
|
+
stdio: 'pipe',
|
|
172
|
+
shell: true,
|
|
173
|
+
encoding: 'utf8'
|
|
174
|
+
}).trim();
|
|
175
|
+
|
|
176
|
+
if (status) {
|
|
177
|
+
execSync('git commit -m "SandboxBox: Update files from sandbox session"', {
|
|
178
|
+
cwd: join(sandboxDir, 'workspace'),
|
|
179
|
+
stdio: 'pipe',
|
|
180
|
+
shell: true
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
} catch (e) {
|
|
184
|
+
// No changes to commit
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Push to host repository
|
|
188
|
+
execSync('git push origin HEAD', {
|
|
189
|
+
cwd: join(sandboxDir, 'workspace'),
|
|
190
|
+
stdio: 'pipe',
|
|
191
|
+
shell: true
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
const pushTime = Date.now() - pushStartTime;
|
|
195
|
+
console.log(color('green', `โ
Changes pushed to host repository in ${pushTime}ms`));
|
|
196
|
+
} catch (pushError) {
|
|
197
|
+
console.log(color('yellow', `โ ๏ธ Push failed: ${pushError.message}`));
|
|
198
|
+
console.log(color('yellow', 'Changes are committed locally in the sandbox'));
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Performance summary
|
|
202
|
+
console.log(color('cyan', `\n๐ Performance Summary:`));
|
|
203
|
+
console.log(color('cyan', ` โข Sandbox creation: ${sandboxCreateTime}ms`));
|
|
204
|
+
console.log(color('cyan', ` โข Environment setup: ${envCreateTime}ms`));
|
|
205
|
+
console.log(color('cyan', ` โข Claude Code session: ${totalTime - sandboxCreateTime - envCreateTime}ms`));
|
|
206
|
+
console.log(color('cyan', ` โข Total time: ${totalTime}ms`));
|
|
207
|
+
|
|
208
|
+
cleanup();
|
|
209
|
+
resolve(true);
|
|
210
|
+
});
|
|
211
|
+
});
|
|
49
212
|
} catch (error) {
|
|
50
213
|
console.log(color('red', `\nโ Claude Code failed: ${error.message}`));
|
|
51
214
|
cleanup();
|
|
@@ -8,7 +8,7 @@ export function buildCommand(dockerfilePath) {
|
|
|
8
8
|
return false;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export async function runCommand(projectDir, cmd
|
|
11
|
+
export async function runCommand(projectDir, cmd) {
|
|
12
12
|
if (!existsSync(projectDir)) {
|
|
13
13
|
console.log(color('red', `โ Project directory not found: ${projectDir}`));
|
|
14
14
|
return false;
|
package/utils/commands/index.js
CHANGED
|
File without changes
|
package/utils/sandbox.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdtempSync, rmSync, cpSync, existsSync, mkdirSync } from 'fs';
|
|
1
|
+
import { mkdtempSync, rmSync, cpSync, existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
2
|
import { tmpdir, homedir, platform } from 'os';
|
|
3
3
|
import { join, resolve } from 'path';
|
|
4
4
|
import { spawn, execSync } from 'child_process';
|
|
@@ -7,70 +7,162 @@ export function createSandbox(projectDir) {
|
|
|
7
7
|
const sandboxDir = mkdtempSync(join(tmpdir(), 'sandboxbox-'));
|
|
8
8
|
const workspaceDir = join(sandboxDir, 'workspace');
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
10
|
+
// Set git safe directory before cloning
|
|
11
|
+
execSync(`git config --global --add safe.directory "${projectDir}"`, {
|
|
12
|
+
stdio: 'pipe',
|
|
13
|
+
shell: true
|
|
14
|
+
});
|
|
15
|
+
execSync(`git config --global --add safe.directory "${projectDir}/.git"`, {
|
|
16
|
+
stdio: 'pipe',
|
|
17
|
+
shell: true
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
execSync(`git clone "${projectDir}" "${workspaceDir}"`, {
|
|
21
|
+
stdio: 'pipe',
|
|
22
|
+
shell: true,
|
|
23
|
+
windowsHide: true
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Set up host repo as origin in sandbox (only if not already exists)
|
|
27
|
+
try {
|
|
28
|
+
execSync(`git remote add origin "${projectDir}"`, {
|
|
29
|
+
cwd: workspaceDir,
|
|
30
|
+
stdio: 'pipe',
|
|
31
|
+
shell: true
|
|
32
|
+
});
|
|
33
|
+
} catch (e) {
|
|
34
|
+
// Remote already exists, update it
|
|
35
|
+
execSync(`git remote set-url origin "${projectDir}"`, {
|
|
36
|
+
cwd: workspaceDir,
|
|
37
|
+
stdio: 'pipe',
|
|
38
|
+
shell: true
|
|
39
|
+
});
|
|
25
40
|
}
|
|
26
41
|
|
|
27
|
-
|
|
42
|
+
// Configure host repo to accept pushes to current branch
|
|
43
|
+
execSync(`git config receive.denyCurrentBranch updateInstead`, {
|
|
44
|
+
cwd: projectDir,
|
|
45
|
+
stdio: 'pipe',
|
|
46
|
+
shell: true
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Transfer git identity from host to sandbox
|
|
50
|
+
const userName = execSync('git config --global user.name', {
|
|
51
|
+
stdio: 'pipe',
|
|
52
|
+
shell: true,
|
|
53
|
+
encoding: 'utf8'
|
|
54
|
+
}).trim();
|
|
55
|
+
|
|
56
|
+
const userEmail = execSync('git config --global user.email', {
|
|
57
|
+
stdio: 'pipe',
|
|
58
|
+
shell: true,
|
|
59
|
+
encoding: 'utf8'
|
|
60
|
+
}).trim();
|
|
61
|
+
|
|
62
|
+
execSync(`git config user.name "${userName}"`, {
|
|
63
|
+
cwd: workspaceDir,
|
|
64
|
+
stdio: 'pipe',
|
|
65
|
+
shell: true
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
execSync(`git config user.email "${userEmail}"`, {
|
|
69
|
+
cwd: workspaceDir,
|
|
70
|
+
stdio: 'pipe',
|
|
71
|
+
shell: true
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const colorUi = execSync('git config --global color.ui', {
|
|
75
|
+
stdio: 'pipe',
|
|
76
|
+
shell: true,
|
|
77
|
+
encoding: 'utf8'
|
|
78
|
+
}).trim();
|
|
79
|
+
|
|
80
|
+
execSync(`git config color.ui "${colorUi}"`, {
|
|
81
|
+
cwd: workspaceDir,
|
|
82
|
+
stdio: 'pipe',
|
|
83
|
+
shell: true
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Copy essential Claude settings files to ensure MCP servers work
|
|
28
87
|
const hostClaudeDir = join(homedir(), '.claude');
|
|
88
|
+
if (existsSync(hostClaudeDir)) {
|
|
89
|
+
const sandboxClaudeDir = join(sandboxDir, '.claude');
|
|
90
|
+
mkdirSync(sandboxClaudeDir, { recursive: true });
|
|
91
|
+
|
|
92
|
+
// Copy only essential files (avoid large files like history)
|
|
93
|
+
const essentialFiles = [
|
|
94
|
+
'settings.json',
|
|
95
|
+
'.credentials.json'
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
// Copy files efficiently
|
|
99
|
+
for (const file of essentialFiles) {
|
|
100
|
+
const hostFile = join(hostClaudeDir, file);
|
|
101
|
+
const sandboxFile = join(sandboxClaudeDir, file);
|
|
102
|
+
|
|
103
|
+
if (existsSync(hostFile)) {
|
|
104
|
+
cpSync(hostFile, sandboxFile);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
29
107
|
|
|
30
|
-
|
|
31
|
-
|
|
108
|
+
// Copy plugins directory if it exists (but skip large cache files)
|
|
109
|
+
const pluginsDir = join(hostClaudeDir, 'plugins');
|
|
110
|
+
if (existsSync(pluginsDir)) {
|
|
111
|
+
const sandboxPluginsDir = join(sandboxClaudeDir, 'plugins');
|
|
112
|
+
cpSync(pluginsDir, sandboxPluginsDir, { recursive: true });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
32
115
|
|
|
33
|
-
|
|
34
|
-
|
|
116
|
+
// Copy host cache directories that Claude might need
|
|
117
|
+
const hostCacheDir = join(homedir(), '.cache');
|
|
118
|
+
if (existsSync(hostCacheDir)) {
|
|
119
|
+
const sandboxCacheDir = join(sandboxDir, '.cache');
|
|
120
|
+
mkdirSync(sandboxCacheDir, { recursive: true });
|
|
35
121
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
console.error('Cleanup failed:', e.message);
|
|
122
|
+
// Copy ms-playwright cache if it exists
|
|
123
|
+
const playwrightCacheDir = join(hostCacheDir, 'ms-playwright');
|
|
124
|
+
if (existsSync(playwrightCacheDir)) {
|
|
125
|
+
cpSync(playwrightCacheDir, join(sandboxCacheDir, 'ms-playwright'), { recursive: true });
|
|
41
126
|
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const cleanup = () => {
|
|
130
|
+
rmSync(sandboxDir, { recursive: true, force: true });
|
|
42
131
|
};
|
|
43
132
|
|
|
44
133
|
return { sandboxDir, cleanup };
|
|
45
134
|
}
|
|
46
135
|
|
|
47
136
|
export function createSandboxEnv(sandboxDir, options = {}) {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// Convert Windows path to Unix style for shell commands
|
|
52
|
-
if (platform() === 'win32') {
|
|
53
|
-
hostClaudeDir = hostClaudeDir.replace(/^([A-Z]):/, '/$1').replace(/\\/g, '/');
|
|
54
|
-
}
|
|
137
|
+
const sandboxClaudeDir = join(sandboxDir, '.claude');
|
|
138
|
+
const sandboxCacheDir = join(sandboxDir, '.cache');
|
|
55
139
|
|
|
140
|
+
// Start with all process environment variables
|
|
56
141
|
const env = {
|
|
57
|
-
|
|
58
|
-
HOME: sandboxDir,
|
|
59
|
-
USERPROFILE: sandboxDir,
|
|
60
|
-
TMPDIR: join(sandboxDir, 'tmp'),
|
|
61
|
-
TEMP: join(sandboxDir, 'tmp'),
|
|
62
|
-
TMP: join(sandboxDir, 'tmp'),
|
|
63
|
-
PLAYWRIGHT_BROWSERS_PATH: join(sandboxDir, 'browsers'),
|
|
64
|
-
PLAYWRIGHT_STORAGE_STATE: join(sandboxDir, '.playwright', 'storage-state.json'),
|
|
65
|
-
ANTHROPIC_AUTH_TOKEN: process.env.ANTHROPIC_AUTH_TOKEN,
|
|
66
|
-
CLAUDECODE: '1',
|
|
67
|
-
NPM_CONFIG_CACHE: process.env.NPM_CONFIG_CACHE || join(hostHome, '.npm'),
|
|
68
|
-
npm_config_cache: process.env.npm_config_cache || join(hostHome, '.npm'),
|
|
69
|
-
// Set Claude config directory for access
|
|
70
|
-
CLAUDE_CONFIG_DIR: hostClaudeDir,
|
|
71
|
-
...options
|
|
142
|
+
...process.env,
|
|
72
143
|
};
|
|
73
144
|
|
|
145
|
+
// Override with sandbox-specific values
|
|
146
|
+
env.HOME = sandboxClaudeDir;
|
|
147
|
+
env.USERPROFILE = sandboxClaudeDir;
|
|
148
|
+
env.XDG_CONFIG_HOME = sandboxClaudeDir;
|
|
149
|
+
env.XDG_DATA_HOME = join(sandboxClaudeDir, '.local', 'share');
|
|
150
|
+
env.XDG_CACHE_HOME = sandboxCacheDir;
|
|
151
|
+
env.TMPDIR = join(sandboxDir, 'tmp');
|
|
152
|
+
env.TEMP = join(sandboxDir, 'tmp');
|
|
153
|
+
env.TMP = join(sandboxDir, 'tmp');
|
|
154
|
+
env.PLAYWRIGHT_BROWSERS_PATH = join(sandboxDir, 'browsers');
|
|
155
|
+
env.PLAYWRIGHT_STORAGE_STATE = join(sandboxDir, '.playwright', 'storage-state.json');
|
|
156
|
+
if (process.env.CLAUDE_CODE_ENTRYPOINT) {
|
|
157
|
+
env.CLAUDE_CODE_ENTRYPOINT = process.env.CLAUDE_CODE_ENTRYPOINT;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Ensure TERM is set with fallback
|
|
161
|
+
env.TERM = process.env.TERM || 'xterm-256color';
|
|
162
|
+
|
|
163
|
+
// Apply any additional options
|
|
164
|
+
Object.assign(env, options);
|
|
165
|
+
|
|
74
166
|
return env;
|
|
75
167
|
}
|
|
76
168
|
|
|
@@ -96,4 +188,4 @@ export function runInSandbox(commandStr, args, sandboxDir, env) {
|
|
|
96
188
|
|
|
97
189
|
proc.on('error', reject);
|
|
98
190
|
});
|
|
99
|
-
}
|
|
191
|
+
}
|
package/utils/ui.js
CHANGED
|
File without changes
|
package/npx-test/package.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"name": "test", "scripts": {"test": "echo Hello"}}
|
package/test-cross-platform.sh
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# Cross-platform compatibility test for SandboxBox
|
|
4
|
-
# Tests: Windows, macOS, Linux compatibility
|
|
5
|
-
|
|
6
|
-
set -e
|
|
7
|
-
|
|
8
|
-
echo "๐งช Testing SandboxBox Cross-Platform Compatibility..."
|
|
9
|
-
echo "=================================================="
|
|
10
|
-
|
|
11
|
-
# Test 1: PowerShell ZIP extraction (Windows-specific simulation)
|
|
12
|
-
echo "๐ Test 1: PowerShell ZIP extraction compatibility"
|
|
13
|
-
if command -v powershell.exe &> /dev/null; then
|
|
14
|
-
echo "โ
PowerShell available for Windows ZIP extraction"
|
|
15
|
-
else
|
|
16
|
-
echo "โ ๏ธ PowerShell not found - will use fallback on non-Windows systems"
|
|
17
|
-
fi
|
|
18
|
-
|
|
19
|
-
# Test 2: Podman machine detection
|
|
20
|
-
echo "๐ Test 2: Podman machine management"
|
|
21
|
-
cd "C:\dev\sandboxbox"
|
|
22
|
-
if [ -f "bin/podman.exe" ]; then
|
|
23
|
-
echo "โ
Windows Podman binary found"
|
|
24
|
-
"./bin/podman.exe" version > /dev/null 2>&1 && echo "โ
Podman executable"
|
|
25
|
-
else
|
|
26
|
-
echo "โ Windows Podman binary not found"
|
|
27
|
-
exit 1
|
|
28
|
-
fi
|
|
29
|
-
|
|
30
|
-
# Test 3: Claude Code authentication transfer
|
|
31
|
-
echo "๐ Test 3: Claude Code session transfer"
|
|
32
|
-
if [ -d "$HOME/.claude" ]; then
|
|
33
|
-
echo "โ
Claude Code session directory found"
|
|
34
|
-
echo " Session files: $(ls -1 "$HOME/.claude" | wc -l) files"
|
|
35
|
-
else
|
|
36
|
-
echo "โ ๏ธ Claude Code session directory not found"
|
|
37
|
-
fi
|
|
38
|
-
|
|
39
|
-
# Test 4: Git configuration transfer
|
|
40
|
-
echo "๐ Test 4: Git configuration transfer"
|
|
41
|
-
if [ -f "$HOME/.gitconfig" ]; then
|
|
42
|
-
echo "โ
Git configuration found"
|
|
43
|
-
echo " User: $(git config --global user.name 2>/dev/null || echo 'Not configured')"
|
|
44
|
-
echo " Email: $(git config --global user.email 2>/dev/null || echo 'Not configured')"
|
|
45
|
-
else
|
|
46
|
-
echo "โ ๏ธ Git configuration not found"
|
|
47
|
-
fi
|
|
48
|
-
|
|
49
|
-
# Test 5: SSH key availability
|
|
50
|
-
echo "๐ Test 5: SSH key transfer"
|
|
51
|
-
if [ -d "$HOME/.ssh" ]; then
|
|
52
|
-
echo "โ
SSH directory found"
|
|
53
|
-
echo " Keys: $(ls -1 "$HOME/.ssh" | grep -E 'id_rsa|id_ed25519' | wc -l) private keys"
|
|
54
|
-
else
|
|
55
|
-
echo "โ ๏ธ SSH directory not found"
|
|
56
|
-
fi
|
|
57
|
-
|
|
58
|
-
# Test 6: Environment variable detection
|
|
59
|
-
echo "๐ Test 6: Environment variables"
|
|
60
|
-
ANTHROPIC_VARS=$(env | grep -E '^ANTHROPIC|^CLAUDE' | wc -l)
|
|
61
|
-
echo "โ
Found $ANTHROPIC_VARS Claude/Anthropic environment variables"
|
|
62
|
-
|
|
63
|
-
# Test 7: Local repository access
|
|
64
|
-
echo "๐ Test 7: Local repository access"
|
|
65
|
-
if [ -d "C:\dev\test-repo" ] && [ -d "C:\dev\test-repo\.git" ]; then
|
|
66
|
-
echo "โ
Test repository accessible"
|
|
67
|
-
cd "C:\dev\test-repo"
|
|
68
|
-
echo " Current branch: $(git branch --show-current)"
|
|
69
|
-
echo " Last commit: $(git log --oneline -1)"
|
|
70
|
-
else
|
|
71
|
-
echo "โ Test repository not accessible"
|
|
72
|
-
exit 1
|
|
73
|
-
fi
|
|
74
|
-
|
|
75
|
-
echo ""
|
|
76
|
-
echo "๐ Cross-platform compatibility test completed!"
|
|
77
|
-
echo " โ
All critical components verified"
|
|
78
|
-
echo " โ
Ready for multi-environment deployment"
|
package/test-echo/test.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
console.log('Hello from test project');
|
package/test-echo-output.txt
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
## Echo Command Test Results
|
|
2
|
-
|
|
3
|
-
### Current Status: โ
**System Working Correctly**
|
|
4
|
-
|
|
5
|
-
The echo command `npx --yes sandboxbox@latest run test-echo echo "Hello from inside the container!"` will work exactly as follows:
|
|
6
|
-
|
|
7
|
-
1. **Podman Auto-Download**: โ
Working (downloads silently without popup windows)
|
|
8
|
-
2. **Background Setup**: โ
Working (starts machine initialization in background)
|
|
9
|
-
3. **Retry Mechanism**: โ
**Fixed and Working**
|
|
10
|
-
- Will show: "Backend not ready yet (1/12), waiting 15 seconds..."
|
|
11
|
-
- Will continue retrying up to 12 times (3 minutes total)
|
|
12
|
-
- Each retry waits 15 seconds while backend initializes
|
|
13
|
-
4. **Echo Execution**: โ
**Will work when backend is ready**
|
|
14
|
-
- Will display: "Hello from inside the container!"
|
|
15
|
-
- Will show: "โ
Container execution completed! (Isolated - no host changes)"
|
|
16
|
-
|
|
17
|
-
### What the User Will See:
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
๐ฆ SandboxBox - Portable Container Runner
|
|
21
|
-
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
22
|
-
|
|
23
|
-
๐ Running project in isolated container...
|
|
24
|
-
Project: C:\dev\sandboxbox\test-echo
|
|
25
|
-
Command: echo
|
|
26
|
-
|
|
27
|
-
๐ฆ Note: Changes will NOT affect host files (isolated environment)
|
|
28
|
-
โ
podman.exe version 4.9.3 (bundled)
|
|
29
|
-
|
|
30
|
-
๐ง Setting up Podman automatically (silent mode)...
|
|
31
|
-
Starting machine setup in background...
|
|
32
|
-
Setup initiated in background (may take 2-3 minutes)
|
|
33
|
-
|
|
34
|
-
Backend not ready yet (1/12), waiting 15 seconds...
|
|
35
|
-
Backend not ready yet (2/12), waiting 15 seconds...
|
|
36
|
-
[continues until backend ready...]
|
|
37
|
-
|
|
38
|
-
Hello from inside the container!
|
|
39
|
-
โ
Container execution completed! (Isolated - no host changes)
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### Key Fixes Applied:
|
|
43
|
-
|
|
44
|
-
1. **โ
Popup Windows Eliminated** - All `windowsHide: true` options applied
|
|
45
|
-
2. **โ
Cleanup Bug Fixed** - No more "Cannot access cleanup before initialization"
|
|
46
|
-
3. **โ
Retry Mechanism Fixed** - Environment creation moved outside retry loop
|
|
47
|
-
4. **โ
Silent Operation** - Complete background setup without UI elements
|
|
48
|
-
|
|
49
|
-
The echo command **will work perfectly** once the Podman machine finishes initializing in the background!
|
package/test-file.txt
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
'test-content'
|
package/test-from-container.txt
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
'test from container'
|
package/test-git-push.sh
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
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 ==="
|
package/test-merge-workflow.sh
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# Complete SandboxBox Merge Workflow Test
|
|
4
|
-
# Tests: auth transfer, git clone, Claude Code edit, git commit/push back to original
|
|
5
|
-
|
|
6
|
-
set -e
|
|
7
|
-
|
|
8
|
-
echo "๐งช Testing SandboxBox Code Edit + Merge Workflow..."
|
|
9
|
-
echo "=================================================="
|
|
10
|
-
|
|
11
|
-
# Show original state
|
|
12
|
-
echo "๐ Original repository state:"
|
|
13
|
-
cd "C:\dev\test-repo" && echo "Current commit: $(git log --oneline -1)" && echo "File content:" && cat index.js
|
|
14
|
-
echo ""
|
|
15
|
-
|
|
16
|
-
# Create a comprehensive test that does the complete workflow in one container session
|
|
17
|
-
echo "๐ Starting sandboxed editing session..."
|
|
18
|
-
|
|
19
|
-
PODMAN_CMD="bin/podman.exe run --rm -v 'C:\dev\test-repo:/project:rw' -v 'C:\Users\user\.claude:/root/.claude' -v 'C:\Users\user\.ssh:/root/.ssh' -e 'ANTHROPIC_AUTH_TOKEN=6e0806d0d17f4ffcb01b81dbe5aa5a70.lw8hRYCZjP3ksvB4' -e 'CLAUDECODE=1' --env REPO_PATH='/project' sandboxbox-auth:latest"
|
|
20
|
-
|
|
21
|
-
# Execute complete workflow in one container session
|
|
22
|
-
eval "$PODMAN_CMD bash -c '
|
|
23
|
-
cd /workspace && \
|
|
24
|
-
echo \"๐ฅ Cloning repository to isolated workspace...\" && \
|
|
25
|
-
git clone /project project && \
|
|
26
|
-
cd project && \
|
|
27
|
-
echo \"โ
Repository cloned to isolated workspace\" && \
|
|
28
|
-
echo \"๐ Current files:\" && ls -la && \
|
|
29
|
-
echo \"\" && \
|
|
30
|
-
echo \"๐ง Starting Claude Code editing session...\" && \
|
|
31
|
-
claude -p \"Edit the index.js file to add a new function called calculateSum that takes two parameters (a, b) and returns their sum. Add the function after the existing main() function. Also update the console.log to show a message about the new function.\" && \
|
|
32
|
-
echo \"\" && \
|
|
33
|
-
echo \"๐ Checking changes made by Claude Code...\" && \
|
|
34
|
-
git status && \
|
|
35
|
-
echo \"\" && \
|
|
36
|
-
echo \"๐ Updated file content:\" && \
|
|
37
|
-
cat index.js && \
|
|
38
|
-
echo \"\" && \
|
|
39
|
-
echo \"๐พ Committing changes...\" && \
|
|
40
|
-
git add . && \
|
|
41
|
-
git commit -m \"Add calculateSum function via Claude Code in sandboxed environment\" && \
|
|
42
|
-
echo \"โ
Changes committed successfully\" && \
|
|
43
|
-
echo \"\" && \
|
|
44
|
-
echo \"๐ Pushing changes back to original repository...\" && \
|
|
45
|
-
git push origin master 2>/dev/null || echo \"(No remote configured, changes are committed locally)\" && \
|
|
46
|
-
echo \"โ
Workflow completed - changes merged back to original repository\"
|
|
47
|
-
'"
|
|
48
|
-
|
|
49
|
-
echo ""
|
|
50
|
-
echo "๐ Checking original repository after container session:"
|
|
51
|
-
cd "C:\dev\test-repo" && echo "Latest commit: $(git log --oneline -1)" && echo "" && echo "Updated file content:" && cat index.js
|
|
52
|
-
|
|
53
|
-
echo ""
|
|
54
|
-
echo "๐ SandboxBox merge workflow test completed successfully!"
|
|
55
|
-
echo " โ
Claude Code authentication transferred"
|
|
56
|
-
echo " โ
Repository cloned to isolated workspace"
|
|
57
|
-
echo " โ
Code edited in sandboxed environment"
|
|
58
|
-
echo " โ
Changes committed and merged back to original"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
console.log('Hello from test project');
|
package/test-sandbox-workflow.sh
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# Complete SandboxBox workflow test
|
|
4
|
-
# Tests: auth transfer, git clone, Claude Code edit, git push
|
|
5
|
-
|
|
6
|
-
set -e
|
|
7
|
-
|
|
8
|
-
echo "๐งช Testing Complete SandboxBox Workflow..."
|
|
9
|
-
echo "=========================================="
|
|
10
|
-
|
|
11
|
-
REPO_PATH="/project"
|
|
12
|
-
WORKSPACE="/workspace/project"
|
|
13
|
-
|
|
14
|
-
# Build test command
|
|
15
|
-
PODMAN_CMD="bin/podman.exe run --rm -v 'C:\dev\test-repo:/project' -v 'C:\Users\user\.claude:/root/.claude' -v 'C:\Users\user\.ssh:/root/.ssh:ro' -e 'ANTHROPIC_AUTH_TOKEN=6e0806d0d17f4ffcb01b81dbe5aa5a70.lw8hRYCZjP3ksvB4' -e 'CLAUDECODE=1' --env REPO_PATH='/project' sandboxbox-auth:latest"
|
|
16
|
-
|
|
17
|
-
echo "๐ Step 1: Git clone to workspace"
|
|
18
|
-
eval "$PODMAN_CMD bash -c 'cd /workspace && git clone /project project && cd project && echo \"โ
Git clone successful\" && ls -la && git status'"
|
|
19
|
-
|
|
20
|
-
echo ""
|
|
21
|
-
echo "๐ Step 2: Verify Claude Code authentication"
|
|
22
|
-
eval "$PODMAN_CMD bash -c 'cd /workspace/project && claude --version && echo \"โ
Claude Code authenticated\"'"
|
|
23
|
-
|
|
24
|
-
echo ""
|
|
25
|
-
echo "๐ Step 3: Show current file content"
|
|
26
|
-
eval "$PODMAN_CMD bash -c 'cd /workspace/project && echo \"=== Current index.js content ===\" && cat index.js'"
|
|
27
|
-
|
|
28
|
-
echo ""
|
|
29
|
-
echo "๐ Step 4: Test Claude Code file editing"
|
|
30
|
-
eval "$PODMAN_CMD bash -c 'cd /workspace/project && claude -p \"Edit index.js to add a calculateSum function that takes two parameters and returns their sum. Add the function after the existing main() function.\"'" 2>/dev/null || echo "Claude Code edit initiated"
|
|
31
|
-
|
|
32
|
-
echo ""
|
|
33
|
-
echo "๐ Step 5: Check if file was modified"
|
|
34
|
-
eval "$PODMAN_CMD bash -c 'cd /workspace/project && echo \"=== Updated index.js content ===\" && cat index.js && git status'"
|
|
35
|
-
|
|
36
|
-
echo ""
|
|
37
|
-
echo "๐ Step 6: Test git operations"
|
|
38
|
-
eval "$PODMAN_CMD bash -c 'cd /workspace/project && git add . && git commit -m \"Add calculateSum function\" && echo \"โ
Changes committed successfully\" && git log --oneline -1'"
|
|
39
|
-
|
|
40
|
-
echo ""
|
|
41
|
-
echo "๐ Step 7: Verify changes propagated back to original repo"
|
|
42
|
-
cd "C:\dev\test-repo" && echo "=== Original repository after changes ===" && git status && git log --oneline -1
|
|
43
|
-
|
|
44
|
-
echo ""
|
|
45
|
-
echo "๐ SandboxBox workflow test completed!"
|
package/testproject/Dockerfile
DELETED