This commit is contained in:
Chris Wanstrath 2026-02-18 23:50:16 -08:00
parent 9eae7c0951
commit 218609bffb

View File

@ -5,6 +5,18 @@ const CONTAINER_NAME = "sandlot"
const USER = "ubuntu"
const CLAUDE_BIN = `/home/${USER}/.local/bin/claude`
/** Translate a host path to its corresponding container path. */
function containerPath(hostPath: string): string {
const home = homedir()
if (hostPath.startsWith(`${home}/.sandlot`)) {
return "/sandlot" + hostPath.slice(`${home}/.sandlot`.length)
}
if (hostPath.startsWith(`${home}/dev`)) {
return "/dev-host" + hostPath.slice(`${home}/dev`.length)
}
return hostPath
}
function requireContainer(): void {
if (!Bun.which("container")) {
console.error('Apple Container is not installed. Install it with: brew install container')
@ -30,7 +42,7 @@ export async function ensure(log?: (msg: string) => void): Promise<void> {
// Create from scratch
const home = homedir()
log?.("Pulling image & creating container")
await $`container run -d --name ${CONTAINER_NAME} -m 4G --mount type=bind,source=${home}/dev,target=${home}/dev,readonly -v ${home}/.sandlot:${home}/.sandlot ubuntu:24.04 sleep infinity`.quiet()
await $`container run -d --name ${CONTAINER_NAME} -m 4G --mount type=bind,source=${home}/dev,target=/dev-host,readonly -v ${home}/.sandlot:/sandlot ubuntu:24.04 sleep infinity`.quiet()
// Provision (as root)
log?.("Installing packages")
@ -97,7 +109,7 @@ export async function status(): Promise<"running" | "stopped" | "missing"> {
/** Launch claude in the container at the given workdir. */
export async function claude(workdir: string, prompt?: string): Promise<void> {
const args = ["container", "exec", "-it", "--user", USER, "--workdir", workdir, CONTAINER_NAME, CLAUDE_BIN, "--dangerously-skip-permissions"]
const args = ["container", "exec", "-it", "--user", USER, "--workdir", containerPath(workdir), CONTAINER_NAME, CLAUDE_BIN, "--dangerously-skip-permissions"]
if (prompt) args.push(prompt)
const proc = Bun.spawn(args, { stdin: "inherit", stdout: "inherit", stderr: "inherit" })
await proc.exited
@ -123,7 +135,7 @@ export async function info(): Promise<void> {
/** 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 }> {
const result = await $`container exec --user ${USER} --workdir ${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/.local/bin:$PATH; " + command}`.nothrow().quiet()
return {
exitCode: result.exitCode,
stdout: result.stdout.toString().trim(),