From ac745d02f646a5f7ed729756e0c62d9e35e1d723 Mon Sep 17 00:00:00 2001 From: Chris Wanstrath Date: Wed, 11 Mar 2026 22:36:18 -0700 Subject: [PATCH 1/2] Add statusline script showing branch in powerline --- src/vm.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/vm.ts b/src/vm.ts index bcfde9d..454e177 100644 --- a/src/vm.ts +++ b/src/vm.ts @@ -157,7 +157,10 @@ async function configureEnvironment(home: string, apiKey: string): Promise Stop: [{ hooks: [{ type: "command", command: `${activityBin} idle` }] }], PostToolUseFailure: [{ hooks: [{ type: "command", command: `${activityBin} idle` }] }], } - const settingsJson = JSON.stringify({ apiKeyHelper: "~/.claude/api-key-helper.sh", skipDangerousModePermissionPrompt: true, hooks }) + // Status line: show current branch in the Claude Code powerline + const statusLineBin = `/home/${USER}/.local/bin/sandlot-statusline` + const statusLine = { type: "command", command: statusLineBin } + const settingsJson = JSON.stringify({ apiKeyHelper: "~/.claude/api-key-helper.sh", skipDangerousModePermissionPrompt: true, hooks, statusLine }) const claudeJson = JSON.stringify({ hasCompletedOnboarding: true, effortCalloutDismissed: true, projects: { "/": { hasTrustDialogAccepted: true } } }) // Write the helper script to a temp file and copy it in so the key @@ -180,6 +183,19 @@ async function configureEnvironment(home: string, apiKey: string): Promise await $`container exec --user ${USER} ${CONTAINER_NAME} bash -c ${"cp /sandlot/.sandlot-activity.tmp ~/.local/bin/sandlot-activity"}`.quiet() await Bun.file(activityTmp).unlink() + // Install statusline script (shows branch in Claude Code powerline) + const statuslineTmp = `${home}/.sandlot/.sandlot-statusline.tmp` + await Bun.write(statuslineTmp, [ + '#!/bin/bash', + 'input=$(cat)', + 'branch=$(echo "$input" | grep -oP \'"branch"\\s*:\\s*"\\K[^"]+\' | head -1)', + '[ -n "$branch" ] && printf \'\\033[36m⎇ %s\\033[0m\\n\' "$branch"', + '', + ].join('\n')) + await $`chmod +x ${statuslineTmp}`.quiet() + await $`container exec --user ${USER} ${CONTAINER_NAME} bash -c ${"cp /sandlot/.sandlot-statusline.tmp ~/.local/bin/sandlot-statusline"}`.quiet() + await Bun.file(statuslineTmp).unlink() + await $`container exec --user ${USER} ${CONTAINER_NAME} bash -c ${` mkdir -p ~/.claude echo '${settingsJson}' > ~/.claude/settings.json From 3fc59774a540415437d8af79b9d95b36631fb80b Mon Sep 17 00:00:00 2001 From: Chris Wanstrath Date: Thu, 12 Mar 2026 07:45:16 -0700 Subject: [PATCH 2/2] refactor: extract installScript helper function --- src/vm.ts | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/src/vm.ts b/src/vm.ts index 454e177..6dc5857 100644 --- a/src/vm.ts +++ b/src/vm.ts @@ -144,6 +144,15 @@ async function installTooling(cached: boolean, log?: (msg: string) => void): Pro await $`container exec --user ${USER} ${CONTAINER_NAME} bash -c ${"cp ~/.local/bin/bun ~/.local/bin/claude ~/.local/bin/neofetch /sandlot/.cache/ && cp /tmp/nvim.tar.gz /sandlot/.cache/nvim.tar.gz"}`.nothrow().quiet() } +/** Write a script to a temp file, copy it into ~/.local/bin/ in the container, then clean up. */ +async function installScript(home: string, name: string, content: string): Promise { + const tmp = `${home}/.sandlot/.${name}.tmp` + await Bun.write(tmp, content) + await $`chmod +x ${tmp}`.quiet() + await $`container exec --user ${USER} ${CONTAINER_NAME} bash -c ${`cp /sandlot/.${name}.tmp ~/.local/bin/${name}`}`.quiet() + await Bun.file(tmp).unlink() +} + /** Configure git identity, API key helper, activity hook, and Claude settings. */ async function configureEnvironment(home: string, apiKey: string): Promise { const gitName = (await $`git config user.name`.quiet().text()).trim() @@ -157,9 +166,7 @@ async function configureEnvironment(home: string, apiKey: string): Promise Stop: [{ hooks: [{ type: "command", command: `${activityBin} idle` }] }], PostToolUseFailure: [{ hooks: [{ type: "command", command: `${activityBin} idle` }] }], } - // Status line: show current branch in the Claude Code powerline - const statusLineBin = `/home/${USER}/.local/bin/sandlot-statusline` - const statusLine = { type: "command", command: statusLineBin } + const statusLine = { type: "command", command: `/home/${USER}/.local/bin/sandlot-statusline` } const settingsJson = JSON.stringify({ apiKeyHelper: "~/.claude/api-key-helper.sh", skipDangerousModePermissionPrompt: true, hooks, statusLine }) const claudeJson = JSON.stringify({ hasCompletedOnboarding: true, effortCalloutDismissed: true, projects: { "/": { hasTrustDialogAccepted: true } } }) @@ -171,30 +178,8 @@ async function configureEnvironment(home: string, apiKey: string): Promise await $`container exec --user ${USER} ${CONTAINER_NAME} bash -c ${"mkdir -p ~/.claude && cp /sandlot/.api-key-helper.tmp ~/.claude/api-key-helper.sh"}`.quiet() await Bun.file(tmp).unlink() - // Install activity tracking hook script - const activityTmp = `${home}/.sandlot/.sandlot-activity.tmp` - await Bun.write(activityTmp, [ - '#!/bin/bash', - 'P="${CLAUDE_PROJECT_DIR%/}"', - 'echo "$1" > "$(dirname "$P")/.activity-$(basename "$P")"', - '', - ].join('\n')) - await $`chmod +x ${activityTmp}`.quiet() - await $`container exec --user ${USER} ${CONTAINER_NAME} bash -c ${"cp /sandlot/.sandlot-activity.tmp ~/.local/bin/sandlot-activity"}`.quiet() - await Bun.file(activityTmp).unlink() - - // Install statusline script (shows branch in Claude Code powerline) - const statuslineTmp = `${home}/.sandlot/.sandlot-statusline.tmp` - await Bun.write(statuslineTmp, [ - '#!/bin/bash', - 'input=$(cat)', - 'branch=$(echo "$input" | grep -oP \'"branch"\\s*:\\s*"\\K[^"]+\' | head -1)', - '[ -n "$branch" ] && printf \'\\033[36m⎇ %s\\033[0m\\n\' "$branch"', - '', - ].join('\n')) - await $`chmod +x ${statuslineTmp}`.quiet() - await $`container exec --user ${USER} ${CONTAINER_NAME} bash -c ${"cp /sandlot/.sandlot-statusline.tmp ~/.local/bin/sandlot-statusline"}`.quiet() - await Bun.file(statuslineTmp).unlink() + await installScript(home, "sandlot-activity", `#!/bin/bash\nP="\${CLAUDE_PROJECT_DIR%/}"\necho "$1" > "$(dirname "$P")/.activity-$(basename "$P")"\n`) + await installScript(home, "sandlot-statusline", `#!/bin/bash\ninput=$(cat)\nbranch=$(echo "$input" | grep -oP '"branch"\\s*:\\s*"\\K[^"]+' | head -1)\n[ -n "$branch" ] && printf '\\033[36m\u2387 %s\\033[0m\\n' "$branch"\n`) await $`container exec --user ${USER} ${CONTAINER_NAME} bash -c ${` mkdir -p ~/.claude