Tool runtime, events, and integration flows
This page answers the cross-cutting cli.renamed.js questions that span the tool catalog, event handling, communication, shell execution, plugins, SDK support, LSP diagnostics, web tools, permission control, hooks, context exclusion, settings, and persistence.
It is intentionally an integration map: deeper single-topic pages still own the long-form details for built-in tools and permissions, sandbox and isolation, MCP/plugins/hooks, settings and policy, and sessions/persistence.
For canonical tables, use Tool inventory and schemas, Hooks and events reference, and Settings schema reference. This page stays as the cross-cutting synthesis map.
Source anchors
| Semantic alias | String or symbol | Meaning |
|---|---|---|
| BashToolConstant | var Rq="Bash" | Shell-command tool constant. |
| ReadToolConstant | var Bq="Read" | File read tool constant. |
| EditToolConstant | var v7="Edit" | File edit tool constant. |
| WriteToolConstant | var $9="Write" | File write tool constant. |
| WebFetchToolConstant | var gD="WebFetch" | WebFetch tool constant. |
| WebSearchToolConstant | var RI="WebSearch" | WebSearch tool constant. |
| KillShellCompatibilityAlias | KillShell:"TaskStop" | Compatibility alias from KillShell to TaskStop. |
| BashOutputCompatibilityAlias | BashOutputTool:"TaskOutput" | Compatibility alias from Bash output to task output. |
| ToolExecutionBoundary | async function Yny | Main tool execution/permission boundary. |
| ToolBlockPlanner | Y3g, J3g, X3g | Builds contiguous concurrency-safe blocks and serial singleton barriers. |
| ToolConcurrencyCap | K3g, CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY | Positive override or default cap 10 for parallel safe blocks. |
| PerCallPostHooks | pYr, fYr | Success and failure hooks dispatched per completed call. |
| AggregatePostHook | executePostToolBatchHooks, Fmy | Batch hook after settled results, with different normal-loop and end-turn continuation semantics. |
| PreToolUseAuthorization | hookPermissionResult, PreToolUse | Hook output participates in authorization. |
| CanUseToolBridge | createCanUseTool | SDK/Remote Control permission bridge wrapper. |
| SdkControlRequestHandler | processControlRequest / can_use_tool | SDK stdio control request handler for permission asks. |
| PermissionDeniedFrame | permission_denied | Stream/system frame for deny-shortcut decisions. |
| ControlRequestFrame | control_request | Stream/control frame family for host-driven decisions. |
| SessionStateFrame | session_state_changed | Headless/SDK session-state frame. |
| BridgeStateFrame | bridge_state | Remote/bridge state frame. |
| ShellExecutionPath | async function SHH | Shell execution path: build command, sandbox, spawn, capture output. |
| ShellProcessManager | class pg6 | Shell process result/background manager. |
| TaskStopIdentifierBridge | shell_id, task_id | TaskStop accepts task_id; shell_id is deprecated. |
| BackgroundTaskPersistence | persistent, timeout_ms, TaskStop | Monitor/background task persistence model. |
| WebFetchPreflight | async function getURLMarkdownContent | WebFetch fetch/cache/preflight implementation. |
| WebFetchApplyPrompt | async function applyPromptToMarkdown | WebFetch post-fetch model prompt over fetched content. |
| ServerSideWebSearchTool | web_search_20250305 | Provider/server-side web-search tool type. |
| WebSearchWildcardGuard | WebSearch does not support wildcards | WebSearch permission-pattern validation. |
| WebFetchDomainGuard | WebFetch permissions use domain format | WebFetch permission-pattern validation. |
| McpRuntimeCoordinator | function fH9 | MCP runtime coordinator. |
| PluginCommandRegistrar | function fC4 | Plugin command family. |
| PluginLspServerSchema | lspServers | Plugin manifest schema for LSP server configuration. |
| LspDiagnosticsNotification | textDocument/publishDiagnostics | Passive LSP diagnostics notification handler. |
| AgentSdkChildProcessWrapper | wF6=class wF6 | Agent SDK child-process wrapper. |
| HeadlessRunner | async function runHeadless | Headless runner entry. |
| HeadlessStreamMultiplexer | function runHeadlessStreamingForTesting | Headless/SDK stream multiplexer. |
| DynamicSectionExclusion | excludeDynamicSections | Dynamic system-prompt section exclusion during context accounting. |
| ClaudeMdExcludeSetting | claudeMdExcludes | Excludes User/Project/Local memory files; managed memory is not excluded. |
| GitignoreRespectSetting | respectGitignore | File-index context discovery can respect gitignore. |
| IgnoreFileDiscovery | .ignore, .rgignore | Additional ignore-pattern inputs for file suggestions/indexing. |
| SandboxDenyReadSetting | denyRead | Sandbox/filesystem read exclusion setting. |
| AddDirectoryFlag | --add-dir <directories...> | Adds additional workspace/tool-access directories. |
| SettingsPrecedenceRule | Settings precedence is user < project < local < flag < policy | Settings merge precedence. |
| SettingsInjectionFlag | --settings <file-or-json> | Runtime settings injection flag. |
| NoSessionPersistenceFlag | --no-session-persistence | Disables local session persistence. |
| SessionJsonlFilename | ${v$()}.jsonl | Current-session JSONL transcript filename. |
| TranscriptRecorder | recordTranscript | Transcript write function family. |
| SdkSessionStoreAdapter | sessionStore | SDK external session-store adapter surface. |
| LatestSessionDiscovery | async function loadConversationForResume | Resume/latest-session discovery. |
| RestoredSessionApplier | async function OG8 | Restored-session state application. |
One-page answer map
| Question | Source-confirmed answer |
|---|---|
| Which tools exist? | Built-ins include shell, file read/search/edit/write, web, todo/plan, skill, task/subagent, output/stop aliases, and MCP/plugin-provided tools. |
| What is the event mechanism? | In-process events are normal JS calls/stores; externalized events are hook events, headless stream frames, control requests, bridge frames, telemetry, and JSONL transcript entries. |
| How is communication handled? | Different boundaries use different protocols: MCP JSON-RPC, provider HTTP/SSE, SDK stdio stream-JSON, Remote/IDE/Chrome bridge JSON frames, local JSONL persistence, and direct JS calls inside the bundle. |
| How does shell execution work? | SHH chooses a shell provider, wraps with sandbox when enabled, spawns a child process, captures output through a task-output file/buffer, and pg6 manages timeout/background/kill/result state. |
| How are plugins/extensions supported? | PluginCommandRegistrar exposes plugin commands; plugin manifests can contribute agents, skills, hooks, MCP servers, output styles, monitors, settings, and lspServers. MCP runtime wiring is coordinated by McpRuntimeCoordinator. |
| How is SDK supported? | AgentSdkChildProcessWrapper spawns the CLI in stream-json mode, translates SDK options to CLI flags/env, writes/reads JSON frames, and handles can_use_tool control requests through stdio. |
| Is there LSP syntax support? | Yes, but the source-confirmed path is LSP server configuration plus passive diagnostics (publishDiagnostics) and file sync; this is diagnostics/syntax-error support, not proof of full editor refactoring features. |
| Is there WebSearch/WebFetch? | Yes. WebFetch is local HTTP fetch + conversion + optional model prompt; WebSearch is provider/server-side web_search_20250305 invoked through a model call. |
| How is permission control done? | Tool visibility flags/settings feed ToolExecutionBoundary, which applies initial validation, PreToolUse rewrite validation, permission mode/rules, SDK/host can_use_tool, a separate final permission-rewrite check, denial frames, and tool-specific guards. |
| How do hooks work? | PreToolUse can affect authorization and input. Success/failure hooks are per call; PostToolBatch is aggregate. Only auto-mode classifier denial reaches the observed PermissionDenied branch, whose retry flag is model guidance rather than an automatic retry. |
| How is context exclusion done? | Multiple mechanisms: dynamic prompt-section exclusion, claudeMdExcludes, gitignore/ignore-file filtering for file context, sandbox/file denyRead, and explicit add-dir root expansion. |
| How are settings implemented? | Settings are layered user/project/local/flag/policy config with managed policy controls and CLI injection via --settings, --managed-settings, and --setting-sources. |
| What is persistence? | Local sessions are JSONL transcript files keyed by session ID; resume uses SessionDiscovery/SessionRestore; headless/SDK mirrors transcript frames; SDK sessionStore can mirror local writes externally. |
Tool catalog and capability assembly
The tool set is assembled from several sources, then filtered before the model sees it.
flowchart TD Builtins[Built-in tools] --> Registry[Capability registry] MCP[MCP tools via McpRuntimeCoordinator] --> Registry Plugins[Plugin tools, skills, agents, hooks] --> Registry Tasks[Task/subagent tools] --> Registry SDK[External/SDK tool definitions] --> Registry Registry --> Filters[--tools / allow / deny / settings / policy] Filters --> Model[Model-visible tool schemas] Model --> Boundary[Tool execution boundary]Confirmed built-in families:
| Family | Representative names | Notes |
|---|---|---|
| Shell/process | Bash, TaskStop, TaskOutput, BashOutputTool, KillShell | KillShell and BashOutputTool are compatibility aliases around task stop/output semantics. |
| File read/search | Read, Glob, Grep, LS | File visibility can also be shaped by ignore files, gitignore, add-dir, permissions, and sandbox policy. |
| File write/edit | Edit, Write, MultiEdit, NotebookEdit | Subject to read-before-write and modified-after-read guards. |
| Web | WebFetch, WebSearch | Separate local-fetch and provider/server-search paths. |
| Planning/context | TodoWrite, ExitPlanMode, Skill | Planning and skill dispatch participate in the same tool visibility plane. |
| Agents/tasks | TaskCreate, TaskGet, TaskList, TaskUpdate, SendMessage | Task/subagent coordination is tool/state/event mediated. |
| External capabilities | MCP tools, plugin skills/agents/hooks/LSP, SDK tools | External sources still pass through the common permission boundary. |
The important architectural point is that “available tool” is not the same as “executed action.” A tool can be registered, filtered out, denied by policy, denied or mutated by hooks, routed to a host permission request, blocked by a tool-specific guard, or finally executed.
Events and communication
cli.renamed.js does not use one universal event bus. It uses boundary-specific mechanisms.
| Boundary | Mechanism | Evidence |
|---|---|---|
| In-process runtime | JS calls, async stores, React/TUI state, queues, telemetry helpers | Most logical module boundaries stay inside the bundled process. |
| Hook scripts | Named hook events and structured hook input/output | PreToolUse, PostToolUse, PostToolBatch, PermissionDenied, UserPromptExpansion, SessionStart, SessionEnd, PreCompact, PostCompact, task/subagent hooks. |
| Tool permission host | Control frames | control_request, can_use_tool, permission_denied, permission_response. |
| Headless/SDK stream | Stream-JSON frames | HeadlessControlLoop emits system/user/assistant/result/control/rate-limit/session/bridge/transcript frames. |
| MCP | JSON-RPC-shaped protocol | initialize, tools/list, tools/call, resources/list, prompts/get, task methods. |
| Provider/model API | HTTP(S), SSE/event-stream, provider headers | [API REQUEST], text/event-stream, x-client-request-id in the provider path. |
| Remote/IDE/Chrome bridge | JSON envelopes over persistent transports | bridge_state, permission request/response, pairing, tool-call/result frames. |
| Persistence | Append-only transcript/event records | ${sessionId}.jsonl, recordTranscript, transcript_mirror. |
flowchart TD Model[Model output] --> ToolUse[tool_use] ToolUse --> Boundary[Tool execution boundary] Boundary --> Hooks[PreToolUse / per-call post hooks / aggregate PostToolBatch] Boundary --> Control[can_use_tool control_request] Boundary --> Result[tool_result or denial] Result --> Stream[headless/SDK stream frames] Result --> Jsonl[local JSONL transcript] Control --> Host[SDK / Remote / MCP permission prompt] Host --> BoundaryFor the protocol-family overview, see Runtime communication protocols.
Shell command execution
The shell path is source-confirmed around async function SHH.
sequenceDiagram autonumber participant Tool as Bash/Monitor tool participant Shell as SHH participant Sandbox as Sandbox manager participant OS as child_process.spawn participant Output as Task output file/buffer participant Manager as pg6 process manager participant Registry as Task registry
Tool->>Shell: command + timeout/background/sandbox options Shell->>Shell: choose bash/zsh or powershell provider Shell->>Shell: build command and cwd marker file alt sandbox enabled Shell->>Sandbox: wrapWithSandbox(command, shell) Sandbox-->>Shell: wrapped command string end Shell->>OS: spawn(shell, args, env, cwd, stdio) OS-->>Output: stdout/stderr chunks Shell->>Manager: Xf8(process, abort, timeout, output, background?) Manager->>Registry: background task id/output path when backgrounded Manager-->>Tool: result, timeout, interrupted, output file, or task idKey mechanics:
- Shell provider selection. The runtime honors
CLAUDE_CODE_SHELLwhen it points to a valid bash/zsh path, otherwise probes$SHELL,zsh, andbash. PowerShell has a separate provider. - Command wrapping.
SHHbuilds a provider-specific command string and a cwd marker file so it can detect whether a command changed the working directory. - Sandbox handoff. When sandboxing is active,
SHHcallsc6.wrapWithSandbox(...)before spawning. The sandbox decision is still permission-mediated; see Sandbox and isolation. - Spawn environment. The spawned process receives a controlled env including
CLAUDECODE=1,AI_AGENT,CLAUDE_CODE_SESSION_ID, optionalTRACEPARENT, shell overrides, session env vars, and tool-provided extra env. - Output capture. A task-output object records stdout/stderr. Large or background outputs spill to disk and can be read via task output/file paths.
- Timeout/background manager.
pg6owns process exit/error/timeout, kills withSIGKILL, marksbackgroundTaskId, and reports timeout text such asCommand timed out after .... - Task stop.
TaskStopstops background shell/monitor/agent tasks bytask_id;shell_idremains as a deprecated compatibility input.
Persistent does not mean a reusable interactive shell
There are two separate concepts that are easy to conflate:
| Concept | Source-confirmed behavior |
|---|---|
| Normal Bash calls | Spawn a command through SHH; state is persisted through cwd/session/task outputs, not by keeping one interactive shell process for every call. |
| Background/persistent tasks | run_in_background, Monitor, and persistent: true keep a task or monitor alive until timeout, session end, or TaskStop. |
The internal user-initiated shell command schema also states that a direct shell command path has “no persistent shell state across calls,” so persistent shell semantics should be described as task lifetime, not as an always-reused REPL shell.
Plugins, MCP, extensions, and LSP
Plugins and extension points
Plugins are the main extension packaging surface. The plugin / plugins command family is anchored by PluginCommandRegistrar, and plugin manifests can contribute multiple runtime components:
| Plugin component | Runtime effect |
|---|---|
agents | Adds custom/background/subagent definitions. |
skills and commands | Adds skill and slash-command automation surfaces. |
hooks | Adds lifecycle hook scripts. |
mcpServers | Adds MCP capability providers. |
outputStyles, themes, settings | Changes prompt/style/settings surfaces. |
monitors | Arms persistent background monitor tasks. |
lspServers | Adds language-server configurations for diagnostics. |
MCP is the runtime protocol side of extension. McpRuntimeCoordinator connects regular, always-load, and claude.ai connector configs; MCP protocol schemas include tools/list, tools/call, resources/list, and prompts/get. MCP tools become model-visible capabilities only after connection and still pass through ToolExecutionBoundary.
Two integration families have focused owners because their process/transport state is larger than a generic MCP row:
- Browser automation and Claude in Chrome traces dynamic MCP setup, Chrome native messaging, the authenticated browser bridge, tab groups, browser tools, and permissions.
- IDE integration and LSP diagnostics separates IDE dynamic MCP discovery/connection from plugin-provided LSP subprocesses.
LSP support
The source-confirmed LSP path is diagnostics-oriented. The complete configuration, lazy subprocess, file-sync, crash/retry, deduplication, and volume-bound lifecycle is in IDE integration and LSP diagnostics:
- Plugins/settings can declare
lspServersas a path, keyed record, or array of inline/path configs. - The LSP manager initializes server processes and tracks file-to-server associations.
- The manager sends file lifecycle notifications such as
textDocument/didSaveandtextDocument/didClose. - It registers a passive
textDocument/publishDiagnosticshandler. - Diagnostics are converted from URI/range/severity/source/code into internal diagnostic records and registered for async delivery.
- Stale diagnostics can be dropped when a diagnostic version is older than the current document version.
This is enough to answer “is there LSP syntax support?” as yes for language-server diagnostics / syntax-error reporting. The client advertises and has generic request plumbing for additional LSP capabilities, but the anchors do not by themselves prove a model-visible semantic-rename, hover, code-action, or workspace-edit surface.
SDK support
The Agent SDK path wraps Claude Code as a child process rather than importing the whole runtime as a normal library call.
flowchart TD SDKOptions[SDK options] --> Wrapper[Agent SDK child-process wrapper] Wrapper --> Flags[stream-json CLI flags/env] Flags --> Child[spawn Claude Code process] Child --> Stdout[stream-json stdout] Child --> Stdin[stream-json stdin/control] Stdout --> SDKConsumer[SDK caller] SDKConsumer --> Stdin Stdin --> Control[processControlRequest] Control --> Permission[can_use_tool callback]Important SDK mechanics:
AgentSdkChildProcessWrappermaps SDK options into CLI flags such as--output-format stream-json,--input-format stream-json,--model,--max-turns,--max-budget-usd,--permission-mode,--allowedTools,--disallowedTools,--tools,--mcp-config, and--strict-mcp-config.- When the SDK supplies a
canUseToolcallback, the wrapper selects--permission-prompt-tool stdio; the child then emitscan_use_toolcontrol requests over stdio. processControlRequesthandlescan_use_toolrequests, calls the SDK callback with suggestions, blocked path, and decision reason context, then replies with acontrol_response.sessionStoreis an SDK storage adapter surface. The source explicitly requires local transcript writes to exist so they can be mirrored;persistSession: falseis incompatible withsessionStore.enableFileCheckpointingis rejected withsessionStorein this build because backup blobs are not mirrored, so rewind would be unsafe after store-backed resume.
WebFetch and WebSearch
WebFetch and WebSearch are separate implementations.
WebFetch
FN6 implements the local fetch path:
- Validates the URL.
- Upgrades
http:tohttps:where possible. - Performs a domain preflight against
https://api.anthropic.com/api/web/domain_info?domain=...unless skipped by runtime settings. - Fetches with
Accept: text/markdown, text/html, */*and a Claude Code user agent. - Handles redirects with a same-domain/same-protocol/same-port policy and a redirect cap.
- Treats egress-proxy allowlist failures as structured
EGRESS_BLOCKEDerrors. - Caps content length and converts HTML to Markdown via a bundled turndown path.
- Persists binary/image-like content to a file when possible.
- Caches fetch results by URL with TTL/size limits.
QN6can then run a model prompt over the fetched content usingweb_fetch_applyas the query source.
Permission syntax is domain-oriented: WebFetch(domain:example.com), not raw URL allow rules.
WebSearch
WebSearch is implemented through provider/server-side tool use:
- The tool schema accepts
query, optionalallowed_domains, and optionalblocked_domains. - Input validation rejects missing queries and simultaneous allow+block domain lists.
VH5builds a server-side tool descriptor with typeweb_search_20250305, nameweb_search, domain filters, andmax_uses: 8.- The runtime runs a model request with a web-search system prompt and the server-side search tool.
vH5extractsserver_tool_useandweb_search_tool_resultblocks into a model-facing result shape.isEnabled()gates availability by provider/model family.
Permission syntax rejects wildcard search permissions (WebSearch does not support wildcards).
Permission control and hooks
The permission pipeline is a layered trust path:
flowchart TD Visible[Tool visible to model] --> Schema[Schema parse and tool validateInput] Schema --> PreHook[PreToolUse hook and rewrite check] PreHook --> Decision[Permission mode/rules/classifier] Decision -->|allow with replacement| FinalInput[Independent permission-input check] Decision -->|allow unchanged| Guards[Tool body and live guards] FinalInput --> Guards Decision -->|ask| Host[SDK/Remote/MCP permission prompt] Host --> Decision Decision -->|deny| Deny[denial result / permission_denied frame] Deny -. auto-mode classifier only .-> PermissionDenied[PermissionDenied hook] Guards --> Execute[Tool implementation] Execute --> PerCall[PostToolUse or PostToolUseFailure] PerCall --> Batch[PostToolBatch after settled results]Key behaviors:
- Initial schema/tool validation precedes
PreToolUse. A pre-hookupdatedInputhas its own check; a later permission-handlerupdatedInputis independently validated throughn8uand fails withPERMISSION_UPDATED_INPUTbeforetool.callwhen invalid. PreToolUseis pre-execution and can allow, ask, deny, defer, add context, or supplyupdatedInput; rule checks can still override a hook rewrite that would weaken ask/deny policy.- The deny shortcut emits
permission_deniedframes so SDK/remote hosts can render a denial even when no prompt is shown. - Ask-style decisions emit
can_use_toolcontrol requests and wait for a host response. PermissionDenieddispatch is source-confirmed only for an auto-mode classifier denial.retry: trueappends guidance for the model; it does not automatically execute the tool again.PostToolUseandPostToolUseFailureare per-call hooks.PostToolBatchis a separate aggregate hook after the batch settles.- Tool-specific guards still apply after permission approval, e.g. read-before-edit and WebFetch/WebSearch permission syntax.
Scheduling and post-hook timing
Tool calls from one model response are not one undifferentiated Promise.all. Y3g classifies calls by schema shape and isConcurrencySafe, grouping only adjacent safe calls. An unsafe or schema-invalid call is a singleton ordering barrier. J3g executes a safe block through the bounded parallel executor; X3g executes singleton blocks serially. K3g accepts a positive CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY override and otherwise caps a parallel block at 10 (cli.renamed.js:343251-343333).
This block structure also explains hook timing:
- Each successful call dispatches
pYr/PostToolUse; each thrown call dispatchesfYr/PostToolUseFailure. Calls in one parallel block can therefore have overlapping per-call hook execution. - In the normal model loop,
executePostToolBatchHooksruns after all tool results settle and before attachments/tool refresh and the next recursive model request. Its additional context is appended, while a blocking result orpreventContinuationends the loop withhook_stopped(aroundcli.renamed.js:462430-462490). Fmyalso runsPostToolBatchwhen a tool result or MCP metadata has already ended the turn. Hook messages can still be emitted, but blocking/prevent-continuation output is logged as discarded because there is no next model request to stop (aroundcli.renamed.js:459780-459830; exact log prefix[end-turn] PostToolBatch block discarded).- Abort and other exceptional termination branches are handled separately; the two paths above are not evidence that every exit runs normal batch-hook semantics.
Context exclusion
“Context exclusion” is not one switch. The bundle has several exclusion layers with different scopes.
| Layer | Source surface | What it excludes |
|---|---|---|
| Dynamic system prompt sections | --exclude-dynamic-system-prompt-sections, excludeDynamicSections | Per-machine/per-session sections from the system prompt/accounting path. |
| Memory file excludes | claudeMdExcludes | User, Project, and Local CLAUDE.md / .claude/rules paths. Managed/policy memory is explicitly not excluded. |
| File-index ignores | respectGitignore, .ignore, .rgignore, git ls-files / ripgrep fallback | Candidate project files for suggestions/context discovery. |
| Filesystem/sandbox policy | denyRead, allowRead, allowWrite, denyWrite | Runtime process/file access for sandboxed commands and tool paths. |
| Workspace root expansion | --add-dir, additionalDirectories | Adds more allowed roots; exclusion/permission logic then applies across the enlarged root set. |
This distinction matters. Excluding a CLAUDE.md file from memory loading does not necessarily hide a file from Read; ignoring a path in file suggestions does not necessarily sandbox-deny a shell process; adding a directory expands the candidate roots but does not automatically authorize every write.
Settings implementation
Settings are layered configuration objects with explicit precedence:
flowchart LR User[User settings] --> Project[Project settings] Project --> Local[Local settings] Local --> Flags[Flag/inline settings] Flags --> Policy[Managed policy] Policy --> Runtime[Runtime config]Confirmed surfaces include:
| Surface | Role |
|---|---|
~/.claude/settings.json, .claude/settings.json, .claude/settings.local.json | Persistent user/project/local overlays. |
--settings <file-or-json> | Adds a settings file or inline JSON for the current session. |
--managed-settings / managed policy schema | Enterprise/policy controls with highest precedence. |
--setting-sources | Restricts which setting sources participate. |
enabledPlugins, extraKnownMarketplaces, blockedMarketplaces, strictKnownMarketplaces | Plugin trust/marketplace policy. |
disableAllHooks, disableRemoteControl, disableSkillShellExecution, disableAgentView | Managed switches that disable extension/runtime surfaces. |
cleanupPeriodDays, autoCompactEnabled, fileCheckpointingEnabled | Persistence/context/file-history runtime behavior. |
Settings are not only preferences. They shape tool availability, plugin/MCP loading, hooks, context sources, sandbox policy, remote control, retention, model behavior, and integration defaults.
Persistence mechanism
Persistence is session-centered.
flowchart TD SessionID[session id] --> Jsonl[session-id.jsonl] Loop[Runtime loop] --> Record[recordTranscript] Record --> Jsonl Jsonl --> Resume[Session discovery] Resume --> Restore[Session restore envelope] Restore --> Loop Jsonl --> Mirror[transcript_mirror frames] Mirror --> SDKStore[SDK sessionStore mirror]Source-confirmed components:
| Component | Behavior |
|---|---|
| Local JSONL | Sessions write append-only transcript/event lines to ${sessionId}.jsonl under the project/config session root. |
recordTranscript family | Records messages, tool events, sidechain/subagent entries, metadata, context-collapse commits, file-history snapshots, and aliases. |
SessionDiscovery | Resolves latest or explicit sessions and loads transcript/message state. |
SessionRestore | Applies restored state: session id, permission mode, model, agent metadata, bridge/worktree metadata, deferred tools, context-collapse state. |
--no-session-persistence | Disables transcript writes and therefore future local resume for that run. |
cleanupPeriodDays | Retention window for persisted transcripts. |
transcript_mirror | Headless/SDK frame mirroring transcript writes to consumers. |
sessionStore | SDK adapter that mirrors local writes externally; it requires local persistence and currently cannot combine with file checkpointing. |
session_state_changed | Live state frame for hosts/automation watching running/requires-action/completed states. |
The practical model is: local JSONL is the canonical durable layer; SDK/remote/session-store features mirror or project it rather than replacing the local session spine.
Tool-result rendering registry
Every tool definition supplies its own renderer set on the same object that ships its name, inputSchema, and call — there is no centralized registry. The shared shape carries up to five callbacks:
renderToolUseMessage(input, { verbose })— the header banner shown while the tool is running (and again above its result).renderToolUseProgressMessage(data, ctx)— intermediate output for streaming tools.renderToolUseRejectedMessage(input, ctx)— displayed when permission is denied.renderToolUseErrorMessage(error, { verbose })— displayed whencallthrows.renderToolResultMessage(data, toolUseId, { verbose })— the success render.
The permission/loop dispatcher at cli.renamed.js line 419964 guards every render with if (!A || !A.renderToolUseRejectedMessage) and falls back to a generic message; the same pattern is repeated for the other four callbacks. Concrete tools therefore opt in per surface:
| Tool group | Anchor | Renderer style |
|---|---|---|
MCP ListMcpResources | line 252785 | renderToolUseMessage returns a one-line "List MCP resources from server X"; renderToolResultMessage shows pretty-printed JSON inside <zm> with the verbose flag forwarded for truncation. |
| Read / Bash file tools | line 323786 | renderToolUseMessage_2(H) renders compact path + size header. |
| Glob / Grep | lines 406403, 406851 | renderToolUseMessage_3/_4({ pattern, path }, { verbose }) show the pattern and the search root. |
WebFetch family | line 403846 | renderToolUseProgressMessage_8(content, { verbose, theme, tools, style }) builds an Ink <QvH> element with timeoutMs so the in-progress component can show elapsed/total time. |
| Permission rejection | line 421584 | renderToolUseRejectedMessage(input, ctx) exists as _1 … _5 variants per tool, customizing the explanation per surface (Edit/MultiEdit/Write get diffs of the rejected change). |
Because renderers are co-located with call, adding a new tool requires no UI registry edits — the loop discovers the renderer via the tool object’s own properties. The fallback at if (!A.renderToolUseRejectedMessage) is what guarantees the TUI never crashes when a tool ships without one.
Residual caveats
- The bundle is minified; semantic names in this page are explanatory aliases, not stable public APIs.
- LSP support is documented only as far as diagnostics/file-sync anchors confirm. Treat hover/rename/code-actions as unconfirmed until separately anchored.
- WebSearch behavior depends on provider/model availability gates.
- Marketplace declaration, materialization, update, and scoped-removal mechanics are documented in MCP, plugins, and hooks. The current materializer implements URL/GitHub/Git/file/directory/settings sources but explicitly throws for an NPM marketplace source.
Related docs
Created and maintained by Yingting Huang.