sandboxbox 3.0.48 → 3.0.49
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/package/CLAUDE.md +200 -0
- package/package/package/Dockerfile +95 -0
- package/package/package/README.md +242 -0
- package/package/package/claude-settings.json +85 -0
- package/package/package/cli.js +90 -0
- package/package/package/package.json +39 -0
- package/package/package/sandboxbox-3.0.45.tgz +0 -0
- package/package/package/sandboxbox-settings.json +40 -0
- package/package/package/test.txt +1 -0
- package/package/package/utils/claude-optimizer.js +129 -0
- package/package/package/utils/colors.js +15 -0
- package/package/package/utils/commands/claude.js +501 -0
- package/package/package/utils/commands/container.js +60 -0
- package/package/package/utils/commands/index.js +23 -0
- package/package/package/utils/sandbox.js +341 -0
- package/package/package/utils/system-optimizer.js +231 -0
- package/package/package/utils/ui.js +38 -0
- package/package/package.json +1 -1
- package/package/sandboxbox-3.0.46.tgz +0 -0
- package/package/utils/commands/claude.js +7 -6
- package/package.json +1 -1
- package/sandboxbox-3.0.48.tgz +0 -0
- package/sandboxbox-settings.json +16 -1
|
@@ -0,0 +1,90 @@
|
|
|
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> [prompt] [--host] [--headless]'));
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Parse flags from command args
|
|
61
|
+
const claudeArgs = commandArgs.slice(1);
|
|
62
|
+
const flags = {
|
|
63
|
+
useHostSettings: claudeArgs.includes('--host'),
|
|
64
|
+
headlessMode: claudeArgs.includes('--headless')
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// Remove flags from prompt
|
|
68
|
+
const promptArgs = claudeArgs.filter(arg => arg !== '--host' && arg !== '--headless');
|
|
69
|
+
const claudeProjectDir = resolve(process.cwd(), commandArgs[0]);
|
|
70
|
+
const claudePrompt = promptArgs.join(' ');
|
|
71
|
+
|
|
72
|
+
if (!(await claudeCommand(claudeProjectDir, claudePrompt, flags))) process.exit(1);
|
|
73
|
+
break;
|
|
74
|
+
|
|
75
|
+
case 'version':
|
|
76
|
+
if (!versionCommand()) process.exit(1);
|
|
77
|
+
break;
|
|
78
|
+
|
|
79
|
+
default:
|
|
80
|
+
console.log(color('red', `❌ Unknown command: ${command}`));
|
|
81
|
+
console.log(color('yellow', 'Use --help for usage information'));
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.log(color('red', `\n❌ Fatal error: ${error.message}`));
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
main();
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sandboxbox",
|
|
3
|
+
"version": "3.0.46",
|
|
4
|
+
"description": "Lightweight process containment sandbox for CLI tools - Playwright, Claude Code, and more. Pure Node.js, no dependencies.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "cli.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"sandboxbox": "cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node cli.js"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"sandbox",
|
|
15
|
+
"process-isolation",
|
|
16
|
+
"playwright",
|
|
17
|
+
"claude-code",
|
|
18
|
+
"cli-tools",
|
|
19
|
+
"environment-isolation",
|
|
20
|
+
"cross-platform",
|
|
21
|
+
"windows",
|
|
22
|
+
"macos",
|
|
23
|
+
"linux",
|
|
24
|
+
"portable",
|
|
25
|
+
"npm",
|
|
26
|
+
"npx"
|
|
27
|
+
],
|
|
28
|
+
"author": "",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"dependencies": {},
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/AnEntrypoint/sandboxbox.git"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://github.com/AnEntrypoint/sandboxbox#readme",
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/AnEntrypoint/sandboxbox/issues"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://schemas.modelcontextprotocol.io/0.1.0/mcp.json",
|
|
3
|
+
"pluginTimeout": 5000,
|
|
4
|
+
"alwaysThinkingEnabled": false,
|
|
5
|
+
"mcpServers": {
|
|
6
|
+
"glootie": {
|
|
7
|
+
"command": "npx",
|
|
8
|
+
"args": ["-y", "mcp-glootie@latest"]
|
|
9
|
+
},
|
|
10
|
+
"playwright": {
|
|
11
|
+
"command": "npx",
|
|
12
|
+
"args": ["-y", "@playwright/mcp@latest"]
|
|
13
|
+
},
|
|
14
|
+
"vexify": {
|
|
15
|
+
"command": "npx",
|
|
16
|
+
"args": ["-y", "vexify@latest", "mcp"]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"hooks": {
|
|
20
|
+
"SessionStart": [
|
|
21
|
+
{
|
|
22
|
+
"matcher": "*",
|
|
23
|
+
"hooks": [
|
|
24
|
+
{
|
|
25
|
+
"type": "command",
|
|
26
|
+
"command": "curl https://raw.githubusercontent.com/AnEntrypoint/glootie-cc/refs/heads/master/start.md"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"type": "command",
|
|
30
|
+
"command": "npx -y mcp-thorns@latest"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"type": "command",
|
|
34
|
+
"command": "npx -y wfgy@latest hook"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This is a test file created by Claude Code.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join, dirname } from 'path';
|
|
3
|
+
|
|
4
|
+
export class ClaudeOptimizer {
|
|
5
|
+
constructor(sandboxDir) {
|
|
6
|
+
this.sandboxDir = sandboxDir;
|
|
7
|
+
this.claudeDir = join(sandboxDir, '.claude');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Optimize Claude settings for faster startup
|
|
11
|
+
optimizeSettings() {
|
|
12
|
+
const settingsPath = join(this.claudeDir, 'settings.json');
|
|
13
|
+
|
|
14
|
+
// Load existing settings or create optimized defaults
|
|
15
|
+
let settings = {};
|
|
16
|
+
if (existsSync(settingsPath)) {
|
|
17
|
+
try {
|
|
18
|
+
settings = JSON.parse(require('fs').readFileSync(settingsPath, 'utf8'));
|
|
19
|
+
} catch (e) {
|
|
20
|
+
// Silently create default settings
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Apply startup optimizations - preserve bundled hooks!
|
|
25
|
+
const optimizedSettings = {
|
|
26
|
+
...settings,
|
|
27
|
+
// Reduce plugin timeouts
|
|
28
|
+
pluginTimeout: settings.pluginTimeout || 5000,
|
|
29
|
+
// Disable unnecessary features for faster startup
|
|
30
|
+
alwaysThinkingEnabled: settings.alwaysThinkingEnabled || false,
|
|
31
|
+
// Optimize plugin loading - preserve existing plugins
|
|
32
|
+
enabledPlugins: {
|
|
33
|
+
...settings.enabledPlugins,
|
|
34
|
+
// Only enable essential plugins for performance
|
|
35
|
+
'glootie-cc@anentrypoint-plugins': true
|
|
36
|
+
}
|
|
37
|
+
// Note: DO NOT override hooks - preserve bundled settings hooks!
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Ensure directory exists
|
|
41
|
+
mkdirSync(dirname(settingsPath), { recursive: true });
|
|
42
|
+
|
|
43
|
+
// Write optimized settings
|
|
44
|
+
writeFileSync(settingsPath, JSON.stringify(optimizedSettings, null, 2));
|
|
45
|
+
|
|
46
|
+
return optimizedSettings;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Pre-warm plugin connections
|
|
50
|
+
async prewarmPlugins() {
|
|
51
|
+
|
|
52
|
+
const prewarmScript = `
|
|
53
|
+
# Pre-warm script for Claude plugins
|
|
54
|
+
echo "Pre-warming plugin connections..."
|
|
55
|
+
|
|
56
|
+
# Set environment for faster plugin discovery
|
|
57
|
+
export NODE_OPTIONS="--max-old-space-size=2048"
|
|
58
|
+
export CLAUDE_PLUGIN_TIMEOUT=5000
|
|
59
|
+
|
|
60
|
+
# Pre-warm glootie plugin
|
|
61
|
+
if command -v npx >/dev/null 2>&1; then
|
|
62
|
+
timeout 3s npx -y glootie-cc@anentrypoint-plugins --version >/dev/null 2>&1 &
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
echo "Plugin pre-warming complete"
|
|
66
|
+
`;
|
|
67
|
+
|
|
68
|
+
const scriptPath = join(this.sandboxDir, '.claude', 'prewarm.sh');
|
|
69
|
+
writeFileSync(scriptPath, prewarmScript);
|
|
70
|
+
|
|
71
|
+
return scriptPath;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Create optimized environment for Claude
|
|
75
|
+
createOptimizedEnv(baseEnv = {}) {
|
|
76
|
+
return {
|
|
77
|
+
...baseEnv,
|
|
78
|
+
// Performance optimizations
|
|
79
|
+
NODE_OPTIONS: "--max-old-space-size=2048",
|
|
80
|
+
CLAUDE_PLUGIN_TIMEOUT: "5000",
|
|
81
|
+
CLAUDE_CACHE_DIR: join(this.sandboxDir, '.cache', 'claude'),
|
|
82
|
+
// Network optimizations
|
|
83
|
+
NODE_TLS_REJECT_UNAUTHORIZED: "0",
|
|
84
|
+
// Plugin optimizations
|
|
85
|
+
MCP_TIMEOUT: "5000",
|
|
86
|
+
MCP_CONNECTION_TIMEOUT: "3000",
|
|
87
|
+
// Fast startup flags
|
|
88
|
+
CLAUDE_FAST_STARTUP: "1",
|
|
89
|
+
CLAUDE_MINIMAL_MODE: "1"
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Generate startup timing profile
|
|
94
|
+
async profileStartup(claudeCommand) {
|
|
95
|
+
console.log('📊 Profiling Claude startup...');
|
|
96
|
+
|
|
97
|
+
const profileScript = `
|
|
98
|
+
#!/bin/bash
|
|
99
|
+
echo "Starting Claude startup profile..."
|
|
100
|
+
start_time=$(date +%s%3N)
|
|
101
|
+
|
|
102
|
+
# Run Claude with timing
|
|
103
|
+
timeout 30s ${claudeCommand} --help >/dev/null 2>&1 &
|
|
104
|
+
claude_pid=$!
|
|
105
|
+
|
|
106
|
+
# Monitor startup progress
|
|
107
|
+
while kill -0 $claude_pid 2>/dev/null; do
|
|
108
|
+
current_time=$(date +%s%3N)
|
|
109
|
+
elapsed=$((current_time - start_time))
|
|
110
|
+
|
|
111
|
+
if [ $elapsed -gt 10000 ]; then
|
|
112
|
+
echo "⚠️ Startup taking longer than 10s..."
|
|
113
|
+
kill $claude_pid 2>/dev/null
|
|
114
|
+
break
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
sleep 0.5
|
|
118
|
+
done
|
|
119
|
+
|
|
120
|
+
wait $claude_pid
|
|
121
|
+
end_time=$(date +%s%3N)
|
|
122
|
+
total_time=$((end_time - start_time))
|
|
123
|
+
|
|
124
|
+
echo "Claude startup completed in ${total_time}ms"
|
|
125
|
+
`;
|
|
126
|
+
|
|
127
|
+
return profileScript;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Color utilities for CLI output
|
|
2
|
+
export const colors = {
|
|
3
|
+
red: '\x1b[31m',
|
|
4
|
+
green: '\x1b[32m',
|
|
5
|
+
yellow: '\x1b[33m',
|
|
6
|
+
blue: '\x1b[34m',
|
|
7
|
+
magenta: '\x1b[35m',
|
|
8
|
+
cyan: '\x1b[36m',
|
|
9
|
+
white: '\x1b[37m',
|
|
10
|
+
reset: '\x1b[0m'
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function color(colorName, text) {
|
|
14
|
+
return `${colors[colorName]}${text}${colors.reset}`;
|
|
15
|
+
}
|