detached b6e3279

fix(demo): clean up the claude temp home through the container

The host `rm -rf` on the mktemp HOME cannot unlink subuid-owned files
that claude wrote as the container's demo user, and `2>/dev/null ||
true` hid that a credentials-bearing directory lingered in /tmp
indefinitely instead of just until reboot. Retry the removal through
the container, where the creating uid can unlink its own files, and
warn on stderr (without touching the script's exit status) if
anything still remains afterward.
commit
b6e32794cad0d81e2e9c9598ef6cbf1f3a90c609
author
brice · · 2026-07-24 12:46 UTC
parent
45b1180
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
1 file · +23 -4
M scripts/demo/run.sh +23 -4
@@ -7,10 +7,29 @@ install -d -m 0777 scripts/demo/out
77
88 CLAUDE_TMP=$(mktemp -d)
99 # claude writes files into the temp HOME as the container's demo user, which
10-# rootless docker maps to a subuid the host cannot delete; the rm then fails and
11-# leaves a dir in /tmp. Accepted (cleared on reboot); `|| true` keeps the script
12-# exit status clean. A container-based cleanup isn't worth the complexity.
13-trap 'rm -rf "$CLAUDE_TMP" 2>/dev/null || true' EXIT
10+# rootless docker maps to a subuid the host cannot delete directly. Clean up
11+# through the container first, where the creating uid can unlink its own
12+# files, then remove the (now-empty) temp dir from the host. This never
13+# suppresses a leftover: if anything still remains, it's reported so a
14+# credentials-bearing directory doesn't silently linger in /tmp.
15+cleanup() {
16+ # Every step here is best-effort: under `set -e`, an unguarded failure in an
17+ # EXIT trap would abort the trap early and replace the script's real exit
18+ # status with the failing cleanup command's. Guard each step with `|| true`
19+ # so cleanup always runs to completion and never masks the vhs run's result;
20+ # the final check below is what surfaces an unrecovered leftover.
21+ rm -rf "$CLAUDE_TMP" 2>/dev/null || true
22+ if [ -d "$CLAUDE_TMP" ]; then
23+ docker run --rm -v "$CLAUDE_TMP:/cleanup" --entrypoint sh vev-demo \
24+ -c 'rm -rf /cleanup/.claude /cleanup/.claude.json' 2>/dev/null || true
25+ rmdir "$CLAUDE_TMP" 2>/dev/null || true
26+ fi
27+ if [ -d "$CLAUDE_TMP" ]; then
28+ echo "warning: could not remove claude temp home, left at $CLAUDE_TMP" >&2
29+ fi
30+ return 0
31+}
32+trap cleanup EXIT
1433 mkdir -p "$CLAUDE_TMP/.claude"
1534 cp "$HOME/.claude/.credentials.json" "$CLAUDE_TMP/.claude/"
1635 cp scripts/demo/claude-settings.json "$CLAUDE_TMP/.claude/settings.json"
@@ -7,10 +7,29 @@ install -d -m 0777 scripts/demo/out
7 7
8 CLAUDE_TMP=$(mktemp -d)8 CLAUDE_TMP=$(mktemp -d)
9 # claude writes files into the temp HOME as the container's demo user, which9 # claude writes files into the temp HOME as the container's demo user, which
10-# rootless docker maps to a subuid the host cannot delete; the rm then fails and10+# rootless docker maps to a subuid the host cannot delete directly. Clean up
11-# leaves a dir in /tmp. Accepted (cleared on reboot); `|| true` keeps the script11+# through the container first, where the creating uid can unlink its own
12-# exit status clean. A container-based cleanup isn't worth the complexity.12+# files, then remove the (now-empty) temp dir from the host. This never
13-trap 'rm -rf "$CLAUDE_TMP" 2>/dev/null || true' EXIT13+# suppresses a leftover: if anything still remains, it's reported so a
14+# credentials-bearing directory doesn't silently linger in /tmp.
15+cleanup() {
16+ # Every step here is best-effort: under `set -e`, an unguarded failure in an
17+ # EXIT trap would abort the trap early and replace the script's real exit
18+ # status with the failing cleanup command's. Guard each step with `|| true`
19+ # so cleanup always runs to completion and never masks the vhs run's result;
20+ # the final check below is what surfaces an unrecovered leftover.
21+ rm -rf "$CLAUDE_TMP" 2>/dev/null || true
22+ if [ -d "$CLAUDE_TMP" ]; then
23+ docker run --rm -v "$CLAUDE_TMP:/cleanup" --entrypoint sh vev-demo \
24+ -c 'rm -rf /cleanup/.claude /cleanup/.claude.json' 2>/dev/null || true
25+ rmdir "$CLAUDE_TMP" 2>/dev/null || true
26+ fi
27+ if [ -d "$CLAUDE_TMP" ]; then
28+ echo "warning: could not remove claude temp home, left at $CLAUDE_TMP" >&2
29+ fi
30+ return 0
31+}
32+trap cleanup EXIT
14 mkdir -p "$CLAUDE_TMP/.claude"33 mkdir -p "$CLAUDE_TMP/.claude"
15 cp "$HOME/.claude/.credentials.json" "$CLAUDE_TMP/.claude/"34 cp "$HOME/.claude/.credentials.json" "$CLAUDE_TMP/.claude/"
16 cp scripts/demo/claude-settings.json "$CLAUDE_TMP/.claude/settings.json"35 cp scripts/demo/claude-settings.json "$CLAUDE_TMP/.claude/settings.json"

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close