Skip to content

Commit 56838f5

Browse files
committed
build(bootstrap): make the SessionStart prover hook synchronous
Flip .claude/hooks/session-start.sh from async to synchronous so session start blocks until Coq/Idris2/Zig are provisioned — the first prompt is guaranteed a working prover instead of racing the background install. The ~10-15 min Idris2 source build is paid once on a cold container; Claude Code on the web caches the container after the hook completes, so subsequent sessions hit the idempotent early-exits and start fast. Still fail-soft + idempotent, so a timeout-truncated cold build just resumes on the next session until the container is cached. The verbose build is logged to a file; only a one-line-per-prover summary reaches the transcript. Validated in-session: emits no async JSON; runs bootstrap to completion; prints the prover summary; no-ops silently when CLAUDE_CODE_REMOTE is unset. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AGFqWzByua4dKbA7W7oVsL
1 parent 04d3c3e commit 56838f5

1 file changed

Lines changed: 23 additions & 11 deletions

File tree

.claude/hooks/session-start.sh

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,35 @@
66
# methods provers (Coq / Idris2 / Zig) via scripts/bootstrap-provers.sh so
77
# a fresh remote session can run the proofs without a manual install dance.
88
#
9-
# ASYNC (non-blocking): the first stdout line opts into async mode, so the
10-
# session becomes usable immediately while the provers install in the
11-
# background. Coq (apt) and Zig (vendor binary) land in ~1–2 min; the
12-
# Idris2 source build takes ~10–15 min and finishes within asyncTimeout.
13-
# Everything is idempotent + fail-soft, so re-runs and blocked egress are
14-
# both safe. PATH for idris2 is persisted via $CLAUDE_ENV_FILE.
9+
# SYNCHRONOUS (blocking): the session does not start until the provers are
10+
# provisioned, so the first prompt is GUARANTEED a working Coq/Idris2/Zig
11+
# (no race where Claude runs a proof before its prover exists). The heavy
12+
# Idris2 source build (~10–15 min) is paid ONCE on a cold container; Claude
13+
# Code on the web caches the container after the hook completes, so every
14+
# later session hits the idempotent early-exits and starts fast. Everything
15+
# is fail-soft, so a blocked egress domain degrades gracefully instead of
16+
# wedging startup; and because the installers are idempotent, a hook cut
17+
# short by any timeout simply resumes on the next session until cached.
18+
# PATH for idris2 is persisted via $CLAUDE_ENV_FILE.
19+
#
20+
# (To return to non-blocking startup, restore async mode by emitting
21+
# `{"async": true, "asyncTimeout": 1200000}` as the first stdout line.)
1522

1623
set -uo pipefail
1724

18-
# Opt into async so session startup is not blocked by the ~15-min Idris2 build.
19-
echo '{"async": true, "asyncTimeout": 1200000}'
20-
2125
# Only meaningful in the remote (web) environment; devcontainers use the
2226
# postCreateCommand instead. No-op locally.
2327
if [ "${CLAUDE_CODE_REMOTE:-}" != "true" ]; then
2428
exit 0
2529
fi
2630

27-
exec "${CLAUDE_PROJECT_DIR:-.}/scripts/bootstrap-provers.sh" \
28-
> "${TMPDIR:-/tmp}/ephapax-bootstrap.log" 2>&1
31+
LOG="${TMPDIR:-/tmp}/ephapax-bootstrap.log"
32+
echo "[session-start] Provisioning provers (Coq/Idris2/Zig) before the session starts."
33+
echo "[session-start] First cold start builds Idris2 (~10-15 min, then cached). Full log: $LOG"
34+
35+
# Run synchronously; keep the verbose Idris2 build out of the session
36+
# transcript by logging to a file, then surface a one-line-per-prover summary.
37+
"${CLAUDE_PROJECT_DIR:-.}/scripts/bootstrap-provers.sh" > "$LOG" 2>&1 || true
38+
39+
echo "[session-start] Prover bootstrap finished:"
40+
grep -E '^\[bootstrap-provers\] (coq|idris2|zig):' "$LOG" || tail -n 3 "$LOG"

0 commit comments

Comments
 (0)