sandboxbox 2.0.4 → 2.0.7
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/0.60 +0 -0
- package/CLAUDE.md +138 -0
- package/Dockerfile +94 -94
- package/Dockerfile.local-workspace +56 -0
- package/README.md +242 -242
- package/cli.js +269 -278
- package/launch-sandboxbox.bat +75 -0
- package/launch-sandboxbox.sh +81 -0
- package/npx-test/package.json +1 -0
- package/package.json +38 -38
- package/scripts/download-podman.js +237 -148
- package/test/Dockerfile +19 -0
- package/test/index.js +16 -0
- package/test/package.json +13 -0
- package/test-cross-platform.sh +78 -0
- package/test-merge-workflow.sh +58 -0
- package/test-sandbox-workflow.sh +45 -0
- package/utils/claude-workspace.js +77 -0
- package/utils/colors.js +15 -0
- package/utils/podman.js +116 -0
- package/bin/.gitkeep +0 -1
package/0.60
ADDED
File without changes
|
package/CLAUDE.md
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
# SandboxBox Technical Documentation
|
2
|
+
|
3
|
+
## Architecture Overview
|
4
|
+
SandboxBox provides portable containerized development environments using Podman with automatic WSL machine management and Claude Code integration.
|
5
|
+
|
6
|
+
## Core Components
|
7
|
+
|
8
|
+
### CLI (cli.js)
|
9
|
+
- Main entry point with automatic Podman machine management
|
10
|
+
- Commands: build, run, shell, version, help
|
11
|
+
- Auto-detects and starts Podman machine when needed
|
12
|
+
- Shell execution with Windows compatibility (`shell: process.platform === 'win32'`)
|
13
|
+
|
14
|
+
### Podman Downloader (scripts/download-podman.js)
|
15
|
+
- Cross-platform binary downloads from GitHub releases
|
16
|
+
- PowerShell ZIP extraction on Windows (no external dependencies)
|
17
|
+
- Automatic version detection and binary path resolution
|
18
|
+
|
19
|
+
### Container Images
|
20
|
+
- **sandboxbox-auth**: Full development environment with Claude Code
|
21
|
+
- **sandboxbox-local**: Local repository workspace (symlink approach)
|
22
|
+
|
23
|
+
## Windows Compatibility Fixes
|
24
|
+
|
25
|
+
### Critical PowerShell ZIP Extraction
|
26
|
+
```javascript
|
27
|
+
// scripts/download-podman.js:81
|
28
|
+
execSync(`powershell -Command "${psCommand}"`, {
|
29
|
+
stdio: 'pipe',
|
30
|
+
cwd: __dirname,
|
31
|
+
shell: true // REQUIRED for PowerShell commands
|
32
|
+
});
|
33
|
+
```
|
34
|
+
|
35
|
+
### Shell Execution Pattern
|
36
|
+
All `execSync()` calls must include:
|
37
|
+
```javascript
|
38
|
+
{
|
39
|
+
stdio: 'pipe',
|
40
|
+
shell: process.platform === 'win32' // Windows compatibility
|
41
|
+
}
|
42
|
+
```
|
43
|
+
|
44
|
+
### Auto Podman Machine Management
|
45
|
+
```javascript
|
46
|
+
// cli.js checkPodman() function
|
47
|
+
if (process.platform === 'win32' && isBundled) {
|
48
|
+
try {
|
49
|
+
execSync(`"${podmanPath}" info`, { ...execOptions, stdio: 'pipe' });
|
50
|
+
} catch (infoError) {
|
51
|
+
if (infoError.message.includes('Cannot connect to Podman')) {
|
52
|
+
// Auto-start existing machine
|
53
|
+
execSync(`"${podmanPath}" machine start`, { stdio: 'inherit' });
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
```
|
58
|
+
|
59
|
+
## Claude Code Integration
|
60
|
+
|
61
|
+
### Authentication Transfer
|
62
|
+
Mount complete Claude session data:
|
63
|
+
```bash
|
64
|
+
-v "$HOME/.claude:/root/.claude"
|
65
|
+
```
|
66
|
+
|
67
|
+
### Environment Variables
|
68
|
+
Key variables to transfer:
|
69
|
+
```bash
|
70
|
+
ANTHROPIC_AUTH_TOKEN
|
71
|
+
CLAUDECODE=1
|
72
|
+
ANTHROPIC_BASE_URL
|
73
|
+
```
|
74
|
+
|
75
|
+
### Git Identity Transfer
|
76
|
+
```bash
|
77
|
+
-v "$HOME/.gitconfig:/root/.gitconfig:ro"
|
78
|
+
-v "$HOME/.ssh:/root/.ssh:ro"
|
79
|
+
```
|
80
|
+
|
81
|
+
## Local Repository Workflow
|
82
|
+
|
83
|
+
### Architecture
|
84
|
+
- Container mounts local repo as `/project:rw`
|
85
|
+
- Creates symlink `/workspace/project` → `/project`
|
86
|
+
- Works directly with local repository (no cloning needed)
|
87
|
+
- Changes persist to host folder automatically
|
88
|
+
|
89
|
+
### Container Command
|
90
|
+
```bash
|
91
|
+
podman run --rm \
|
92
|
+
-v "/path/to/repo:/project:rw" \
|
93
|
+
-v "$HOME/.claude:/root/.claude" \
|
94
|
+
-v "$HOME/.gitconfig:/root/.gitconfig:ro" \
|
95
|
+
-v "$HOME/.ssh:/root/.ssh" \
|
96
|
+
-e "ANTHROPIC_AUTH_TOKEN=..." \
|
97
|
+
-e "CLAUDECODE=1" \
|
98
|
+
sandboxbox-local:latest
|
99
|
+
```
|
100
|
+
|
101
|
+
### Dockerfile.local-workspace
|
102
|
+
```dockerfile
|
103
|
+
# Creates symlink to mounted repository
|
104
|
+
ln -sf "$REPO_PATH" "$WORKSPACE_DIR"
|
105
|
+
cd "$WORKSPACE_DIR"
|
106
|
+
exec claude # Changes save directly to local repo
|
107
|
+
```
|
108
|
+
|
109
|
+
## Complete Workflow Example
|
110
|
+
|
111
|
+
1. **Setup**: Build sandboxbox-local image
|
112
|
+
2. **Mount**: Local repository as `/project:rw`
|
113
|
+
3. **Auth Transfer**: Mount `.claude`, `.gitconfig`, `.ssh`
|
114
|
+
4. **Edit**: Claude Code modifies files in `/workspace/project` (symlink to `/project`)
|
115
|
+
5. **Commit**: Changes made directly to local repository
|
116
|
+
6. **Persist**: No additional push/pull needed - changes already in host folder
|
117
|
+
|
118
|
+
## Troubleshooting
|
119
|
+
|
120
|
+
### "unzip command not found"
|
121
|
+
**Solution**: Use PowerShell ZIP extraction with `shell: true`
|
122
|
+
|
123
|
+
### "Cannot connect to Podman"
|
124
|
+
**Solution**: Automatic machine start in checkPodman() function
|
125
|
+
|
126
|
+
### Build context issues
|
127
|
+
**Solution**: Use direct Podman build, then tag for SandboxBox
|
128
|
+
|
129
|
+
### Git identity errors
|
130
|
+
**Solution**: Mount `.gitconfig:ro` for user identity transfer
|
131
|
+
|
132
|
+
### Path resolution issues
|
133
|
+
**Solution**: Use explicit REPO_PATH environment variable
|
134
|
+
|
135
|
+
## Version Management
|
136
|
+
- Publish new version when fixing critical Windows issues
|
137
|
+
- Clear npm cache: `npm cache clean --force`
|
138
|
+
- Use specific version: `npx sandboxbox@latest`
|
package/Dockerfile
CHANGED
@@ -1,95 +1,95 @@
|
|
1
|
-
FROM node:20
|
2
|
-
|
3
|
-
ARG TZ
|
4
|
-
ENV TZ="$TZ"
|
5
|
-
|
6
|
-
ARG CLAUDE_CODE_VERSION=latest
|
7
|
-
|
8
|
-
# Install basic development tools and iptables/ipset
|
9
|
-
RUN apt-get update && apt-get install -y --no-install-recommends \
|
10
|
-
less \
|
11
|
-
git \
|
12
|
-
procps \
|
13
|
-
sudo \
|
14
|
-
fzf \
|
15
|
-
zsh \
|
16
|
-
man-db \
|
17
|
-
unzip \
|
18
|
-
gnupg2 \
|
19
|
-
gh \
|
20
|
-
iptables \
|
21
|
-
ipset \
|
22
|
-
iproute2 \
|
23
|
-
dnsutils \
|
24
|
-
aggregate \
|
25
|
-
jq \
|
26
|
-
nano \
|
27
|
-
vim \
|
28
|
-
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
29
|
-
|
30
|
-
# Ensure default node user has access to /usr/local/share
|
31
|
-
RUN mkdir -p /usr/local/share/npm-global && \
|
32
|
-
chown -R node:node /usr/local/share
|
33
|
-
|
34
|
-
ARG USERNAME=node
|
35
|
-
|
36
|
-
# Persist bash history.
|
37
|
-
RUN SNIPPET="export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \
|
38
|
-
&& mkdir -p /commandhistory \
|
39
|
-
&& touch /commandhistory/.bash_history \
|
40
|
-
&& chown -R $USERNAME /commandhistory
|
41
|
-
|
42
|
-
# Set `DEVCONTAINER` environment variable to help with orientation
|
43
|
-
ENV DEVCONTAINER=true
|
44
|
-
|
45
|
-
# Create workspace and config directories and set permissions
|
46
|
-
RUN mkdir -p /workspace /home/node/.claude && \
|
47
|
-
chown -R node:node /workspace /home/node/.claude
|
48
|
-
|
49
|
-
WORKDIR /workspace
|
50
|
-
|
51
|
-
ARG GIT_DELTA_VERSION=0.18.2
|
52
|
-
RUN ARCH=$(dpkg --print-architecture) && \
|
53
|
-
wget "https://github.com/dandavison/delta/releases/download/${GIT_DELTA_VERSION}/git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" && \
|
54
|
-
sudo dpkg -i "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" && \
|
55
|
-
rm "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb"
|
56
|
-
|
57
|
-
# Set up non-root user
|
58
|
-
USER node
|
59
|
-
|
60
|
-
# Install global packages
|
61
|
-
ENV NPM_CONFIG_PREFIX=/usr/local/share/npm-global
|
62
|
-
ENV PATH=$PATH:/usr/local/share/npm-global/bin
|
63
|
-
|
64
|
-
# Set the default shell to zsh rather than sh
|
65
|
-
ENV SHELL=/bin/zsh
|
66
|
-
|
67
|
-
# Set the default editor and visual
|
68
|
-
ENV EDITOR=nano
|
69
|
-
ENV VISUAL=nano
|
70
|
-
|
71
|
-
# Default powerline10k theme
|
72
|
-
ARG ZSH_IN_DOCKER_VERSION=1.2.0
|
73
|
-
RUN sh -c "$(wget -O- https://github.com/deluan/zsh-in-docker/releases/download/v${ZSH_IN_DOCKER_VERSION}/zsh-in-docker.sh)" -- \
|
74
|
-
-p git \
|
75
|
-
-p fzf \
|
76
|
-
-a "source /usr/share/doc/fzf/examples/key-bindings.zsh" \
|
77
|
-
-a "source /usr/share/doc/fzf/examples/completion.zsh" \
|
78
|
-
-a "export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \
|
79
|
-
-x
|
80
|
-
|
81
|
-
# Install Claude
|
82
|
-
RUN npm install -g @anthropic-ai/claude-code@${CLAUDE_CODE_VERSION}
|
83
|
-
|
84
|
-
# Install playwright deps
|
85
|
-
RUN npx --yes playwright install-deps
|
86
|
-
|
87
|
-
RUN npm i -g @playwright/mcp
|
88
|
-
|
89
|
-
# Copy and set up firewall script
|
90
|
-
COPY init-firewall.sh /usr/local/bin/
|
91
|
-
USER root
|
92
|
-
RUN chmod +x /usr/local/bin/init-firewall.sh && \
|
93
|
-
echo "node ALL=(root) NOPASSWD: /usr/local/bin/init-firewall.sh" > /etc/sudoers.d/node-firewall && \
|
94
|
-
chmod 0440 /etc/sudoers.d/node-firewall
|
1
|
+
FROM node:20
|
2
|
+
|
3
|
+
ARG TZ
|
4
|
+
ENV TZ="$TZ"
|
5
|
+
|
6
|
+
ARG CLAUDE_CODE_VERSION=latest
|
7
|
+
|
8
|
+
# Install basic development tools and iptables/ipset
|
9
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
10
|
+
less \
|
11
|
+
git \
|
12
|
+
procps \
|
13
|
+
sudo \
|
14
|
+
fzf \
|
15
|
+
zsh \
|
16
|
+
man-db \
|
17
|
+
unzip \
|
18
|
+
gnupg2 \
|
19
|
+
gh \
|
20
|
+
iptables \
|
21
|
+
ipset \
|
22
|
+
iproute2 \
|
23
|
+
dnsutils \
|
24
|
+
aggregate \
|
25
|
+
jq \
|
26
|
+
nano \
|
27
|
+
vim \
|
28
|
+
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
29
|
+
|
30
|
+
# Ensure default node user has access to /usr/local/share
|
31
|
+
RUN mkdir -p /usr/local/share/npm-global && \
|
32
|
+
chown -R node:node /usr/local/share
|
33
|
+
|
34
|
+
ARG USERNAME=node
|
35
|
+
|
36
|
+
# Persist bash history.
|
37
|
+
RUN SNIPPET="export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \
|
38
|
+
&& mkdir -p /commandhistory \
|
39
|
+
&& touch /commandhistory/.bash_history \
|
40
|
+
&& chown -R $USERNAME /commandhistory
|
41
|
+
|
42
|
+
# Set `DEVCONTAINER` environment variable to help with orientation
|
43
|
+
ENV DEVCONTAINER=true
|
44
|
+
|
45
|
+
# Create workspace and config directories and set permissions
|
46
|
+
RUN mkdir -p /workspace /home/node/.claude && \
|
47
|
+
chown -R node:node /workspace /home/node/.claude
|
48
|
+
|
49
|
+
WORKDIR /workspace
|
50
|
+
|
51
|
+
ARG GIT_DELTA_VERSION=0.18.2
|
52
|
+
RUN ARCH=$(dpkg --print-architecture) && \
|
53
|
+
wget "https://github.com/dandavison/delta/releases/download/${GIT_DELTA_VERSION}/git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" && \
|
54
|
+
sudo dpkg -i "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" && \
|
55
|
+
rm "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb"
|
56
|
+
|
57
|
+
# Set up non-root user
|
58
|
+
USER node
|
59
|
+
|
60
|
+
# Install global packages
|
61
|
+
ENV NPM_CONFIG_PREFIX=/usr/local/share/npm-global
|
62
|
+
ENV PATH=$PATH:/usr/local/share/npm-global/bin
|
63
|
+
|
64
|
+
# Set the default shell to zsh rather than sh
|
65
|
+
ENV SHELL=/bin/zsh
|
66
|
+
|
67
|
+
# Set the default editor and visual
|
68
|
+
ENV EDITOR=nano
|
69
|
+
ENV VISUAL=nano
|
70
|
+
|
71
|
+
# Default powerline10k theme
|
72
|
+
ARG ZSH_IN_DOCKER_VERSION=1.2.0
|
73
|
+
RUN sh -c "$(wget -O- https://github.com/deluan/zsh-in-docker/releases/download/v${ZSH_IN_DOCKER_VERSION}/zsh-in-docker.sh)" -- \
|
74
|
+
-p git \
|
75
|
+
-p fzf \
|
76
|
+
-a "source /usr/share/doc/fzf/examples/key-bindings.zsh" \
|
77
|
+
-a "source /usr/share/doc/fzf/examples/completion.zsh" \
|
78
|
+
-a "export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \
|
79
|
+
-x
|
80
|
+
|
81
|
+
# Install Claude
|
82
|
+
RUN npm install -g @anthropic-ai/claude-code@${CLAUDE_CODE_VERSION}
|
83
|
+
|
84
|
+
# Install playwright deps
|
85
|
+
RUN npx --yes playwright install-deps
|
86
|
+
|
87
|
+
RUN npm i -g @playwright/mcp
|
88
|
+
|
89
|
+
# Copy and set up firewall script
|
90
|
+
COPY init-firewall.sh /usr/local/bin/
|
91
|
+
USER root
|
92
|
+
RUN chmod +x /usr/local/bin/init-firewall.sh && \
|
93
|
+
echo "node ALL=(root) NOPASSWD: /usr/local/bin/init-firewall.sh" > /etc/sudoers.d/node-firewall && \
|
94
|
+
chmod 0440 /etc/sudoers.d/node-firewall
|
95
95
|
USER node
|
@@ -0,0 +1,56 @@
|
|
1
|
+
FROM node:20
|
2
|
+
|
3
|
+
# Install basic development tools
|
4
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
5
|
+
git \
|
6
|
+
curl \
|
7
|
+
bash \
|
8
|
+
sudo \
|
9
|
+
nano \
|
10
|
+
vim \
|
11
|
+
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
12
|
+
|
13
|
+
# Create workspace directory
|
14
|
+
WORKDIR /workspace
|
15
|
+
|
16
|
+
# Install Claude Code globally
|
17
|
+
RUN npm install -g @anthropic-ai/claude-code@latest
|
18
|
+
|
19
|
+
# Create startup script for local workspace (no cloning needed)
|
20
|
+
RUN echo '#!/bin/bash\n\
|
21
|
+
set -e\n\
|
22
|
+
\n\
|
23
|
+
# Get repository path from environment or default\n\
|
24
|
+
REPO_PATH=${REPO_PATH:-"/project"}\n\
|
25
|
+
WORKSPACE_DIR="/workspace/project"\n\
|
26
|
+
\n\
|
27
|
+
echo "🚀 Starting SandboxBox with Claude Code..."\n\
|
28
|
+
echo "📁 Working with local repository: $REPO_PATH"\n\
|
29
|
+
echo "🎯 Workspace: $WORKSPACE_DIR"\n\
|
30
|
+
\n\
|
31
|
+
# Create symbolic link to the mounted repository\n\
|
32
|
+
if [ -d "$REPO_PATH" ] && [ -d "$REPO_PATH/.git" ]; then\n\
|
33
|
+
echo "📂 Creating workspace symlink to local repository..."\n\
|
34
|
+
ln -sf "$REPO_PATH" "$WORKSPACE_DIR"\n\
|
35
|
+
cd "$WORKSPACE_DIR"\n\
|
36
|
+
echo "✅ Workspace linked successfully!"\n\
|
37
|
+
echo "📋 Current status:"\n\
|
38
|
+
git status\n\
|
39
|
+
echo "📁 Repository contents:"\n\
|
40
|
+
ls -la\n\
|
41
|
+
echo ""\n\
|
42
|
+
echo "🔧 Starting Claude Code..."\n\
|
43
|
+
echo "💡 Tip: Changes will be saved directly to the local repository"\n\
|
44
|
+
echo "💡 Use Ctrl+C to exit Claude Code"\n\
|
45
|
+
exec claude\n\
|
46
|
+
else\n\
|
47
|
+
echo "❌ Error: $REPO_PATH is not a valid git repository"\n\
|
48
|
+
echo "Please ensure the path contains a .git directory"\n\
|
49
|
+
echo "Contents of $REPO_PATH:"\n\
|
50
|
+
ls -la "$REPO_PATH" 2>/dev/null || echo "Directory not accessible"\n\
|
51
|
+
exit 1\n\
|
52
|
+
fi' > /usr/local/bin/start-local-sandbox.sh && \
|
53
|
+
chmod +x /usr/local/bin/start-local-sandbox.sh
|
54
|
+
|
55
|
+
# Set default command
|
56
|
+
CMD ["/usr/local/bin/start-local-sandbox.sh"]
|