create-claude-workspace 1.1.12 → 1.1.14
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/dist/template/.claude/docker/Dockerfile +17 -0
- package/dist/template/.claude/docker/docker-compose.yml +2 -0
- package/dist/template/.claude/docker/docker-entrypoint.sh +31 -4
- package/dist/template/.claude/scripts/autonomous.mjs +27 -16
- package/dist/template/.claude/scripts/docker-run.mjs +5 -1
- package/package.json +1 -1
|
@@ -4,6 +4,19 @@ RUN apt-get update && \
|
|
|
4
4
|
apt-get install -y --no-install-recommends git ca-certificates curl gosu && \
|
|
5
5
|
apt-get clean && rm -rf /var/lib/apt/lists/*
|
|
6
6
|
|
|
7
|
+
# GitHub CLI (gh)
|
|
8
|
+
RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
|
|
9
|
+
-o /usr/share/keyrings/githubcli-archive-keyring.gpg && \
|
|
10
|
+
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
|
|
11
|
+
> /etc/apt/sources.list.d/github-cli.list && \
|
|
12
|
+
apt-get update && apt-get install -y --no-install-recommends gh && \
|
|
13
|
+
apt-get clean && rm -rf /var/lib/apt/lists/*
|
|
14
|
+
|
|
15
|
+
# GitLab CLI (glab)
|
|
16
|
+
RUN curl -fsSL "https://gitlab.com/gitlab-org/cli/-/releases/permalink/latest/downloads/glab_$(dpkg --print-architecture).deb" \
|
|
17
|
+
-o /tmp/glab.deb && \
|
|
18
|
+
dpkg -i /tmp/glab.deb && rm /tmp/glab.deb
|
|
19
|
+
|
|
7
20
|
# Non-root user — Claude Code refuses --dangerously-skip-permissions as root
|
|
8
21
|
RUN useradd -m -s /bin/bash claude && \
|
|
9
22
|
mkdir -p /home/claude/.claude && \
|
|
@@ -13,6 +26,10 @@ RUN useradd -m -s /bin/bash claude && \
|
|
|
13
26
|
RUN gosu claude bash -c 'curl -fsSL https://claude.ai/install.sh | bash'
|
|
14
27
|
ENV PATH="/home/claude/.local/bin:$PATH"
|
|
15
28
|
|
|
29
|
+
# Pre-configure Claude to skip first-run onboarding (theme, permissions prompts)
|
|
30
|
+
RUN echo '{"hasCompletedOnboarding":true,"theme":"dark"}' > /home/claude/.claude.json && \
|
|
31
|
+
chown claude:claude /home/claude/.claude.json
|
|
32
|
+
|
|
16
33
|
# Git config for commits inside container
|
|
17
34
|
RUN git config --system user.name "Claude Code" && \
|
|
18
35
|
git config --system user.email "claude@localhost"
|
|
@@ -8,19 +8,46 @@ if [[ -n "${NPM_TOKEN:-}" ]]; then
|
|
|
8
8
|
chown claude:claude /home/claude/.npmrc
|
|
9
9
|
fi
|
|
10
10
|
|
|
11
|
-
# Restore .claude.json
|
|
12
|
-
#
|
|
13
|
-
# so .claude.json is lost on container restart — restore from backup each time.
|
|
11
|
+
# Restore .claude.json if missing (volume only mounts $HOME/.claude/, not $HOME/.claude.json).
|
|
12
|
+
# First try backup from previous session, then fall back to onboarding-skip defaults.
|
|
14
13
|
if [[ ! -f /home/claude/.claude.json ]]; then
|
|
15
14
|
backup=$(find /home/claude/.claude/backups -name '.claude.json.backup.*' 2>/dev/null | sort -V | tail -1)
|
|
16
15
|
if [[ -n "$backup" ]]; then
|
|
17
16
|
cp "$backup" /home/claude/.claude.json
|
|
18
|
-
|
|
17
|
+
else
|
|
18
|
+
echo '{"hasCompletedOnboarding":true,"theme":"dark"}' > /home/claude/.claude.json
|
|
19
19
|
fi
|
|
20
|
+
chown claude:claude /home/claude/.claude.json
|
|
20
21
|
fi
|
|
21
22
|
|
|
22
23
|
# Ensure claude user owns its home dir (volume mounts come in as root)
|
|
23
24
|
chown claude:claude /home/claude
|
|
24
25
|
chown -R claude:claude /home/claude/.claude 2>/dev/null || true
|
|
25
26
|
|
|
27
|
+
# Git platform auth — configure gh/glab from env vars if set
|
|
28
|
+
if [[ -n "${GH_TOKEN:-}" ]]; then
|
|
29
|
+
echo "GH_TOKEN detected — GitHub CLI authenticated."
|
|
30
|
+
fi
|
|
31
|
+
if [[ -n "${GITLAB_TOKEN:-}" ]]; then
|
|
32
|
+
echo "GITLAB_TOKEN detected — GitLab CLI authenticated."
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# Auth pre-check — fail fast if no credentials available
|
|
36
|
+
if [[ -z "${ANTHROPIC_API_KEY:-}" ]]; then
|
|
37
|
+
creds="/home/claude/.claude/.credentials.json"
|
|
38
|
+
if [[ ! -f "$creds" ]] || [[ ! -s "$creds" ]]; then
|
|
39
|
+
echo ""
|
|
40
|
+
echo "ERROR: No Claude authentication found."
|
|
41
|
+
echo ""
|
|
42
|
+
echo " Option 1 — On your HOST machine:"
|
|
43
|
+
echo " claude auth login"
|
|
44
|
+
echo " Then re-run docker-run.mjs"
|
|
45
|
+
echo ""
|
|
46
|
+
echo " Option 2 — API key:"
|
|
47
|
+
echo " ANTHROPIC_API_KEY=sk-... node .claude/scripts/docker-run.mjs"
|
|
48
|
+
echo ""
|
|
49
|
+
exit 1
|
|
50
|
+
fi
|
|
51
|
+
fi
|
|
52
|
+
|
|
26
53
|
exec gosu claude "$@"
|
|
@@ -195,46 +195,57 @@ function runClaude(projectDir, opts) {
|
|
|
195
195
|
let child;
|
|
196
196
|
const isWin = process.platform === 'win32';
|
|
197
197
|
|
|
198
|
-
// Run Claude in interactive mode (no -p) so the full TUI is visible.
|
|
199
|
-
// Prompt is sent via stdin then closed — Claude processes it and exits on EOF.
|
|
200
|
-
// stdout+stderr inherited so the terminal UI renders directly.
|
|
201
198
|
if (isWin) {
|
|
199
|
+
// Windows: claude is a .cmd shim requiring shell execution.
|
|
200
|
+
// cmd.exe mangles quoted arguments, so pipe prompt via stdin instead.
|
|
202
201
|
const permFlag = opts.skipPermissions ? ' --dangerously-skip-permissions' : '';
|
|
203
|
-
child = spawn(`claude --agent orchestrator --max-turns ${opts.maxTurns}${permFlag}`, [], {
|
|
202
|
+
child = spawn(`claude -p --agent orchestrator --max-turns ${opts.maxTurns}${permFlag}`, [], {
|
|
204
203
|
cwd: projectDir,
|
|
205
|
-
stdio: ['pipe', '
|
|
204
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
206
205
|
shell: true,
|
|
207
206
|
});
|
|
207
|
+
child.stdin.write(PROMPT);
|
|
208
|
+
child.stdin.end();
|
|
208
209
|
} else {
|
|
209
|
-
const args = ['--agent', 'orchestrator', '--max-turns', String(opts.maxTurns)];
|
|
210
|
+
const args = ['-p', PROMPT, '--agent', 'orchestrator', '--max-turns', String(opts.maxTurns)];
|
|
210
211
|
if (opts.skipPermissions) args.push('--dangerously-skip-permissions');
|
|
211
212
|
child = spawn('claude', args, {
|
|
212
213
|
cwd: projectDir,
|
|
213
|
-
stdio: ['
|
|
214
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
214
215
|
});
|
|
215
216
|
}
|
|
216
217
|
|
|
217
|
-
child.stdin.write(PROMPT);
|
|
218
|
-
child.stdin.end();
|
|
219
|
-
|
|
220
218
|
currentChild = child;
|
|
219
|
+
let stderr = '';
|
|
220
|
+
|
|
221
|
+
child.stdout.on('data', chunk => {
|
|
222
|
+
process.stdout.write(chunk);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
child.stderr.on('data', chunk => {
|
|
226
|
+
const text = chunk.toString();
|
|
227
|
+
stderr += text;
|
|
228
|
+
process.stderr.write(text);
|
|
229
|
+
});
|
|
221
230
|
|
|
222
231
|
child.on('close', code => {
|
|
223
232
|
currentChild = null;
|
|
224
|
-
resolvePromise({ code });
|
|
233
|
+
resolvePromise({ code, stderr });
|
|
225
234
|
});
|
|
226
235
|
|
|
227
236
|
child.on('error', err => {
|
|
228
237
|
currentChild = null;
|
|
229
|
-
resolvePromise({ code: 1 });
|
|
238
|
+
resolvePromise({ code: 1, stderr: err.message });
|
|
230
239
|
});
|
|
231
240
|
});
|
|
232
241
|
}
|
|
233
242
|
|
|
234
|
-
function detectRateLimit(
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
243
|
+
function detectRateLimit(output) {
|
|
244
|
+
const stderr = output.stderr.toLowerCase();
|
|
245
|
+
return stderr.includes('rate limit') ||
|
|
246
|
+
stderr.includes('rate_limit') ||
|
|
247
|
+
stderr.includes('too many requests') ||
|
|
248
|
+
stderr.includes('overloaded');
|
|
238
249
|
}
|
|
239
250
|
|
|
240
251
|
async function main() {
|
|
@@ -146,6 +146,10 @@ npm Publishing (optional):
|
|
|
146
146
|
Set NPM_TOKEN=npm_XXXXX before running.
|
|
147
147
|
Optionally: NPM_REGISTRY=npm.pkg.github.com (default: registry.npmjs.org)
|
|
148
148
|
|
|
149
|
+
Git Platform (optional — for push, MR/PR, issues):
|
|
150
|
+
GitHub: set GH_TOKEN=ghp_XXXXX before running
|
|
151
|
+
GitLab: set GITLAB_TOKEN=glpat-XXXXX before running
|
|
152
|
+
|
|
149
153
|
Examples:
|
|
150
154
|
node .claude/scripts/docker-run.mjs
|
|
151
155
|
node .claude/scripts/docker-run.mjs --max-iterations 20
|
|
@@ -358,5 +362,5 @@ if (opts.shell) {
|
|
|
358
362
|
info('Autonomous mode — isolated in Docker, --skip-permissions is safe.');
|
|
359
363
|
info('Press Ctrl+C to stop after current iteration.');
|
|
360
364
|
console.log('');
|
|
361
|
-
compose(['run', '--rm', 'claude', '-c', `node .claude/scripts/autonomous.mjs ${autoArgs}`]);
|
|
365
|
+
compose(['run', '--rm', '-T', 'claude', '-c', `node .claude/scripts/autonomous.mjs ${autoArgs}`]);
|
|
362
366
|
}
|