anthropics / anthropics/claude-code

Windows/Git Bash: 85 per-function base64 evals make every Bash call pay ~5-9s; snapshot-creation 10s timeout silently forks sessions into fast/slow regimes

オープン
#89,580 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る
area:bash bug has repro platform:windows
主要言語
Python
スター
145k
フォーク
23.1k
PR マージ指標
PR 指標を取得中

説明

## Summary

On Windows + Git for Windows (MSYS bash), the Bash tool's shell-snapshot mechanism adds **~5–9 seconds to every Bash tool call**, and the snapshot-*creation* path has a timeout asymmetry that silently splits sessions into two performance regimes. Two coupled problems, both measured:

1. **Per-call cost:** the snapshot stores every captured shell function as its own `eval "$(echo '' | base64 -d)" > /dev/null 2>&1` line. On a machine whose login shell defines 145 functions (stock Git-for-Windows `git-completion.bash` — 144 of the 145), that is **85 base64-eval lines**, each paying an MSYS subshell fork (~16 ms) plus an external `base64` exec (~65 ms with real-time AV on). Re-sourced on **every** Bash tool call.
2. **Creation-timeout roulette:** snapshot creation runs the login shell under a hard **10,000 ms** timeout, while creation itself takes **~6 s idle** on this class of machine. Under load it times out → the session permanently falls back to per-call `bash -c -l` (the `-l` is added only when no snapshot was captured) — which is *faster* (~1.3 s/call) than snapshot mode (~6.5 s/call). Sessions randomly land in one regime at their first Bash call and stay there. A timed-out creation can still leave the snapshot file on disk, which makes forensics confusing (file present, never sourced).

## Environment

- Windows 11 Pro, Git for Windows (stock `/etc/profile.d/git-prompt.sh` → git-completion), Windows Defender real-time on
- Claude Code 2.1.237 (desktop app and CLI; behavior identical), snapshot files `~/.claude/shell-snapshots/snapshot-bash-*.sh`, 88,199 bytes / 85 evals each

## Measurements

Sourcing cost isolated (same snapshot, same machine, idle):

```
source full snapshot (85 evals) : 5,703 – 6,510 ms
same file, eval lines stripped : 88 ms <- 98.5% of cost is the eval lines
85 × $(:) fork-only control : 1,393 ms <- pure MSYS fork floor, AV-independent
85 × $(echo|base64 -d) : 6,853 ms (~81 ms/eval)
```

Corpus evidence (stream-parsed 9,473 clean serial Bash tool_use→tool_result deltas across 110 session transcripts / 35 days, one machine):

- Sessions in snapshot mode: floors 6.2–8.4 s, medians 8–15 s under load
- Sessions in `-l` fallback mode: floors 972–1,300 ms
- 39 of 83 sessions (n≥5) sat under a 2 s floor — i.e. **the busier the machine, the more sessions accidentally escape the tax**, which makes the cost look nondeterministic and very hard for users to attribute
- First call of a session ≈ 2× median (creation) — consistent with the 10 s deadline being marginal, not comfortable

## Suggested fixes (either helps; both are small)

1. **Batch the decode**: store all function bodies in one base64 blob (or plain `declare -f` text — which #50733 already requests for auditability) and decode once. Turns 85 forks+execs into ~1. Expected: ~6 s → well under 200 ms per call on this machine class.
2. **Rationalize the creation timeout**: either raise/scale it, or make the outcome consistent — right now timing out yields a *faster* session than succeeding, which is exactly backwards; and the partially-written snapshot file should be removed on timeout so file-presence matches behavior.

## Workaround for affected users (validated)

Git for Windows' `/etc/profile.d/git-prompt.sh` sources `~/.config/git/git-prompt.sh` *instead of* its completion-loading block when that file exists. A user-level override that replicates the stock prompt but skips `git-completion.bash` when `CLAUDECODE=1` is set (Claude Code sets it on the snapshot-creation shell) drops the snapshot to ~1 eval / 4.9 KB with the interactive prompt byte-identical. After deploying it: per-call floors converge to ~1.0–1.3 s in every new session. Happy to share the override file in a comment if useful.

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

調査の方向性

Start by locating the Bash shell-snapshot creation and per-call sourcing paths that produce ~/.claude/shell-snapshots/snapshot-bash-*.sh, then reproduce the timing behavior on Windows with Git Bash. Compare batched decoding and timeout handling, including cleanup of partially written snapshots; done means the per-call cost is reduced and timeout and successful-creation sessions behave consistently.

索引モデルが issue の本文から書いたものです。

評価

技術スタック
bash, git, python
領域
cli, operating-systems, performance
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
活発
明瞭さ
おおむね明確
初心者へのやさしさ
48/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。