[BUG] Stack overflow: infinite recursion between Fw (spinnerTip updater) and P5 callback in main loop
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Claude Code CLI crashed with what appears to be infinite recursion / stack overflow
in the main loop's spinner tip updater. The stack trace shows Fw (spinnerTip
useCallback) and P5 (a useRef guard) calling each other repeatedly until the
process died.
### Stack trace (top frames, repeats indefinitely)
- (B:/~BUN/root/src/entrypoints/cli.js:9273:5663)
- PI (B:/~BUN/root/src/entrypoints/cli.js:512:63749)
- Fw (B:/~BUN/root/src/entrypoints/cli.js:512:76948)
- P5 (B:/~BUN/root/src/entrypoints/cli.js:512:76827)
- Fw (B:/~BUN/root/src/entrypoints/cli.js:512:76926)
- P5 (B:/~BUN/root/src/entrypoints/cli.js:512:76827)
- Fw (B:/~BUN/root/src/entrypoints/cli.js:512:77745)
- P5 (B:/~BUN/root/src/entrypoints/cli.js:512:76827)
... (Fw <-> P5 cycle repeats)
### Side signal (printed to stderr just before the crash)
Error: sandbox required but unavailable:
sandbox.failIfUnavailable is set — refusing to start without a working sandbox.
This sandbox message was printed immediately before the recursion crash, but
the actual termination cause is the stack overflow above, not the sandbox check.
### Suspected location
Around cli.js:512:76900 — the spinnerTip useCallback (Fw) guarded by a
useRef flag (P5.current). It looks like the guard is not being reset on
some code path, or the setAppState setter inside the .then() re-enters
synchronously and triggers another Fw call before P5.current is cleared.
### Environment
- Claude Code version: 2.1.120
- Model: Claude Opus 4.7 (1M context) —
claude-opus-4-7[1m] - OS: Windows 11 Pro 10.0.26200 (win32)
- Shell: Git Bash
- Runtime: Bun (
B:/~BUN/root/...) - Working dir: git repo, path contains non-ASCII characters
- Active MCP servers (many): filesystem, github, playwright, vibium,
sequential-thinking, TestAI-Prod, claude_ai_Gmail, Google_Drive,
Google_Calendar, notion, etc.
- bkit plugin active (SessionStart hook injecting context)
### Reproduction
Not reliably reproducible. Occurred once during a long-running session
with many active plugins/MCP servers and the bkit SessionStart hook
emitting a large context block. No specific user action triggered it —
the crash happened mid-session.
### Expected
Spinner tip update should be idempotent / debounced and never recurse
into itself. Even if setAppState triggers a re-render, the P5.current
guard should prevent re-entry.
### Actual
Fw and P5 recurse indefinitely, exhausting the stack and killing the CLI.
What Should Happen?
The CLI should remain stable during long-running sessions. Specifically:
- The spinner tip updater (
Fw) should be safely idempotent and protected
against re-entry. The useRef guard (P5.current) must be reliably
reset on all code paths — including when the inner setAppState call
triggers a synchronous re-render or when the underlying H07(...).then()
resolves/rejects unexpectedly.
- Even under adverse conditions (sandbox unavailable, MCP server timeouts,
large hook-injected context, many concurrent plugins), the main loop
should never enter unbounded recursion. A defensive depth limit or
debounce on spinner tip updates would prevent stack-overflow crashes.
- If the sandbox is genuinely required but unavailable
(sandbox.failIfUnavailable set), the CLI should exit cleanly with the
stderr message that's already being printed — not crash via stack
overflow afterward. The two failure modes appear entangled here.
- Ideally, an unhandled stack overflow in internal UI/state code should
surface a clear error to the user (e.g. "internal error: spinner tip
recursion — please report") rather than a raw minified stack trace,
so users can recover without losing session context.
Error Messages/Logs
### 1. Stack trace (printed on crash, repeats until stack exhausted)
- (B:/~BUN/root/src/entrypoints/cli.js:9273:5663)
- PI (B:/~BUN/root/src/entrypoints/cli.js:512:63749)
- Fw (B:/~BUN/root/src/entrypoints/cli.js:512:76948)
- P5 (B:/~BUN/root/src/entrypoints/cli.js:512:76827)
- Fw (B:/~BUN/root/src/entrypoints/cli.js:512:76926)
- P5 (B:/~BUN/root/src/entrypoints/cli.js:512:76827)
- Fw (B:/~BUN/root/src/entrypoints/cli.js:512:77745)
- P5 (B:/~BUN/root/src/entrypoints/cli.js:512:76827)
- Fw (B:/~BUN/root/src/entrypoints/cli.js:512:76926)
- P5 (B:/~BUN/root/src/entrypoints/cli.js:512:76827)
... (Fw <-> P5 alternation continues indefinitely)
### 2. stderr output emitted just before the crash
Error: sandbox required but unavailable:
sandbox.failIfUnavailable is set — refusing to start without a working sandbox.
### 3. Surrounding code context at cli.js:9273 (minified)
let j8 = hq.getSandboxUnavailableReason();
if (!j8) return;
if (hq.isSandboxRequired()) {
process.stderr.write(`
Error: sandbox required but unavailable: ${j8}
`+` sandbox.failIfUnavailable is set — refusing to start without a working sandbox.
`);
...
}
4. Additional notes
- No .claude/logs/ entries were generated for this crash (process died
before flush).
- No exit code captured — terminal showed the stack trace then returned to
the shell prompt.
- No core dump produced.
- The crash occurred mid-conversation; the immediately preceding user input
was a normal text message (not a tool invocation, not a slash command).
Steps to Reproduce
Note: I have NOT been able to reliably reproduce this crash. It occurred
once during a long-running session. Below is the best description of the
state at the time of the crash, in case it helps narrow down the trigger.
### Environment at time of crash
- Started Claude Code in a Windows 11 (Git Bash) terminal:
claude (in working dir C:\Users\win10_original\agiqa\agi-qa-workspace\tmkim,
a git repo with non-ASCII characters in the parent path)
- Session was running with the bkit plugin active, which injects a
large SessionStart hook context block (~several KB of system reminders,
skill listings, deferred tool listings) on every session start.
- Multiple MCP servers were configured and active:
filesystem, github, playwright, vibium, sequential-thinking,
TestAI-Prod, claude_ai_Gmail, claude_ai_Google_Drive,
claude_ai_Google_Calendar, notion, plugin_playwright_playwright.
- Model in use: Claude Opus 4.7 (1M context).
- Session had been active for an extended period with multiple turns,
tool uses, and large tool results in the context window.
### Last action before crash
- Sent a normal text message to the assistant (no slash command, no tool).
- The assistant began responding; mid-response, the CLI crashed with the
stack overflow shown in "Error Messages/Logs".
### What I tried for reproduction (none reproduced the crash)
- Restarted Claude Code in the same directory → worked normally.
- Opened a fresh session with the same MCP/plugin set → worked normally.
- Sent the same message that preceded the crash → no crash.
### Hypothesized triggers (unverified)
- Long session with many tool results may have inflated some internal
state that the spinner tip updater iterates over.
- Sandbox-unavailable condition (the stderr message printed just before
the crash) may have set the system into a state where Fw/P5 lost
their re-entry guard.
- Very large SessionStart hook context (bkit) producing a render burst
that re-triggered setAppState synchronously inside Fw.
If logs/replay artifacts would help, please advise what to capture next
time and I'll attach them on recurrence.
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
2.1.120
Claude Code Version
2.1.120
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
Warp
Additional Information
ERROR FKH is not a function. (In 'FKH(K)', 'FKH' is undefined)
B:/~BUN/root/src/entrypoints/cli.js:9273:5663
9270: ${K.join( )}
9271:
9272 }var oTf,mV7=1000,aTf=300,sTf=5000;var kCq=T(()=>{X8();v8();Tp();fb();uV7();q8();oN();oTf=(XmH(),Rq(WmH))});var [ScheduledTasks] teammate
: QV7={};P8(QV7,{useScheduledTasks:()=>eTf});function eTf({isLoading:H,assistantMode:q,setMessages:$}){let
K=mD6.useRef(H);K.current=H;let _=B4(),f=Uq(),A=Gw();mD6.useEffect(()=>{if(!VG()||Iq())return;let
z=(O)=>y5({value:tTf.resolveLoopDefaultFire(O),mode:"prompt",priority:"later",isMeta:!0,workload:kRH}),Y=void
0,M=vCq({onFire:z,onFireTask:(O)=>{if(O.agentId){let
w=cr(O.agentId,_.getState().tasks);if(w&&!aS(w.status)){tuH(w.id,O.prompt,A);return}h(
${O.agentId} gone, removing orphaned cron ${O.id}),n8H([O.id]);return}let D=ep_(O.kind==="loop"?Claude resuming /loop
wakeup (${gV7(new Date)}):Running scheduled task (${gV7(new Date)}));$((w)=>[...w,D]),z(O.prompt)},isLoading:()=>K.cur open in ${D}
rent,assistantMode:q,getJitterConfig:efH,isKilled:()=>!VG(),getExtraTasks:FV7&&Y?()=>FV7.getRoutineCronTasks(G9(),Y):void
0});return M.start(),()=>{M.stop()}},[q,$,_.getState,A])}function gV7(H){return
H.toLocaleString("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit"}).replace(/,? at |, /,"
").replace(/ ([AP]M)/,(q,$)=>$.toLowerCase())}var mD6,tTf,FV7=null;var
dV7=T(()=>{ER();X8();yq();mT();tS();zb();y78();kCq();fb();q8();g3();Dq();K9H();mD6=u(WH(),1),tTf=(XmH(),Rq(WmH))});var
rV7={};P8(rV7,{REPL:()=>hCq});function cV7(H){let
q=pD6.c(14),{showAllInTranscript:$,virtualScroll:K,searchBadge:_,suppressShowAll:f,status:A}=H,z=f===void
0?!1:f,Y=W1("app:toggleTranscript","Global","ctrl+o"),M=W1("transcript:toggleShowAll","Transcript","ctrl+e"),O;if(q[0]===
Symbol.for("react.memo_cache_sentinel"))O=Mc_(),q[0]=O;else O=q[0];let D=O,w=D?:"open in ${_8.arrowUp}${_8.arrowDown} scroll \xB7 [ to print output \xB7 v to ${w}
editor",j;if(q[1]===Symbol.for("react.memo_cache_sentinel"))j=f6.createElement(f6.Fragment,null,"Showing detailed
transcript"),q[1]=j;else j=q[1];let P;if(q[2]!==Y)P=f6.createElement(f6.Fragment,null,Y," to toggle"),q[2]=Y,q[3]=P;else
P=q[3];let W=_?"n/N to navigate":K?:z?v to
${w}:${M} to ${$?"collapse":"show all"},X;if(q[4]!==P||q[5]!==W)X=f6.createElement(v,{dimColor:!0},f6.createElement(t8 ${D} ${K}
,null,j,P,W)),q[4]=P,q[5]=W,q[6]=X;else X=q[6];let
J;if(q[7]===Symbol.for("react.memo_cache_sentinel"))J=f6.createElement(p,{flexGrow:1}),q[7]=J;else J=q[7];let
Z;if(q[8]!==_||q[9]!==A)Z=f6.createElement(OVf,{status:A,searchBadge:_}),q[8]=_,q[9]=A,q[10]=Z;else Z=q[10];let
L;if(q[11]!==X||q[12]!==Z)L=f6.createElement(p,{noSelect:!0,alignItems:"center",alignSelf:"center",borderTopDimColor:!0,b
orderBottom:!1,borderLeft:!1,borderRight:!1,borderStyle:"single",marginTop:1,paddingLeft:2,width:"100%"},X,J,Z),q[11]=X,q
[12]=Z,q[13]=L;else L=q[13];return L}function OVf(H){let q=pD6.c(6),{status:$,searchBadge:K}=H;if($){let
f;if(q[0]!==$)f=f6.createElement(v,null,$," "),q[0]=$,q[1]=f;else f=q[1];return f}if(K){let
f;if(q[2]!==K.count||q[3]!==K.current)f=f6.createElement(v,{dimColor:!0},K.current,"/",K.count,"
"),q[2]=K.count,q[3]=K.current,q[4]=f;else f=q[4];return f}let
_;if(q[5]===Symbol.for("react.memo_cache_sentinel"))_=f6.createElement(v,{dimColor:!0},"verbose "),q[5]=_;else
_=q[5];return _}function DVf({jumpRef:H,count:q,current:$,onClose:K,onCancel:_,setHighlight:f,initialQuery:A}){let{query:
z,cursorOffset:Y,handleKeyDown:M,handlePaste:O}=z0({isActive:!0,initialQuery:A,onExit:()=>K(z),onCancel:_}),[D,w]=s8.useS
tate("building");s8.useEffect(()=>{let X=!0,J=H.current?.warmSearchIndex;if(!J){w(null);return}return
w("building"),J().then((Z)=>{if(!X)return;if(Z<20)w(null);else
w({ms:Z}),setTimeout(()=>X&&w(null),2000)}),()=>{X=!1}},[]);let
j=D!=="building";s8.useEffect(()=>{if(!j)return;H.current?.setSearchQuery(z),f(z)},[z,j]);let P=Y,W=P<z.length?z[P]:"
";return f6.createElement(p,{borderTopDimColor:!0,borderBottom:!1,borderLeft:!1,borderRight:!1,borderStyle:"single",margi
nTop:1,paddingLeft:2,tabIndex:0,autoFocus:!0,onKeyDown:M,onPaste:O,width:"100%",noSelect:!0},f6.createElement(v,null,"/")
,f6.createElement(v,null,z.slice(0,P)),f6.createElement(v,{inverse:!0},W),P<z.length&&f6.createElement(v,null,z.slice(P+1
)),f6.createElement(p,{flexGrow:1}),D==="building"?f6.createElement(v,{dimColor:!0},"indexing\u2026
"):D?f6.createElement(v,{dimColor:!0},"indexed in ",D.ms,"ms "):q===0&&z?f6.createElement(v,{color:"error"},"no matches
"):q>0?f6.createElement(v,{dimColor:!0},$,"/",q," "):null)}function nV7(H){let
q=pD6.c(6),{isAnimating:$,title:K,disabled:_,noPrefix:f}=H,A=xY(),[z,Y]=s8.useState(0),M,O;if(q[0]!==_||q[1]!==$||q[2]!==
f||q[3]!==A)M=()=>{if(_||f||!$||!A)return;let
w=setInterval(jVf,wVf,Y);return()=>clearInterval(w)},O=[_,f,$,A],q[0]=_,q[1]=$,q[2]=f,q[3]=A,q[4]=M,q[5]=O;else
M=q[4],O=q[5];s8.useEffect(M,O);let D=$?iV7[z]??lV7:lV7;return o9H(_?null:f?K:),null}function jVf(H){return [REPL:mount] REPL mounted,
H(PVf)}function PVf(H){return(H+1)%iV7.length}function
hCq({commands:H,debug:q,initialTools:$,initialMessages:K,pendingHookMessages:_,initialFileHistorySnapshots:f,initialConte
ntReplacements:A,initialAgentName:z,initialAgentColor:Y,mcpClients:M,dynamicMcpConfig:O,autoConnectIdeFlag:D,strictMcpCon
fig:w=!1,systemPrompt:j,appendSystemPrompt:P,onBeforeQuery:W,onTurnComplete:X,disabled:J=!1,mainThreadAgentDefinition:Z,d
isableSlashCommands:L=!1,remoteSessionConfig:G,directConnectConfig:V,sshSession:k,thinkingConfig:N}){let
y=!!G,I=s8.useMemo(()=>yH(process.env.CLAUDE_CODE_DISABLE_TERMINAL_TITLE),[]),S=s8.useMemo(()=>!1,[]),C=s8.useMemo(()=>yH
(process.env.CLAUDE_CODE_DISABLE_VIRTUAL_SCROLL),[]),B=!1;s8.useEffect(()=>{return h(
disabled=${J}),()=>h("[REPL:unmount] REPL approve ${E7[0].tool.name}
unmounting")},[J]);let[x,R]=s8.useState(Z),U=w8((j8)=>j8.toolPermissionContext),F=w8((j8)=>j8.verbose),g=w8((j8)=>j8.mcp)
,Q=w8((j8)=>j8.plugins),i=w8((j8)=>j8.agentDefinitions),n=w8((j8)=>j8.initialMessage),o=Ss(),qH=w8((j8)=>j8.expandedView)
==="tasks",r=w8((j8)=>j8.pendingWorkerRequest),HH=w8((j8)=>j8.pendingSandboxRequest),t=w8((j8)=>j8.teamContext),zH=w8((j8
)=>j8.tasks),YH=w8((j8)=>j8.workerSandboxPermissions),PH=w8((j8)=>j8.elicitation),s=w8((j8)=>j8.ultraplanPendingChoice),a
=w8((j8)=>j8.ultraplanLaunchPending),KH=w8((j8)=>j8.viewingAgentTaskId),e=Uq(),AH=KH?zH[KH]:void
0,_H=mP(AH)&&AH.retain&&!AH.diskLoaded;s8.useEffect(()=>{if(!KH||!_H)return;let
j8=KH;k5H(S5(j8)).then((r8)=>{e((_6)=>{let H$=_6.tasks[j8];if(!mP(H$)||H$.diskLoaded||!H$.retain)return _6;let
h$=H$.messages??[],MK=new Set(h$.map((lK)=>lK.uuid)),$K=r8?r8.messages.filter((lK)=>!MK.has(lK.uuid)):[];return{..._6,tas
ks:{..._6.tasks,[j8]:{...H$,messages:[...$K,...h$],diskLoaded:!0}}}})})},[KH,_H,e]);let
DH=B4(),MH=s8.useMemo(()=>qh(()=>DH.getState(),e),[DH,e]),XH=s8.useMemo(()=>l0H(()=>DH.getState(),e),[DH,e]),jH=vi(),GH=V
w(),[vH,LH]=s8.useState(H);aL7(y?void 0:G9(),LH);let VH=w8((j8)=>j8.isBriefOnly),IH=s8.useMemo(()=>tG(U),[U,VH]);hj_(),yj
_();let[BH,sH]=s8.useState(O),dH=s8.useCallback((j8)=>{sH(j8)},[sH]),[z8,M8]=s8.useState("prompt"),[TH,CH]=s8.useState(!1
),[mH,xH]=s8.useState(!1),[aH,rH]=s8.useState(""),nH=s8.useRef(0),cH=s8.useRef(void
0),tH=s8.useRef(!1),{addNotification:V8,removeNotification:B8}=f_(),H6=AVf,d8=nL7(M,g.clients),[iH,x8]=s8.useState(void
0),[UH,f8]=s8.useState(null),[kH,oH]=s8.useState(null),[O8,L8]=s8.useState(!1),[fH,wH]=s8.useState(()=>{return!1}),uH=w8(
(j8)=>j8.showRemoteCallout),[bH,eH]=s8.useState(()=>sG7());uT7(),pT7(),CT7({ideSelection:iH,mcpClients:d8,ideInstallation
Status:kH}),k07({mcpClients:d8}),E07(),$T7(),fT7(),Mf6(),XT7(GH),rT7(),sT7(),ZT7(GH),TT7(),ST7(),NT7(),_Vf(),SG7(),FG7(),
lG7(),S07(),QT7();let{recommendation:RH,handleResponse:T8}=d07(),{recommendation:D8,handleResponse:c8}=o07(),{pending:U8,
handleAction:l6,skipForSession:h6}=KVf(),Fq=s8.useMemo(()=>{return[...IH,...$]},[IH,$]);oO6({enabled:!y}),$Z7({enabled:!y
});let Aq=$M_();s8.useEffect(()=>{if(y)return;OT7(e)},[e,y]),s8.useEffect(()=>{let j8=setTimeout(vV7,500);return()=>clear
Timeout(j8)},[]),rG7(y?ECq:d8,U.mode),s8.useEffect(()=>{_hq(U.mode)},[U.mode]),qL7(e,K,{enabled:!y});let
O$=m56(Fq,g.tools,U),{tools:fK,allowedAgentTypes:F6}=s8.useMemo(()=>{if(!x)return{tools:O$,allowedAgentTypes:void 0};let
j8=Gd(x,O$,!1,!0);return{tools:j8.resolvedTools,allowedAgentTypes:j8.allowedAgentTypes}},[x,O$]),Pq=s8.useRef(fK);Pq.curr
ent=fK;let SK=s8.useMemo(()=>{if(!wP())return fK;let j8=new
Set(fK.map((_6)=>_6.name)),r8=izH().filter((_6)=>!j8.has(_6.name));return r8.length>0?[...fK,...r8]:fK},[fK]),pK=CIq(vH,Q
.commands),I7=CIq(pK,g.commands),gq=s8.useMemo(()=>L?[]:I7,[L,I7]);qw7(y?ECq:g.clients),zZ7(y?ECq:g.clients,x8);let[D4,w4
]=s8.useState([]),[p1,l9]=s8.useState(null);s8.useEffect(()=>{if(p1&&!p1.isStreaming&&p1.streamingEndedAt){let
r8=30000-(Date.now()-p1.streamingEndedAt);if(r8>0){let _6=setTimeout(l9,r8,null);return()=>clearTimeout(_6)}else
l9(null)}},[p1]);let[z7,pA]=s8.useState(null),B1=s8.useRef(null);B1.current=z7;let CD=s8.useRef(null),pw=s8.useRef(()=>{}
),_9=s8.useRef(()=>{}),N3=s8.useRef(null),qW=s8.useRef(null),Bw=s8.useRef(0),jA=s8.useRef(new zSq).current,zz=s8.useSyncE
xternalStore(jA.subscribe,jA.getSnapshot),[ff,S9]=s8.useState(G?.hasInitialPrompt??!1),B_=zz||ff,[PA,$1]=s8.useState(void
0),Nf=s8.useRef(0),K1=s8.useRef(!1),WA=s8.useRef(0),Af=s8.useRef(0),sY=s8.useRef(null),lO=s8.useCallback(()=>{WA.current
=Date.now(),Af.current=0,sY.current=null},[]),Fj=s8.useRef(!1);if(zz&&!Fj.current)lO();Fj.current=zz;let
FM=s8.useCallback((j8)=>{if(S9(j8),j8)lO()},[lO]),tY=s8.useRef(null),bD=s8.useRef(void 0),zY=s8.useRef(void 0),$W=1500,[X
A,D5]=s8.useState(!1);s8.useEffect(()=>{if(o$())r3K().then((j8)=>{if(j8)V8({key:"tmux-mouse-hint",text:j8,priority:"low"}
)});o3K().then((j8)=>{if(j8)V8({key:"tmux-focus-hint",text:j8,priority:"low"})})},[]);let[nO,gj]=s8.useState(!1);s8.useEf
fect(()=>{},[]);let[J6,P$]=s8.useState(null),LK=s8.useRef(null),oK=s8.useCallback((j8)=>{if(j8?.isLocalJSXCommand){let{cl
earLocalJSX:r8,..._6}=j8;LK.current={..._6,isLocalJSXCommand:!0},P$(_6);return}if(LK.current){if(j8?.clearLocalJSX){LK.cu
rrent=null,P$(null);return}return}if(j8?.clearLocalJSX){P$(null);return}P$(j8)},[]),[aK,f9]=s8.useState(()=>new
Map),a1=s8.useCallback((j8)=>{f9((r8)=>mZ7(r8,j8))},[]),[E7,Q$]=s8.useState([]),ZK=s8.useMemo(()=>GD7(Q$),[Q$]),[b4,_4]=s
8.useState(null),[cK,BA]=s8.useState([]),[n4,EY]=s8.useState([]),Uw=s8.useRef(new
Map),Qj=w8((j8)=>j8.settings.terminalTitleFromRename)!==!1,rf=s8.useSyncExternalStore($hq,()=>Qj?XD(E8()):void
0);s8.useEffect(()=>{return Hhq(()=>{let j8=GcH();if(!j8)return;e((r8)=>{if(r8.standaloneAgentContext?.name===j8)return
r8;return{...r8,standaloneAgentContext:{...r8.standaloneAgentContext,name:j8}}})})},[e]);let[z_,dj]=s8.useState(),xD=s8.u
seRef((K?.length??0)>0),_L=x?.agentType,_1=rf??_L??z_??"Claude Code",of=E7.length>0||n4.length>0||r||HH,Ef=J6?.isLocalJSX
Command===!0&&J6?.jsx!=null,uD=s8.useMemo(()=>u76(zH),[zH]),KW=of||Ef?"waiting":B_||uD?"busy":"idle",gM=s8.useMemo(()=>jz
7(zH),[zH]),_W=KW==="idle"&&gM?"busy":KW,JA=KW==="busy";s8.useEffect(()=>{if(KW==="busy")return
_D7(),()=>fD7()},[KW]);let w5=KW!=="waiting"?void 0:E7.length>0?:r?"workerrepinScroll(${r8}, force=${j8}): yanking from
request":HH?"sandbox request":Ef?"dialog open":"input
needed";s8.useEffect(()=>{CI8({status:_W,waitingFor:w5})},[_W,w5]);let QM=$77(zH),kK=jc8();s8.useEffect(()=>{oy_({tasks:Q
M.count,queued:kK,kinds:QM.kinds})},[QM.count,kK,QM.kinds.join(",")]);let E3=S8("tengu_terminal_sidebar",!1)&&(y8().showS
tatusInTerminalTab??!1),ex=w8((j8)=>j8.postTurnSummary?.status_detail);Ng8(I||!E3?null:KW,ex),s8.useEffect(()=>{return
bTK(ZK),()=>xTK()},[ZK]);let[R4,ih]=s8.useState(K??[]),zf=s8.useRef(R4),N0=s8.useRef(!1),U_=s8.useCallback((j8)=>{let
r8=zf.current,_6=typeof
j8==="function"?j8(zf.current):j8;if(zf.current=_6,_6.length<Nf.current)Nf.current=0,K1.current=!1,$1(void 0);else
if(_6.length>r8.length&&K1.current){let
H$=_6.length-r8.length;if((r8.length===0||_6[0]===r8[0]?_6.slice(-H$):_6.slice(0,H$)).some(A98))K1.current=!1;else
Nf.current=_6.length}ih(_6)},[]),U5=s8.useCallback((j8)=>U_((r8)=>lO6(r8,j8)),[U_]);BG7(s8.useCallback((j8)=>U_((r8)=>[..
.r8,$6({content:LA6(j8),isMeta:!0})]),[U_]));let kX=s8.useCallback((j8)=>{if(j8!==void
0)Nf.current=zf.current.length,K1.current=!0;else
K1.current=!1;$1(j8)},[]),{dividerIndex:NX,dividerYRef:fL,onScrollAway:CV,onRepin:KN,jumpToNew:Fs,shiftDivider:iO}=fe_(R4
.length);xG7(R4,U_,B_,Bw,!y);let[E0,FH]=s8.useState(null),lH=s8.useRef(E0);lH.current=E0;let
o8=s8.useRef(null),H8=s8.useMemo(()=>Ae_(R4,NX),[NX,R4.length]),F8=s8.useCallback((j8=!1,r8="?")=>{if(!j8&&!xf("autoScrol
lEnabled",!0).value)return;let _6=N3.current;if(_6&&!_6.isSticky())h(
scrollTop=${_6.getScrollTop()} (max=${Math.max(0,_6.getScrollHeight()-_6.getViewportHeight())}));if(_6?.scrollToBottom()
,KN(),lH.current!==null)FH(null)},[KN]),y6=R4.at(-1),G6=y6!=null&&A98(y6);s8.useEffect(()=>{if(G6)F8(!1,"lastMsgIsHuman")
},[G6,y6,F8]);let{maybeLoadOlder:bq}=YVf,sq=s8.useCallback((j8,r8)=>{if(Bw.current=Date.now(),j8)KN();else
CV(r8)},[KN,CV,bq]),k_=UJ7(_,U_),[Yf,U1]=s8.useState(null);s8.useState(()=>{return H$6(pr6()),null});let
O_=s8.useRef(eq6()),i4=GP_(),n_=s8.useCallback(()=>D5(!1),[]),v4=Ei(n_,$W),Uz=s8.useRef(null),Z9=s8.useCallback((j8)=>{if
(H6(O_.current,j8))return;if(O_.current===""&&j8!==""&&Date.now()-Bw.current>=MVf)F8(!1,"typedIntoEmpty");O_.current=j8,H
$6(j8),wqH.recordUserActivity(),TOH(!0);let r8=j8.trim().length>0;if(D5(r8),r8)v4();else
v4.cancel()},[D5,F8,H6,v4]),[Yz,rO]=s8.useState("prompt"),[fW,rh]=s8.useState(),mD=s8.useCallback((j8)=>{let r8=new
Set(j8.slash_commands);LH((_6)=>_6.filter((H$)=>r8.has(H$.name)||pEq.has(H$))),e((_6)=>_6.mainLoopModel===j8.model?_6:{..
._6,mainLoopModel:j8.model})},[LH,e]),[h0,_N]=s8.useState(new
Set),wI=s8.useCallback((j8)=>{_N((r8)=>{switch(j8.action){case"add":{let _6=new Set(r8);for(let H$ of
j8.ids)_6.add(H$);return _6}case"remove":{let _6=new Set(r8);for(let H$ of j8.ids)_6.delete(H$);return
_6.size===r8.size?r8:_6}case"clear":return r8.size>0?new Set:r8}})},[]),EX=s8.useRef(!1),y0=s8.useRef(0),oh=s8.useRef([])
,yU=s8.useRef(0),uc=s8.useCallback((j8)=>{y0.current+=j8;let r8=oh.current;if(j8>0&&r8.length>0){let
_6=r8.at(-1);if(_6.outputTokens==null)_6.lastTokenTime=Date.now(),_6.endResponseLength=y0.current}},[]),JVH=s8.useCallbac
k(()=>{y0.current=0},[]),uKH=s8.useCallback((j8)=>{if(j8.type==="start"){let r8=Date.now(),_6=y0.current;oh.current.push(
{id:j8.id,ttftMs:j8.ttftMs,firstTokenTime:r8,lastTokenTime:r8,responseLengthBaseline:_6,endResponseLength:_6})}else{let
r8=j8.id!=null?oh.current.find((_6)=>_6.id===j8.id):oh.current.findLast((_6)=>_6.id==null);if(r8){if(r8.outputTokens=j8.o
utputTokens,r8.lastTokenTime=Date.now(),j8.id==null)y0.current=Math.max(y0.current,r8.responseLengthBaseline+j8.outputTok
ens*4)}}},[]),SU=fJ7({config:G,setMessages:U_,setIsLoading:FM,onInit:mD,setToolUseConfirmQueue:ZK,tools:Fq,setStreamingTo
olUses:w4,setStreamMode:Pz8,setInProgressToolUseIDs:wI,recordApiMetricsEvent:uKH,permissionMode:U.mode}),gs=MJ7({config:V
,setMessages:U_,setIsLoading:FM,setToolUseConfirmQueue:ZK,tools:Fq,permissionMode:U.mode}),RU=wJ7({session:k,setMessages:
U_,setIsLoading:FM,setToolUseConfirmQueue:ZK,tools:Fq,permissionMode:U.mode}),AW=s8.useMemo(()=>RU.isRemoteMode?e16("ssh"
,RU,!1):gs.isRemoteMode?e16("direct",gs,!1):SU.isRemoteMode?e16("ccr",SU,G?.viewerOnly??!1,G?.sessionId):aLq,[RU,gs,SU,G?
.viewerOnly,G?.sessionId]);s8.useEffect(()=>{let j8=AW.isRemoteMode?AW:null,r8=AW.isRemoteMode&&AW.kind==="ccr"?"ccr-api"
:"local-jsonl",_6=COH();if(_6.remote!==j8||_6.transcriptSource!==r8)HW6({..._6,remote:j8,transcriptSource:r8})},[AW]);let
[UA,O2]=s8.useState({}),[jI,mKH]=s8.useState(0),[PI,bV]=s8.useState(null),mc=!(w8((j8)=>j8.settings.prefersReducedMotion)
??!1)&&!FjK(),WI=s8.useCallback((j8)=>{if(!mc)return;bV(j8)},[mc]),VZ=PI&&mc?PI.substring(0,PI.lastIndexOf(
9273 )+1)||null:null,[xV,Qs]=s8.useState(0),[ds,Hu]=s8.useState(!1),[QMH,cs]=s8.useState(void Worktree creation took ${r8}s. For large repos, set
: 0),[ls,pKH]=s8.useState(!1),[dMH,fN]=s8.useState(bMH.randomUUID()),[IU,vZ]=s8.useState(null),pc=s8.useCallback((j8)=>{let
r8=eO7(j8,VP);if(r8)vZ(r8)},[]),BKH=s8.useRef(xV);BKH.current=xV;let[ns]=s8.useState(()=>({current:IhK(K,A)})),[CU]=s8.u
seState(()=>({current:oQK(K??[])})),[Bc,zW]=s8.useState(y8().hasAcknowledgedCostThreshold),[Uc,D2]=s8.useState(!1),[h8,i6
]=s8.useState(!1),X$=s8.useRef("INSERT");s8.useEffect(()=>{if(s&&Uc)D2(!1)},[s,Uc]);let j4=xY(),f4=s8.useRef(j4);f4.curre
nt=j4;let[f1]=wK(),P5=s8.useRef(!1),Fw=s8.useCallback(()=>{if(P5.current)return;P5.current=!0;let
j8=zf.current.slice(gc.current);for(let r8 of d9q(j8))QKH.current.add(r8);gc.current=zf.current.length,H07({theme:f1,read
FileState:bU.current,bashTools:QKH.current}).then(async(r8)=>{if(r8){let _6=await
r8.content({theme:f1});e((H$)=>({...H$,spinnerTip:_6})),q07(r8)}else e((_6)=>{if(_6.spinnerTip===void 0)return
_6;return{..._6,spinnerTip:void 0}})})},[e,f1]),LA=s8.useCallback(()=>{FM(!1),kX(void
0),y0.current=0,oh.current=[],yU.current++,bV(null),w4([]),p3q(),Pz8("responding"),Fw(),rr(),go8()},[Fw]),w2=s8.useMemo((
)=>XJH(zH).some((j8)=>j8.status==="running"),[zH]);s8.useEffect(()=>{if(!w2&&tY.current!==null){let
j8=Date.now()-tY.current,r8=bD.current;tY.current=null,bD.current=void
0,U_((_6)=>[..._6,bLq(j8,r8,$q(_6,HKH))])}},[w2,U_]);let AL=s8.useRef(!1);s8.useEffect(()=>{{if(U.mode!=="auto"){AL.curre
nt=!1;return}if(AL.current)return;if((y8().autoPermissionsNotificationCount??0)>=3)return;let
_6=setTimeout((H$,h$)=>{H$.current=!0,a8((MK)=>{let $K=MK.autoPermissionsNotificationCount??0;if($K>=3)return
MK;return{...MK,autoPermissionsNotificationCount:$K+1}}),h$((MK)=>[...MK,f5(_O6,"warning")])},800,AL,U_);return()=>clearT
imeout(_6)}},[U.mode,U_]);let ClH=s8.useRef(!1),cMH=s8.useRef(!1);s8.useEffect(()=>{if(cMH.current)return;let
j8=q5();if(!j8?.creationDurationMs||j8.usedSparsePaths)return;if(j8.creationDurationMs<15000)return;cMH.current=!0;let
r8=Math.round(j8.creationDurationMs/1000);U_((_6)=>[..._6,f5(
\worktree.sparsePaths\ in .claude/settings.json to check out only the directories you need \u2014 e.g. \{"worktree": .
{"sparsePaths": ["src", "packages/foo"]}}\,"info")])},[U_]);let{onBeforeQuery:UKH,onTurnComplete:LVH,onSessionRestoredtoolJ
:FKH,render:iW8,ownsInput:ZVH}=XJ7({enabled:S,setMessages:U_,setInputValue:Z9,setToolJSX:oK,resultDedupState:CU.current})
,lMH=(!J6||J6.showSpinner===!0)&&E7.length===0&&n4.length===0&&(B_||PA||w2||jc8()>0)&&!r&&(!VZ||VH),is=E7.length>0||n4.le
ngth>0||cK.length>0||PH.queue.length>0||YH.queue.length>0;DD7({sandboxHost:cK[0]?.hostPattern.host,promptTitle:n4[0]?.tit
le,elicitationServer:PH.queue[0]?.serverName,workerSandboxHost:YH.queue[0]?.host});let nMH=qG7({hasActivePrompt:is,otherS
urveyActive:!1}),gKH=_G7(R4,B_,is,{enabled:!y}),S0=eZ7(R4,B_,is,{enabled:!y,otherSurveyActive:nMH.state!=="closed"||gKH.s
tate!=="closed"}),GVH=nZ7(R4,B_,jI,"session",is,nMH.state!=="closed"||gKH.state!=="closed"||S0.state!=="closed"),uV=OV7(R
4,jI),blH=s8.useMemo(()=>({...GVH,handleSelect:(j8)=>{if(kVH.current=!1,GVH.handleSelect(j8),j8==="bad"&&qV7("feedback_su
rvey_bad"))dKH("feedback_survey_bad"),kVH.current=!0}}),[GVH]),rW8=$Vf(R4,B_,is,nMH.state!=="closed"||blH.state!=="closed
"||gKH.state!=="closed"||S0.state!=="closed");RZ7({autoConnectIdeFlag:D,ideToInstallExtension:UH,setDynamicMcpConfig:sH,s
etShowIdeOnboarding:L8,setIDEInstallationState:oH}),X07(f,(j8)=>e((r8)=>({...r8,fileHistory:j8})));let
oW8=s8.useCallback(async(j8,r8,_6)=>{let H$=performance.now();try{let h$=hz8(r8.messages),MK=mO8();await
q0H("resume",{getAppState:()=>DH.getState(),setAppState:e,signal:AbortSignal.timeout(MK)});let{agentDefinition:$K}=HVH(r8
.agentSetting,Z,i);R($K),e((F1)=>({...F1,agent:$K?.agentType}));let lK=await
yb("resume",{sessionId:j8,agentType:$K?.agentType,model:GH});if(h$.push(...lK),_6==="fork")aBK(r8,JJ(j8));else
Hr8(r8,JJ(j8));if(r8.fileHistorySnapshots)o66(r8);if(e((F1)=>({...F1,standaloneAgentContext:AW8(r8.agentName,r8.agentColo
r)})),Xv(r8.agentName),sW8(h$,r8.projectPath??Kq()),_6!=="fork")oMH.current.current=I38(h$,Fq);LA(),pA(null),fN(j8);let
q$=f7q(j8);r18(),EvH(),x0(JJ(j8),r8.fullPath?BD6.dirname(r8.fullPath):null);let{renameRecordingForSession:Y_}=await
Promise.resolve().then(() => (_W8(),WZ7));if(await Y_(),await aB(),fW8(r8,e),uO8(),Zs(r8),xD.current=!0,dj(void
0),_6!=="fork")JZ7(r8.worktreeSession===void
0?r8.projectPath:r8.worktreeSession?.worktreePath),zW8(r8.worktreeSession,r8.projectPath),Ls(),GMq({abortController:new
AbortController,taskRegistry:MH}),$l(DN().map((F1)=>F1.id)),BIq(h$);else{let F1=q5();if(F1)BR(F1)}if(q$)mnH(q$);if(ns.cur
rent&&_6!=="fork")ns.current=Il8(h$,r8.contentReplacements??[]);if(U_(()=>h$),oK(null),Z9(""),_6!=="fork")pc(h$);d("tengu
_session_resumed",{entrypoint:_6,success:!0,resume_duration_ms:Math.round(performance.now()-H$)})}catch(h$){throw
d("tengu_session_resumed",{entrypoint:_6,success:!1,failure_reason:"processing_error",error_name:n6(h$).name}),h$}},[LA,e
,MH,pc]),[Fc]=s8.useState(()=>Db(Np)),bU=s8.useRef(Fc),QKH=s8.useRef(new Set),gc=s8.useRef(0),xlH=s8.useRef(new
Set),ulH=s8.useRef(new Map),TVH=s8.useRef(new Set),iMH=s8.useRef(new Map),VVH=s8.useRef(void
0),rMH=s8.useRef(AAH()),aW8=s8.useRef(Df8()),oMH=s8.useRef(iFH()),sW8=s8.useCallback((j8,r8)=>{let
_6=qpH(j8,r8,Np);bU.current=tbH(bU.current,_6);for(let H$ of
d9q(j8))QKH.current.add(H$)},[e]);s8.useEffect(()=>{if(K&&K.length>0)sW8(K,Kq()),GMq({abortController:new AbortController
,taskRegistry:MH}),BIq(K),pc(K),oMH.current.current=I38(K,Fq),FKH(K)},[]);let{status:tW8,reverify:vVH}=gJ7(),[qu,dKH]=s8.
useState(null),kVH=s8.useRef(!1),[mlH,plH]=s8.useState(null),[BlH,UlH]=s8.useState(!1),FlH=!B_&&ls;function
aMH(){if(BlH||mlH)return;if(ds)return"message-selector";if(XA)return;if(cK[0])return"sandbox-permission";let
j8=!J6||J6.shouldContinueAnimation;if(j8&&E7[0])return"tool-permission";if(j8&&n4[0])return"prompt";if(j8&&YH.queue[0])re
turn"worker-sandbox-permission";if(j8&&PH.queue[0])return"elicitation";if(j8&&FlH)return"cost";if(j8&&IU)return"resume-re
turn";if(j8&&!B_&&s)return"ultraplan-choice";if(j8&&!B_&&a)return"ultraplan-launch";if(k7()){if(j8&&uH)return"remote-call
out";return}if(j8&&O8)return"ide-onboarding";if(j8&&uH)return"remote-callout";if(j8&&RH)return"lsp-recommendation";if(j8&
&D8)return"plugin-hint";if(j8&&bH)return"desktop-upsell";return}let
W5=aMH(),eW8=XA&&(cK[0]||E7[0]||n4[0]||YH.queue[0]||PH.queue[0]||FlH);zY.current=W5,s8.useEffect(()=>{if(!B_)return;let
j8=W5==="tool-permission",r8=Date.now();if(j8&&sY.current===null)sY.current=r8;else
if(!j8&&sY.current!==null)Af.current+=r8-sY.current,sY.current=null},[W5,B_]);let
glH=s8.useRef(W5),FA=s8.useRef(null);s8.useLayoutEffect(()=>{let
j8=glH.current==="tool-permission",r8=W5==="tool-permission";if(glH.current=W5,j8===r8)return;let
_6=N3.current;if(r8)FA.current=_6&&!_6.isSticky()?_6.getScrollTop():null,F8(!0,"permissionDialogAppear");else
if(FA.current!==null)_6?.scrollTo(FA.current),FA.current=null;else F8(!0,"permissionDialogDismiss")},[W5,F8]);let
rs=J6?.jsx!=null,H28=s8.useRef(rs);s8.useLayoutEffect(()=>{if(H28.current!==rs&&(N3.current?.isSticky()??!0))F8(!1,
sxDialog\u2192${rs});H28.current=rs},[rs,F8]);function NVH(){if(W5==="elicitation")return;if(h([onCancel]
focusedInputDialog=${W5} streamMode=${Xd.getState().mode}`),jA.forceEnd(),PI?.trim())U_((j8)=>[...j8,Zw({content:PI})]);i
f(LA(),W5==="tool-permission")E7[0]?.onAbort(),ZK([]);else if(W5==="prompt"){for(let j8 of n4)j8.reject(Error("Prompt
cancelled by user"));EY([]),z7?.abort("user-cancel")}else if(AW.isRemoteMode)AW.cancelRequest();else
z7?.abort("user-cancel");pA(null),LVH(zf.current,!0)}let q28=s8.useCallback(()=>{let
j8=Wc8(O_.current,0);if(!j8)return;if(Z9(j8.text),rO("prompt"),j8.images.length>0)O2((r8)=>{let _6={...r8};for(let H$ of
j8.images)_6[H$.id]=H$;return _6})},[Z9,rO,O2]),$28={setToolUseConfirmQueue:ZK,onCancel:NVH,getConnectionSummary:()=>CD.c
urrent?.summary(),onAgentsKilled:()=>U_((j8)=>[...j8,qB_()]),isMessageSelectorVisible:ds||!!Uc,screen:z8,abortSignal:z7?.
signal,isExternalLoading:ff,popCommandFromQueue:q28,isLocalJSXCommand:J6?.isLocalJSXCommand,isInputOverlayActive:h8,input
Mode:Yz,isInputEmpty:i4};s8.useEffect(()=>{if(y)return;if(W2()>=5&&!ls&&!Bc){if(d("tengu_cost_threshold_reached",{}),zW(!
0),$R8())pKH(!0)}},[R4,ls,Bc]);let Vw6=s8.useCallback(async(j8)=>{let r8=DH.getState(),{mode:_6,isBypassPermissionsModeAv
ailable:H$}=r8.toolPermissionContext;switch(wv8(_6,H$)){case"allow":return!0;case"deny":return!1;case"classify":return
Nq6(j8.host,j8.port,zf.current,Pq.current,r8.toolPermissionContext,new
AbortController().signal);case"ask":break}if(EK()&&y98()){let MK=KQK(),$K=await _QK(j8.host,MK);return new
Promise((lK)=>{if(!$K){BA((q$)=>[...q$,{hostPattern:j8,resolvePromise:lK}]);return}YQK({requestId:MK,host:j8.host,resolve
:lK}),e((q$)=>({...q$,pendingSandboxRequest:{requestId:MK,host:j8.host}}))})}return new Promise((MK)=>{let $K=!1;function
lK(q$){if($K)return;$K=!0,MK(q$)}BA((q$)=>[...q$,{hostPattern:j8,resolvePromise:lK}]);{let
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗