This commit is contained in:
Chris Wanstrath 2026-02-19 20:11:18 -08:00
parent 1c31d3ed6f
commit 75bbe90b5a

View File

@ -45,7 +45,10 @@ export async function create(log?: (msg: string) => void): Promise<void> {
// Create symlinks so git worktree absolute paths from the host resolve inside the container // Create symlinks so git worktree absolute paths from the host resolve inside the container
await $`container exec ${CONTAINER_NAME} bash -c ${`mkdir -p '${home}' && ln -s /host '${home}/dev' && ln -s /sandlot '${home}/.sandlot'`}`.quiet() await $`container exec ${CONTAINER_NAME} bash -c ${`mkdir -p '${home}' && ln -s /host '${home}/dev' && ln -s /sandlot '${home}/.sandlot'`}`.quiet()
// Install Claude Code and configure (as ubuntu user) // Install Bun and Claude Code (as ubuntu user)
log?.("Installing Bun")
await $`container exec --user ${USER} ${CONTAINER_NAME} bash -c ${"curl -fsSL https://bun.sh/install | bash"}`.quiet()
log?.("Installing Claude Code") log?.("Installing Claude Code")
await $`container exec --user ${USER} ${CONTAINER_NAME} bash -c ${"curl -fsSL https://claude.ai/install.sh | bash"}`.quiet() await $`container exec --user ${USER} ${CONTAINER_NAME} bash -c ${"curl -fsSL https://claude.ai/install.sh | bash"}`.quiet()
@ -155,6 +158,7 @@ export async function claude(workdir: string, opts?: { prompt?: string; print?:
`Your working directory is ${cwd}, a git worktree managed by sandlot.`, `Your working directory is ${cwd}, a git worktree managed by sandlot.`,
"The host's ~/dev is mounted read-only at /host.", "The host's ~/dev is mounted read-only at /host.",
"The host's ~/.sandlot is mounted at /sandlot.", "The host's ~/.sandlot is mounted at /sandlot.",
"Bun is installed at ~/.bun/bin/bun. Use bun instead of node/npm.",
] ]
if (opts?.print) { if (opts?.print) {
systemPromptLines.push("IMPORTANT: Do not use plan mode. Do not call the EnterPlanMode tool. Proceed directly with the task.") systemPromptLines.push("IMPORTANT: Do not use plan mode. Do not call the EnterPlanMode tool. Proceed directly with the task.")
@ -162,7 +166,7 @@ export async function claude(workdir: string, opts?: { prompt?: string; print?:
const systemPrompt = systemPromptLines.join("\n") const systemPrompt = systemPromptLines.join("\n")
const term = process.env.TERM || "xterm-256color" const term = process.env.TERM || "xterm-256color"
const args = ["container", "exec", "-it", "--user", USER, "--workdir", cwd, CONTAINER_NAME, "env", `TERM=${term}`, CLAUDE_BIN, "--dangerously-skip-permissions", "--model", "claude-opus-4-6", "--append-system-prompt", systemPrompt] const args = ["container", "exec", "-it", "--user", USER, "--workdir", cwd, CONTAINER_NAME, "env", `TERM=${term}`, `PATH=/home/${USER}/.bun/bin:/home/${USER}/.local/bin:/usr/local/bin:/usr/bin:/bin`, CLAUDE_BIN, "--dangerously-skip-permissions", "--model", "claude-opus-4-6", "--append-system-prompt", systemPrompt]
if (opts?.print) args.push("-p", opts.print) if (opts?.print) args.push("-p", opts.print)
else if (opts?.prompt) args.push(opts.prompt) else if (opts?.prompt) args.push(opts.prompt)
@ -197,7 +201,7 @@ export async function info(): Promise<void> {
/** Run a bash command in the container at the given workdir, capturing output. */ /** Run a bash command in the container at the given workdir, capturing output. */
export async function exec(workdir: string, command: string): Promise<{ exitCode: number; stdout: string; stderr: string }> { export async function exec(workdir: string, command: string): Promise<{ exitCode: number; stdout: string; stderr: string }> {
const result = await $`container exec --user ${USER} --workdir ${containerPath(workdir)} ${CONTAINER_NAME} bash -c ${"export PATH=$HOME/.local/bin:$PATH; " + command}`.nothrow().quiet() const result = await $`container exec --user ${USER} --workdir ${containerPath(workdir)} ${CONTAINER_NAME} bash -c ${"export PATH=$HOME/.bun/bin:$HOME/.local/bin:$PATH; " + command}`.nothrow().quiet()
return { return {
exitCode: result.exitCode, exitCode: result.exitCode,
stdout: result.stdout.toString().trim(), stdout: result.stdout.toString().trim(),