62 KiB
Claude Code — Components: Agents, Permissions, Design System & Feature Modules
This document provides an exhaustive spec for all components in the src/components/ subdirectories covering agents management, permission UIs, the design system primitives, and the many feature-specific modules (MCP, memory, tasks, teams, diff, grove, hooks, HelpV2, TrustDialog, ManagedSettingsSecurityDialog, ClaudeCodeHint, HighlightedCode, LogoV2, DesktopUpsell, FeedbackSurvey, LspRecommendation, Passes, Spinner, PromptInput, CustomSelect, Settings, sandbox, shell, skills, ui, wizard).
Table of Contents
- agents/
- permissions/
- design-system/
- wizard/
- mcp/
- memory/
- tasks/
- teams/
- diff/
- grove/
- hooks/
- HelpV2/
- TrustDialog/
- ManagedSettingsSecurityDialog/
- ClaudeCodeHint/
- HighlightedCode/
- LogoV2/
- DesktopUpsell/
- FeedbackSurvey/
- LspRecommendation/
- Passes/
- Spinner/
- PromptInput/
- CustomSelect/
- Settings/
- sandbox/
- shell/
- skills/
- ui/
1. agents/
The agents subsystem provides a full UI for creating, viewing, editing, deleting, and listing custom Claude sub-agents (stored as Markdown files with YAML front matter in .claude/agents/).
1.1 AgentDetail
File: agents/AgentDetail.tsx
Purpose: Renders a read-only detail view of a single AgentDefinition, showing all agent metadata (file path, description, tools, model, permission mode, memory, hooks, skills, color swatch, and system prompt for non-built-in agents).
Props Interface:
type Props = {
agent: AgentDefinition; // The agent to display
tools: Tools; // All available tools (for resolving tool names)
allAgents?: AgentDefinition[]; // All agents (unused in current render, passed for context)
onBack: () => void; // Called when user presses Esc or Enter
}
Key Behaviors:
- Resolves tool list via
resolveAgentTools(agent, tools, false)— shows "All tools", named valid tools, and warns about unrecognized tool names with a warning symbol. - Computes
backgroundColorfromgetAgentColor(agent.agentType)for the color swatch preview. - Binds
confirm:nokeybinding in Confirmation context to callonBack. - Binds
returnkeypress toonBack. - Renders system prompt via
<Markdown>only for non-built-in agents (!isBuiltInAgent(agent)). - Displays model via
getAgentModelDisplay(agent.model). - Displays memory via
getMemoryScopeDisplay(agent.memory). - Displays skills count inline when > 10 entries.
Exports: AgentDetail
1.2 AgentEditor
File: agents/AgentEditor.tsx
Purpose: Full-screen editor for modifying an existing AgentDefinition. Supports editing the agent type (name), system prompt, description (whenToUse), tools, model, color, memory, and effort. Persists changes by calling updateAgentFile. Provides a step-by-step editing flow using a sub-state machine.
Props Interface: (large component; reconstructed from source)
type Props = {
agent: AgentDefinition; // The agent to edit
tools: Tools; // All available tools
existingAgents: AgentDefinition[]; // For duplicate-name validation
onComplete: (message: string) => void; // Called after successful save
onCancel: () => void; // Called when user cancels
}
Key Behaviors:
- Multi-step flow: main edit menu → individual field editors (each with their own step).
- Edit menu shows: Edit system prompt, Edit description, Select tools, Select model, Choose color, (conditional) Choose memory, Back.
- Each field editor reuses the same sub-components used in wizard steps (ToolSelector, ModelSelector, ColorPicker, etc.).
- On save calls
updateAgentFile(agent, ...)and reloads agent state in app state. - Validates agent type via
validateAgentType()before allowing name changes. - Uses React compiler memoization throughout.
Exports: AgentEditor
1.3 AgentNavigationFooter
File: agents/AgentNavigationFooter.tsx
Purpose: Renders a dimmed footer line with keyboard navigation instructions. Integrates with Ctrl+C/D exit state to show "Press X again to exit" during double-tap detection.
Props Interface:
type Props = {
instructions?: string;
// Default: "Press ↑↓ to navigate · Enter to select · Esc to go back"
}
Key Behaviors:
- Calls
useExitOnCtrlCDWithKeybindings()to detect pending exit. - When
exitState.pendingis true, overrides instruction text with"Press ${exitState.keyName} again to exit". - Renders with
marginLeft={2}anddimColor.
Exports: AgentNavigationFooter
1.4 AgentsList
File: agents/AgentsList.tsx
Purpose: Displays a list of agents for a given source (all, built-in, userSettings, projectSettings, etc.), grouped by source category. Supports keyboard navigation, optional "Create new agent" entry, and shows override warnings when an agent is shadowed by another scope.
Props Interface:
type Props = {
source: SettingSource | 'all' | 'built-in' | 'plugin';
agents: ResolvedAgent[]; // Agents resolved with override info
onBack: () => void;
onSelect: (agent: AgentDefinition) => void;
onCreateNew?: () => void; // If provided, shows "Create new agent" option at top
changes?: string[]; // Recent change messages to display
}
Key Behaviors:
- State:
selectedAgent(currently highlighted agent),isCreateNewSelected(boolean, focuses "Create new agent"). - Auto-selects first agent or "Create new" if nothing selected.
handleKeyDown: Up/Down arrows navigate the list (wraps around). Enter activates selected item.- Groups agents by source using
AGENT_SOURCE_GROUPS. - Built-in agents are rendered separately with
renderBuiltInAgentsSection()(dimmed, no pointer). - Per-agent display: name, optional model display (middot-separated), memory label, override shadow warning.
- Shadowed agents shown dimmed with a warning symbol (
figures.warning) and "shadowed by X" text. - Changes list shown at top with success color.
Exports: AgentsList
1.5 AgentsMenu
File: agents/AgentsMenu.tsx
Purpose: Top-level orchestrator for the agents management UI. Implements a state machine with modes: list-agents, create-agent, agent-menu, view-agent, edit-agent, delete-confirm. Reads/writes app state for agent definitions.
Props Interface:
type Props = {
tools: Tools;
onExit: (result?: string, options?: { display?: CommandResultDisplay }) => void;
}
Key Behaviors:
modeStateunion type discriminated bymodefield.- Reads
agentDefinitions,mcpTools,toolPermissionContextfrom app state. - Merges tools via
useMergedTools(). - Groups agents into 8 buckets by source (built-in, userSettings, projectSettings, policySettings, localSettings, flagSettings, plugin, all).
- Resolves display-time overrides via
resolveAgentOverrides(). handleAgentCreated: adds change message, returns to list-agents/all view.handleAgentDeleted: callsdeleteAgentFromFile(), updates app state, adds change message.- In
agent-menumode: renders a<Select>with options View / Edit (if editable) / Delete (if editable) / Back. Editability requiressourcenot in['built-in', 'plugin', 'flagSettings']. - In
delete-confirmmode: shows a confirmation<Dialog>with Yes/No options. - On exit: formats change summary or "Agents dialog dismissed" system message.
Exports: AgentsMenu
1.6 ColorPicker
File: agents/ColorPicker.tsx
Purpose: Interactive color selector for agent type color. Displays all AGENT_COLORS plus an "Automatic color" option. Shows a live preview of the color applied to the agent name.
Props Interface:
type Props = {
agentName: string; // For preview display
currentColor?: AgentColorName | 'automatic'; // Pre-selected color
onConfirm: (color: AgentColorName | undefined) => void; // undefined = automatic
}
Key Behaviors:
COLOR_OPTIONS = ['automatic', ...AGENT_COLORS].- State:
selectedIndexinitialized fromcurrentColoror 0. - Up/Down arrow keys navigate; Enter confirms.
'automatic'selection callsonConfirm(undefined). - Preview box shows agent name with background color or inverse styling.
- Uses
AGENT_COLOR_TO_THEME_COLORfor actual terminal color values.
Exports: ColorPicker
1.7 ModelSelector
File: agents/ModelSelector.tsx
Purpose: Renders a <Select> component for choosing an agent model from the standard list (getAgentModelOptions()). Injects the current model as a custom option if it is a full model ID not in the standard alias list.
Props Interface:
interface ModelSelectorProps {
initialModel?: string; // Current model value
onComplete: (model?: string) => void; // Called with selected model
onCancel?: () => void; // If absent, cancel calls onComplete(undefined)
}
Key Behaviors:
- If
initialModelis not in the standard options list, prepends{ value: initialModel, label: initialModel, description: "Current model (custom ID)" }. - Default value:
initialModel ?? 'sonnet'. - Cancel: calls
onCancel()if provided, otherwiseonComplete(undefined). - Renders a description line: "Model determines the agent's reasoning capabilities and speed."
Exports: ModelSelector
1.8 ToolSelector
File: agents/ToolSelector.tsx
Purpose: Multi-select UI for choosing which tools an agent can access. Groups tools into buckets: Read-only, Edit, Execution, MCP (per-server), and Other. Supports "All tools" wildcard selection.
Props Interface:
type Props = {
tools: Tools; // All available tools
initialTools: string[] | undefined; // Pre-selected tool names (undefined = all)
onComplete: (selectedTools: string[] | undefined) => void; // undefined = all tools
onCancel?: () => void;
}
type ToolBucket = {
name: string;
toolNames: Set<string>;
isMcp?: boolean;
};
type ToolBuckets = {
READ_ONLY: ToolBucket; // GlobTool, GrepTool, FileReadTool, WebFetchTool, etc.
EDIT: ToolBucket; // FileEditTool, FileWriteTool, NotebookEditTool
EXECUTION: ToolBucket; // BashTool, (TungstenTool for internal builds)
MCP: ToolBucket; // Dynamic, populated per MCP server
OTHER: ToolBucket; // Uncategorized catch-all
};
Key Behaviors:
- MCP tools grouped dynamically by server name via
getMcpServerBuckets(). - Tools not matching any bucket go into OTHER.
- AGENT_TOOL_NAME excluded from selectable tools.
- Toggle selection per individual tool; "Select all" / "Deselect all" shortcuts within buckets.
- Up/Down navigation; Space/Enter toggle; Tab/Shift+Tab move between buckets.
- On submit: if no tools selected and wildcard not set, passes empty array. Pressing a confirm shortcut with no selection can also pass
undefined(all tools).
Exports: ToolSelector
1.9 agentFileUtils.ts
File: agents/agentFileUtils.ts
Purpose: File system utility functions for reading and writing agent definition Markdown files.
Exports:
// Formats agent fields into a Markdown file with YAML front matter
function formatAgentAsMarkdown(
agentType: string,
whenToUse: string,
tools: string[] | undefined,
systemPrompt: string,
color?: string,
model?: string,
memory?: AgentMemoryScope,
effort?: EffortValue,
): string
// Returns the absolute directory for an agent based on source
function getAgentDirectoryPath(location: SettingSource): string // (private)
// Returns relative directory path for display
function getRelativeAgentDirectoryPath(location: SettingSource): string // (private)
// Path for a NEW agent file (uses agentType as filename)
function getNewAgentFilePath(agent: { source: SettingSource; agentType: string }): string
// Path for an EXISTING agent (uses actual filename if different from agentType)
function getActualAgentFilePath(agent: AgentDefinition): string
// Relative path for new agent display
function getNewRelativeAgentFilePath(agent: { source: SettingSource | 'built-in'; agentType: string }): string
// Relative path for existing agent display (handles built-in/plugin/flagSettings)
function getActualRelativeAgentFilePath(agent: AgentDefinition): string
// Ensures directory exists then writes agent file
async function saveAgentToFile(
source: SettingSource | 'built-in',
agentType: string,
whenToUse: string,
tools: string[] | undefined,
systemPrompt: string,
checkExists?: boolean, // default true — throws EEXIST if file already exists
color?: string,
model?: string,
memory?: AgentMemoryScope,
effort?: EffortValue,
): Promise<void>
// Overwrites an existing agent's file
async function updateAgentFile(
agent: AgentDefinition,
newWhenToUse: string,
newTools: string[] | undefined,
newSystemPrompt: string,
newColor?: string,
newModel?: string,
newMemory?: AgentMemoryScope,
newEffort?: EffortValue,
): Promise<void>
// Removes the agent's file (ignores ENOENT)
async function deleteAgentFromFile(agent: AgentDefinition): Promise<void>
Key Behaviors:
- All writes use
writeFileAndFlushwhich callshandle.datasync()after writing for durability. formatAgentAsMarkdownescapes backslashes, double quotes, and newlines inwhenToUsefor YAML double-quoted strings.- Tools field omitted entirely when
undefinedor['*'](means all tools allowed).
1.10 generateAgent.ts
File: agents/generateAgent.ts
Purpose: Uses an LLM call (queryModelWithoutStreaming) to auto-generate an agent configuration from a natural language user prompt. Returns identifier, whenToUse, and systemPrompt as structured JSON.
Exports:
type GeneratedAgent = {
identifier: string
whenToUse: string
systemPrompt: string
}
async function generateAgent(
userPrompt: string,
model: ModelName,
existingIdentifiers: string[], // Blocked identifiers included in prompt
abortSignal: AbortSignal,
): Promise<GeneratedAgent>
Key Behaviors:
- Uses a detailed system prompt (
AGENT_CREATION_SYSTEM_PROMPT) instructing Claude on how to design agent personas, write system prompts, create identifiers (lowercase, 2-4 words, hyphens only, no "helper"/"assistant"). - When
isAutoMemoryEnabled(), appendsAGENT_MEMORY_INSTRUCTIONSto the system prompt. - Prepends user context via
prependUserContext(). - Parses JSON from response — falls back to regex extraction if direct parse fails.
- Fires
tengu_agent_definition_generatedanalytics event. - Throws on invalid/missing fields.
1.11 types.ts
File: agents/types.ts
Purpose: Shared type definitions for the agents UI state machine.
Exports:
const AGENT_PATHS = {
FOLDER_NAME: '.claude',
AGENTS_DIR: 'agents',
} as const
type ModeState =
| { mode: 'main-menu' }
| { mode: 'list-agents'; source: SettingSource | 'all' | 'built-in' }
| { mode: 'agent-menu'; agent: AgentDefinition; previousMode: ModeState }
| { mode: 'view-agent'; agent: AgentDefinition; previousMode: ModeState }
| { mode: 'create-agent' }
| { mode: 'edit-agent'; agent: AgentDefinition; previousMode: ModeState }
| { mode: 'delete-confirm'; agent: AgentDefinition; previousMode: ModeState }
type AgentValidationResult = {
isValid: boolean
warnings: string[]
errors: string[]
}
1.12 utils.ts
File: agents/utils.ts
Exports:
function getAgentSourceDisplayName(
source: SettingSource | 'all' | 'built-in' | 'plugin'
): string
// Returns: 'Agents' | 'Built-in agents' | 'Plugin agents' | capitalize(getSettingSourceName(source))
1.13 validateAgent.ts
File: agents/validateAgent.ts
Exports:
type AgentValidationResult = {
isValid: boolean
errors: string[]
warnings: string[]
}
function validateAgentType(agentType: string): string | null
// Returns error message or null if valid.
// Rules: required, /^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]$/, length 3-50 chars.
function validateAgent(
agent: Omit<CustomAgentDefinition, 'location'>,
availableTools: Tools,
existingAgents: AgentDefinition[],
): AgentValidationResult
// Validates: agentType, whenToUse (min 10 chars / max 5000), tools array,
// system prompt (min 20 chars / max 10000 chars warning threshold).
// Checks for duplicate agentType across sources.
// Uses resolveAgentTools to check for invalid tool names.
1.14 new-agent-creation/CreateAgentWizard
File: agents/new-agent-creation/CreateAgentWizard.tsx
Purpose: Assembles the multi-step new-agent creation wizard by composing step components inside <WizardProvider>. Conditionally includes MemoryStep based on feature flag.
Props Interface:
type Props = {
tools: Tools;
existingAgents: AgentDefinition[];
onComplete: (message: string) => void;
onCancel: () => void;
}
Wizard Step Order (0-indexed):
0. LocationStep — project vs personal scope
MethodStep— generate with Claude vs manualGenerateStep— natural language prompt → LLM generation (skipped for manual)TypeStep— agent identifier / namePromptStep— system prompt textDescriptionStep— whenToUse descriptionToolsStep— tool selectionModelStep— model selectionColorStep— color selectionMemoryStep— memory scope (conditional onisAutoMemoryEnabled())ConfirmStepWrapper— review and save
Key Behaviors:
- WizardProvider title: "Create new agent",
showStepCounter: false. onCompleteof WizardProvider is a no-op (actual completion handled byConfirmStepWrapper).- Passes
onCancelthrough to WizardProvider.
1.15 Wizard Steps
LocationStep
Offers two options: "Project (.claude/agents/)" (projectSettings) or "Personal (~/.claude/agents/)" (userSettings). Updates wizardData.location and calls goNext().
MethodStep
Offers "Generate with Claude (recommended)" or "Manual configuration". For generate: sets wizardData.method = 'generate', wasGenerated: true, goNext(). For manual: sets method: 'manual', wasGenerated: false, skips to step 3 via goToStep(3).
GenerateStep
- Text input for natural language description of the agent.
- On submit: calls
generateAgent(prompt, model, existingIdentifiers, abortSignal). - Shows animated
<Spinner>during generation. - On success: populates
wizardData.agentType,systemPrompt,whenToUse,generatedAgent. - Navigates directly to step 6 (ToolsStep) after generation (skips manual name/prompt/description steps).
- Esc during generation cancels via abort signal.
- Supports external editor (
chat:externalEditorkeybinding).
TypeStep
Props: { existingAgents: AgentDefinition[] }. Text input for agent identifier. Validates via validateAgentType(). Updates wizardData.agentType.
PromptStep
Large text input for system prompt. Min 20 chars enforced. Supports external editor. Updates wizardData.systemPrompt.
DescriptionStep
Text input for whenToUse. Required, min 1 char. Supports external editor. Updates wizardData.whenToUse.
ToolsStep
Props: { tools: Tools }. Wraps <ToolSelector> in WizardDialogLayout. Updates wizardData.selectedTools.
ModelStep
Wraps <ModelSelector> in WizardDialogLayout. Updates wizardData.selectedModel.
ColorStep
Wraps <ColorPicker> in WizardDialogLayout. On confirm: builds wizardData.finalAgent object with all accumulated data, updates wizardData.selectedColor.
MemoryStep
Conditional step (only shown when isAutoMemoryEnabled()). Offers memory scope options ordered by recommended scope (project-first for project agents, user-first for personal agents). Includes "None" option. Updates wizardData.selectedMemory.
ConfirmStep / ConfirmStepWrapper
Props: { tools: Tools; existingAgents: AgentDefinition[]; onComplete: (message: string) => void }. Shows a summary of all selected options, validates via validateAgent(), calls saveAgentToFile(), then reloads agents in app state and calls onComplete(message).
2. permissions/
The permissions subsystem renders interactive dialogs asking users to approve, reject, or configure rules for tool uses. Each tool has its own permission request component.
2.1 Core Types & PermissionRequest
File: permissions/PermissionRequest.tsx
Purpose: Top-level dispatcher that picks the correct permission request component for each tool type and renders it. Also handles notifications and idle detection.
Key Types:
type PermissionRequestProps<Input extends AnyObject = AnyObject> = {
toolUseConfirm: ToolUseConfirm<Input>;
toolUseContext: ToolUseContext;
onDone(): void;
onReject(): void;
verbose: boolean;
workerBadge: WorkerBadgeProps | undefined;
setStickyFooter?: (jsx: React.ReactNode | null) => void;
// Registers JSX in a sticky footer below scrollable area (fullscreen only).
}
type ToolUseConfirm<Input extends AnyObject = AnyObject> = {
assistantMessage: AssistantMessage;
tool: Tool<Input>;
description: string;
input: z.infer<Input>;
toolUseContext: ToolUseContext;
toolUseID: string;
permissionResult: PermissionDecision;
permissionPromptStartTimeMs: number;
classifierCheckInProgress?: boolean;
classifierAutoApproved?: boolean;
classifierMatchedRule?: string;
workerBadge?: WorkerBadgeProps;
onUserInteraction(): void;
onAbort(): void;
onDismissCheckmark?(): void;
onAllow(updatedInput, permissionUpdates: PermissionUpdate[], feedback?, contentBlocks?): void;
onReject(feedback?, contentBlocks?): void;
recheckPermission(): Promise<void>;
}
Tool→Component Mapping:
| Tool | Component |
|---|---|
| FileEditTool | FileEditPermissionRequest |
| FileWriteTool | FileWritePermissionRequest |
| BashTool | BashPermissionRequest |
| PowerShellTool | PowerShellPermissionRequest |
| WebFetchTool | WebFetchPermissionRequest |
| NotebookEditTool | NotebookEditPermissionRequest |
| ExitPlanModeV2Tool | ExitPlanModePermissionRequest |
| EnterPlanModeTool | EnterPlanModePermissionRequest |
| SkillTool | SkillPermissionRequest |
| AskUserQuestionTool | AskUserQuestionPermissionRequest |
| GlobTool / GrepTool / FileReadTool | FilesystemPermissionRequest |
| ReviewArtifactTool (feature flag) | ReviewArtifactPermissionRequest |
| WorkflowTool (feature flag) | WorkflowPermissionRequest |
| MonitorTool (feature flag) | MonitorPermissionRequest |
| default | FallbackPermissionRequest |
Exports: PermissionRequest, PermissionRequestProps, ToolUseConfirm
2.2 PermissionDialog
File: permissions/PermissionDialog.tsx
Purpose: The shared visual container for all tool permission requests. Renders a title bar (with optional worker badge), subtitle, and children, wrapped in a styled border box.
Props Interface:
type Props = {
title: string;
subtitle?: React.ReactNode;
color?: keyof Theme; // default: 'permission'
titleColor?: keyof Theme;
innerPaddingX?: number; // default: 1
workerBadge?: WorkerBadgeProps;
titleRight?: React.ReactNode; // Right-aligned content in title row
children: React.ReactNode;
}
Key Behaviors:
- Renders
<PermissionRequestTitle>with the title, subtitle, optional color override, and workerBadge. - Title row uses
justifyContent="space-between"to placetitleRighton the right. - Children rendered in inner
BoxwithpaddingX={innerPaddingX}.
Exports: PermissionDialog
2.3 BashPermissionRequest
File: permissions/BashPermissionRequest/BashPermissionRequest.tsx
Purpose: Permission dialog for BashTool. Handles classifier-based auto-approval animation, sed edit detection (redirects to SedEditPermissionRequest), sandbox detection, and a rich set of options.
Key Behaviors:
ClassifierCheckingSubtitle: separate sub-component that renders an animated shimmer "Attempting to auto-approve…" text at 20fps, isolated to prevent full-dialog re-renders.- Checks
classifierCheckInProgressprop — shows shimmer subtitle while classifier runs. - If command matches a
sededit pattern, delegates toSedEditPermissionRequest. - If
shouldUseSandbox(), shows sandbox-specific options. - Options computed by
bashToolUseOptions(). - Logs permission decision via
usePermissionRequestLogging(). - Supports destructive command warning display.
Exports: BashPermissionRequest
2.4 FilePermissionDialog
File: permissions/FilePermissionDialog/FilePermissionDialog.tsx
Purpose: Generic reusable dialog for file-operation permissions (used by FileEdit, FileWrite, NotebookEdit permission requests). Handles path display, symlink detection, IDE diff integration, and option rendering.
Props Interface:
type FilePermissionDialogProps<T extends ToolInput = ToolInput> = {
toolUseConfirm: ToolUseConfirm;
toolUseContext: ToolUseContext;
onDone: () => void;
onReject: () => void;
title: string;
subtitle?: React.ReactNode;
question?: string | React.ReactNode; // default: 'Do you want to proceed?'
content?: React.ReactNode;
completionType?: CompletionType; // default: 'tool_use_single'
languageName?: string; // Overrides path-derived language name
path: string | null;
parseInput: (input: unknown) => T;
operationType?: FileOperationType; // default: 'write'
ideDiffSupport?: IDEDiffSupport<T>;
workerBadge: WorkerBadgeProps | undefined;
}
Key Behaviors:
- Language name derived async from
getLanguageName(path)if not overridden. - Checks for symlink target when
operationType !== 'read'. - Shows
<ShowInIDEPrompt>when IDE diff is available. - Logs via
usePermissionRequestLogging().
Exports: FilePermissionDialog, FilePermissionDialogProps
2.5 WorkerBadge
File: permissions/WorkerBadge.tsx
Purpose: Colored badge showing which swarm worker is requesting a permission.
Props Interface:
type WorkerBadgeProps = {
name: string; // Worker name (shown as @name)
color: string; // Raw color string (converted to Ink color via toInkColor)
}
Rendering: ● @{name} with the bullet in the worker's color.
Exports: WorkerBadge, WorkerBadgeProps
2.6 Other Permission Request Components
Each follows the PermissionRequestProps interface and renders inside <PermissionDialog> or <FilePermissionDialog>.
FileEditPermissionRequest
Renders a diff of the proposed file edit. Uses FilePermissionDialog with diff content component. operationType: 'write'.
FileWritePermissionRequest
Renders the full proposed file content. Uses FilePermissionDialog. operationType: 'write'.
FilesystemPermissionRequest
For GlobTool / GrepTool / FileReadTool. Shows a read-only access dialog. operationType: 'read'.
NotebookEditPermissionRequest
For Jupyter notebook edits. Renders a notebook cell diff. Uses FilePermissionDialog with languageName derived from cell type.
WebFetchPermissionRequest
Shows the URL being fetched and fetch options.
PowerShellPermissionRequest
Similar to BashPermissionRequest but for PowerShell commands. Uses powershellToolUseOptions().
SedEditPermissionRequest
Rendered by BashPermissionRequest when sed-edit pattern is detected. Shows the file diff that the sed command would produce.
EnterPlanModePermissionRequest
Simple confirmation to enter plan mode.
ExitPlanModePermissionRequest
Full plan review with sticky footer for response options. Uses setStickyFooter for keeping response visible while scrolling.
SkillPermissionRequest
For executing a skill/command.
AskUserQuestionPermissionRequest
Renders a multi-question form with navigation. Subcomponents:
PreviewBox— shows rendered preview of a questionPreviewQuestionView— full question previewQuestionNavigationBar— prev/next navigationQuestionView— single question inputSubmitQuestionsView— confirmation before submittinguse-multiple-choice-state.ts— hook managing checkbox/radio state
ComputerUseApproval
For computer-use actions.
FallbackPermissionRequest
Generic fallback for unrecognized tool types. Shows tool name and description.
SandboxPermissionRequest
Shown when a command is being run in sandbox mode.
2.7 PermissionDecisionDebugInfo
File: permissions/PermissionDecisionDebugInfo.tsx
Purpose: Renders debug information about the permission decision (decision reason, rule details, classifier results) when verbose mode is enabled.
2.8 PermissionExplanation
File: permissions/PermissionExplanation.tsx
Purpose: Renders an explanation of why a permission rule is being requested. usePermissionExplainerUI hook manages the expand/collapse state of the explainer section.
Exports: PermissionExplainerContent, usePermissionExplainerUI
2.9 PermissionPrompt
File: permissions/PermissionPrompt.tsx
Purpose: Wraps permission request UI with the fullscreen layout management and sticky footer support for plan mode responses.
2.10 PermissionRequestTitle
File: permissions/PermissionRequestTitle.tsx
Purpose: Renders the colored title bar for permission dialogs. Shows title text in permission color with optional worker badge below.
Props Interface:
type Props = {
title: string;
subtitle?: React.ReactNode;
color?: keyof Theme;
workerBadge?: WorkerBadgeProps;
}
2.11 PermissionRuleExplanation
File: permissions/PermissionRuleExplanation.tsx
Purpose: Shows the permission rule suggestions (e.g., "Allow bash: git *", "Deny bash: rm -rf") that would be created if the user clicks "Always allow" or "Always deny".
2.12 WorkerPendingPermission
File: permissions/WorkerPendingPermission.tsx
Purpose: Rendered in the swarm coordinator view to show a pending permission from a worker agent.
2.13 hooks.ts
File: permissions/hooks.ts
Exports:
type UnaryEvent = {
completion_type: CompletionType;
language_name: string | Promise<string>;
}
// Logs permission request start/end/result analytics. Called once per dialog.
function usePermissionRequestLogging(
toolUseConfirm: ToolUseConfirm,
unaryEvent: UnaryEvent,
): void
Key Behaviors:
- Fires
tengu_permission_request_starton mount. - Fires
tengu_permission_request_endwith result info on unmount. - Converts
permissionResultto a structured log string.
2.14 shellPermissionHelpers.tsx
File: permissions/shellPermissionHelpers.tsx
Purpose: Shared JSX helpers and option builders used by BashPermissionRequest and PowerShellPermissionRequest (e.g., building the approve/deny/always-allow option list).
2.15 useShellPermissionFeedback.ts
File: permissions/useShellPermissionFeedback.ts
Purpose: Hook managing the feedback text input that appears when user selects "No (feedback)" in shell permission dialogs.
2.16 utils.ts
File: permissions/utils.ts
Exports:
function logUnaryPermissionEvent(
toolUseConfirm: ToolUseConfirm,
unaryEvent: UnaryEvent,
result: string,
): void
2.17 rules/ subdirectory
Permission rule management UI for the /permissions command screen.
| File | Purpose |
|---|---|
AddPermissionRules.tsx |
Form to add new allow/deny rules |
AddWorkspaceDirectory.tsx |
Form to add trusted workspace directories |
PermissionRuleDescription.tsx |
Renders a human-readable description of a rule |
PermissionRuleInput.tsx |
Text input + validation for rule patterns |
PermissionRuleList.tsx |
Shows existing rules with delete option |
RecentDenialsTab.tsx |
Tab showing recently denied tool uses (can convert to rules) |
RemoveWorkspaceDirectory.tsx |
Confirmation dialog for removing workspace directory |
WorkspaceTab.tsx |
Tab showing trusted workspace directories |
3. design-system/
Reusable primitive components that form the visual foundation of all terminal UI.
3.1 Byline
File: design-system/Byline.tsx
Purpose: Joins children with a middot separator (·) for inline metadata display. Automatically filters null/undefined/false children.
Props Interface:
type Props = {
children: React.ReactNode;
}
Key Behaviors:
- Uses
Children.toArray()which filters falsy nodes. - Returns
nullif no valid children. - Renders separators only between adjacent valid elements.
Exports: Byline
3.2 Dialog
File: design-system/Dialog.tsx
Purpose: Confirm/cancel dialog container. Registers confirm:no and Ctrl+C/D keybindings. Shows title, optional subtitle, children, and a keyboard hint footer.
Props Interface:
type DialogProps = {
title: React.ReactNode;
subtitle?: React.ReactNode;
children: React.ReactNode;
onCancel: () => void;
color?: keyof Theme; // default: 'permission'
hideInputGuide?: boolean;
hideBorder?: boolean;
inputGuide?: (exitState: ExitState) => React.ReactNode; // Custom footer
isCancelActive?: boolean; // default: true — controls keybinding activation
}
Key Behaviors:
isCancelActive=false: disables theconfirm:noand exit keybindings (useful when embedded TextInput needs Esc).- Default input guide: "Enter to confirm · Esc to cancel" (or "Press X again to exit" when exit pending).
- Wraps content in
<Pane>unlesshideBorder. - Title rendered in bold with
color.
Exports: Dialog
3.3 Divider
File: design-system/Divider.tsx
Props Interface:
type DividerProps = {
width?: number; // Defaults to terminal width
color?: keyof Theme; // If absent, uses dimColor
char?: string; // default: '─' (U+2500)
padding?: number; // Subtracted from width, default: 0
title?: string; // Centered title (may contain ANSI codes)
}
Key Behaviors:
- Without title:
char.repeat(effectiveWidth)in a<Text>. - With title: left fill + space + title + space + right fill. Left/right fill split evenly (left gets floor half).
- Terminal width queried via
useTerminalSize().
Exports: Divider
3.4 FuzzyPicker
File: design-system/FuzzyPicker.tsx
Purpose: Full-featured fuzzy search picker with optional preview panel. Supports up/down/down-to-top list directions, Tab/Shift+Tab secondary actions, preview on right or bottom, match count label.
Props Interface:
type PickerAction<T> = {
action: string; // Label for byline hint
handler: (item: T) => void;
}
type Props<T> = {
title: string;
placeholder?: string; // default: 'Type to search…'
initialQuery?: string;
items: readonly T[];
getKey: (item: T) => string;
renderItem: (item: T, isFocused: boolean) => React.ReactNode;
renderPreview?: (item: T) => React.ReactNode;
previewPosition?: 'bottom' | 'right'; // default: 'bottom'
visibleCount?: number; // default: 8
direction?: 'down' | 'up'; // default: 'down'
onQueryChange: (query: string) => void;
onSelect: (item: T) => void;
onTab?: PickerAction<T>;
onShiftTab?: PickerAction<T>;
onFocus?: (item: T | undefined) => void;
onCancel: () => void;
emptyMessage?: string | ((query: string) => string);
matchLabel?: string;
selectAction?: string;
extraHints?: React.ReactNode;
}
Key Behaviors:
- Constants:
DEFAULT_VISIBLE=8,CHROME_ROWS=10,MIN_VISIBLE=2. - Auto-adjusts visible count based on terminal height.
- Fires
onFocuswhen focused item changes. direction='up': items[0] at bottom (atuin-style); arrows match screen direction.
Exports: FuzzyPicker
3.5 KeyboardShortcutHint
File: design-system/KeyboardShortcutHint.tsx
Purpose: Renders a keyboard shortcut hint like "ctrl+o to expand" or "(tab to toggle)".
Props Interface:
type Props = {
shortcut: string; // e.g., "ctrl+o", "Enter", "↑↓"
action: string; // e.g., "expand", "select", "navigate"
parens?: boolean; // default: false — wraps in parentheses
bold?: boolean; // default: false — renders shortcut in bold
}
Exports: KeyboardShortcutHint
3.6 ListItem
File: design-system/ListItem.tsx
Purpose: Standard list item for selection UIs with pointer (❯), checkmark (✓), scroll hint arrows, focus/selection colors, and disabled state.
Props Interface:
type ListItemProps = {
isFocused: boolean;
isSelected?: boolean; // default: false — shows ✓
children: ReactNode;
description?: string; // Shown below main content
showScrollDown?: boolean; // Shows ↓ instead of pointer (scroll hint)
showScrollUp?: boolean; // Shows ↑ instead of pointer (scroll hint)
styled?: boolean; // default: true — auto-colors children by state
disabled?: boolean; // default: false — dimmed, no indicators
declareCursor?: boolean; // default: true — declares terminal cursor position
}
Key Behaviors:
- When focused and not selected: pointer (❯) in suggestion color.
- When selected and not focused: checkmark (✓) in suggestion color.
- When disabled: no indicator, dimmed text.
- When
styled=false: children rendered as-is for custom styling.
Exports: ListItem
3.7 LoadingState
File: design-system/LoadingState.tsx
Purpose: Spinner + message for async loading states.
Props Interface:
type LoadingStateProps = {
message: string;
bold?: boolean; // default: false
dimColor?: boolean; // default: false
subtitle?: string; // Optional secondary line below
}
Exports: LoadingState
3.8 Pane
File: design-system/Pane.tsx
Purpose: A terminal region bounded by a colored top divider line, used by all slash-command screens.
Props Interface:
type PaneProps = {
children: React.ReactNode;
color?: keyof Theme; // Theme color for top divider
}
Key Behaviors:
- When rendered inside a modal (
useIsInsideModal()): skips the Divider (the modal frame serves as border), renders withpaddingX={1}andflexShrink={0}. - Normal rendering:
paddingTop={1}+<Divider color={color}>+<Box paddingX={2}>children</Box>.
Exports: Pane
3.9 ProgressBar
File: design-system/ProgressBar.tsx
Purpose: Horizontal text-art progress bar using Unicode block characters.
Props Interface:
type Props = {
ratio: number; // [0, 1]
width: number; // Number of character columns
fillColor?: keyof Theme;
emptyColor?: keyof Theme;
}
Key Behaviors:
- Uses 9 block characters:
[' ', '▏', '▎', '▍', '▌', '▋', '▊', '▉', '█']. - Clamps ratio to [0, 1].
- Whole filled cells:
Math.floor(ratio * width). - Partial cell:
Math.floor(remainder * BLOCKS.length). fillColorapplied as text color;emptyColoras background.
Exports: ProgressBar
3.10 Ratchet
File: design-system/Ratchet.tsx
Purpose: Prevents layout bounce/shrink by maintaining minimum height equal to the maximum seen height. Used for content that can grow but should not shrink when re-rendered.
Props Interface:
type Props = {
children: React.ReactNode;
lock?: 'always' | 'offscreen'; // default: 'always'
}
Key Behaviors:
lock='always': always enforces minHeight (inner Box max seen height, capped at terminal rows).lock='offscreen': only enforces minHeight when the element is not visible in terminal viewport.- Uses
useTerminalViewport()for visibility detection. useLayoutEffectmeasures inner content height after every render.
Exports: Ratchet
3.11 StatusIcon
File: design-system/StatusIcon.tsx
Purpose: Renders a colored status indicator icon.
Props Interface:
type Status = 'success' | 'error' | 'warning' | 'info' | 'pending' | 'loading'
type Props = {
status: Status;
withSpace?: boolean; // default: false — adds trailing space
}
Status Config:
| Status | Icon | Color |
|---|---|---|
| success | ✓ (figures.tick) | success (green) |
| error | ✗ (figures.cross) | error (red) |
| warning | ⚠ (figures.warning) | warning (yellow) |
| info | ℹ (figures.info) | suggestion (blue) |
| pending | ○ (figures.circle) | dimColor |
| loading | … | dimColor |
Exports: StatusIcon
3.12 Tabs
File: design-system/Tabs.tsx
Purpose: Tab container with keyboard navigation. Supports controlled and uncontrolled modes, fixed content height, optional banner, and content-initiated tab switching.
Props Interface:
type TabsProps = {
children: Array<React.ReactElement<TabProps>>;
title?: string;
color?: keyof Theme;
defaultTab?: string;
hidden?: boolean;
useFullWidth?: boolean;
selectedTab?: string; // Controlled mode
onTabChange?: (tabId: string) => void; // Controlled mode
banner?: React.ReactNode;
disableNavigation?: boolean;
initialHeaderFocused?: boolean; // default: true
contentHeight?: number; // Fixed height for all tabs
navFromContent?: boolean; // Allow Tab/←/→ from content
}
type TabsContextValue = {
selectedTab: string | undefined;
width: number | undefined;
headerFocused: boolean;
focusHeader: () => void;
blurHeader: () => void;
registerOptIn: () => () => void;
}
Key Behaviors:
- Tab component reads
TabsContextto know if it is the selected tab. - Left/Right arrows or Tab key switches tabs when header focused.
navFromContent=trueallows content area to trigger tab switches.
Exports: Tabs, TabsContext, TabsContextValue
3.13 ThemeProvider
File: design-system/ThemeProvider.tsx
Purpose: Provides theme state (dark/light/auto) to the component tree. Resolves 'auto' by detecting system theme via OSC 11 terminal queries.
Props Interface:
type Props = {
children: React.ReactNode;
initialState?: ThemeSetting;
onThemeSave?: (setting: ThemeSetting) => void;
}
type ThemeContextValue = {
themeSetting: ThemeSetting; // Saved preference (may be 'auto')
setThemeSetting: (s: ThemeSetting) => void;
setPreviewTheme: (s: ThemeSetting) => void;
savePreview: () => void;
cancelPreview: () => void;
currentTheme: ThemeName; // Resolved theme, never 'auto'
}
Key Behaviors:
previewThemetakes priority overthemeSettingduring theme picker interactions.- Seeds system theme from
$COLORFGBGenv var; OSC 11 watcher corrects it. - Default theme (outside provider, for tests):
'dark'.
Exports: ThemeProvider, ThemeContext, useTheme (hook)
3.14 ThemedBox
File: design-system/ThemedBox.tsx
Purpose: Theme-aware Box component that resolves theme key colors (keyof Theme) in all border/background color props to raw terminal colors before passing to the underlying Ink Box.
Props Type: BaseStylesWithoutColors & ThemedColorProps & EventHandlerProps
type ThemedColorProps = {
borderColor?: keyof Theme | Color;
borderTopColor?: keyof Theme | Color;
borderBottomColor?: keyof Theme | Color;
borderLeftColor?: keyof Theme | Color;
borderRightColor?: keyof Theme | Color;
backgroundColor?: keyof Theme | Color;
}
Key Behaviors:
resolveColor(): passes through raw colors (#,rgb(,ansi256(,ansi:), looks up theme keys.
Exports: ThemedBox (default export), Props
3.15 ThemedText
File: design-system/ThemedText.tsx
Purpose: Theme-aware Text component that resolves keyof Theme color values and supports TextHoverColorContext for cascade coloring.
Props Interface:
type Props = {
color?: keyof Theme | Color;
backgroundColor?: keyof Theme;
dimColor?: boolean; // Uses theme's inactive color (compatible with bold)
bold?: boolean;
italic?: boolean;
underline?: boolean;
strikethrough?: boolean;
inverse?: boolean;
wrap?: Styles['textWrap'];
children?: ReactNode;
}
Exports: ThemedText, Props, TextHoverColorContext
3.16 color.ts
File: design-system/color.ts
Purpose: Curried theme-aware colorization function.
Exports:
function color(
c: keyof Theme | Color | undefined,
theme: ThemeName,
type: ColorType = 'foreground',
): (text: string) => string
Key Behaviors:
- Raw color values bypass theme lookup.
- Theme key values are looked up in
getTheme(theme)and passed tocolorize().
4. wizard/
A generic multi-step wizard framework used by agent creation and potentially other flows.
4.1 WizardProvider
File: wizard/WizardProvider.tsx
Purpose: Context provider managing wizard state: current step, data accumulation, navigation history, and completion.
Props Interface:
type WizardProviderProps<T> = {
steps: WizardStepComponent<T>[];
initialData?: Partial<T>;
onComplete: (data: T) => void;
onCancel: () => void;
children?: React.ReactNode;
title?: string;
showStepCounter?: boolean; // default: true
}
WizardContextValue:
type WizardContextValue<T> = {
currentStepIndex: number;
totalSteps: number;
wizardData: Partial<T>;
updateWizardData: (partial: Partial<T>) => void;
goNext: () => void;
goBack: () => void;
goToStep: (index: number) => void;
cancel: () => void;
title: string | undefined;
showStepCounter: boolean;
}
Key Behaviors:
- Maintains
navigationHistorystack forgoBack(). goNext()at last step setsisCompleted=true, triggeringonComplete(wizardData)in an effect.- Calls
useExitOnCtrlCDWithKeybindings()to register Ctrl+C/D at wizard level.
Exports: WizardProvider, WizardContext
4.2 WizardDialogLayout
File: wizard/WizardDialogLayout.tsx
Purpose: Standard layout for wizard steps — wraps content in a <Dialog> with step counter in title, navigation footer.
Props Interface:
type Props = {
title?: string; // Overrides provider title
color?: keyof Theme; // default: 'suggestion'
children: ReactNode;
subtitle?: string;
footerText?: ReactNode;
}
Key Behaviors:
- Title format:
"${title} (${currentStep + 1}/${totalSteps})"whenshowStepCounteris true. isCancelActive={false}on the inner Dialog (wizard handles its own cancel).- Renders
<WizardNavigationFooter instructions={footerText}>below Dialog.
Exports: WizardDialogLayout
4.3 WizardNavigationFooter
File: wizard/WizardNavigationFooter.tsx
Purpose: Renders keyboard hints at the bottom of wizard dialogs.
Props Interface:
type Props = {
instructions?: ReactNode;
}
4.4 useWizard
File: wizard/useWizard.ts
Purpose: Hook to access WizardContext from within a step component. Throws if used outside a WizardProvider.
Exports:
function useWizard<T extends Record<string, unknown> = Record<string, unknown>>(): WizardContextValue<T>
4.5 index.ts
Re-exports WizardProvider, useWizard, and wizard-related types.
5. mcp/
Model Context Protocol server management UI.
Files Overview
| File | Purpose |
|---|---|
CapabilitiesSection.tsx |
Renders server capabilities list (tools, resources, prompts) |
ElicitationDialog.tsx |
Dialog for MCP elicitation (server requesting structured user input) |
MCPAgentServerMenu.tsx |
Menu for managing MCP agent-type servers |
MCPListPanel.tsx |
Panel showing all connected MCP servers with status |
MCPReconnect.tsx |
UI for reconnecting to a disconnected server |
MCPRemoteServerMenu.tsx |
Menu for remote MCP server configuration |
MCPSettings.tsx |
Top-level MCP settings screen |
MCPStdioServerMenu.tsx |
Menu for stdio-type MCP servers |
MCPToolDetailView.tsx |
Detail view of a single MCP tool |
MCPToolListView.tsx |
List of tools provided by an MCP server |
McpParsingWarnings.tsx |
Shows YAML/JSON parsing warnings from MCP config |
index.ts |
Re-exports |
utils/reconnectHelpers.tsx |
Helper functions for server reconnect logic |
Key Types (from MCPSettings):
// Server status display combines name, transport type, connection state, tool count
6. memory/
Agent memory file management UI.
Files
| File | Purpose |
|---|---|
MemoryFileSelector.tsx |
File picker for selecting which memory file to view/edit |
MemoryUpdateNotification.tsx |
Toast-style notification shown when agent updates its memory |
MemoryFileSelector Props:
type Props = {
onSelect: (filePath: string) => void;
onCancel: () => void;
}
7. tasks/
Background task and remote session monitoring UI.
Files Overview
| File | Purpose |
|---|---|
AsyncAgentDetailDialog.tsx |
Detail dialog for an async/queued agent task |
BackgroundTask.tsx |
Single background task row in the task list |
BackgroundTaskStatus.tsx |
Status badge for a background task |
BackgroundTasksDialog.tsx |
Full dialog listing all background tasks |
DreamDetailDialog.tsx |
Detail for a "dream" (autoDream background consolidation) task |
InProcessTeammateDetailDialog.tsx |
Detail for an in-process swarm teammate |
RemoteSessionDetailDialog.tsx |
Detail for a remote Claude Code session |
RemoteSessionProgress.tsx |
Progress display for remote session activity |
ShellDetailDialog.tsx |
Detail for a shell background task |
ShellProgress.tsx |
Progress line for shell commands |
renderToolActivity.tsx |
Renders current tool activity for a running task |
taskStatusUtils.tsx |
Utility functions for task status display |
8. teams/
Swarm/multi-agent team status UI.
Files
| File | Purpose |
|---|---|
TeamStatus.tsx |
Shows the status of all active team members (swarm workers) |
TeamsDialog.tsx |
Dialog for managing team composition and viewing worker details |
9. diff/
File diff viewing UI.
Files
| File | Purpose |
|---|---|
DiffDetailView.tsx |
Full-screen diff detail with scroll support |
DiffDialog.tsx |
Dialog wrapping DiffDetailView |
DiffFileList.tsx |
List of changed files with summary stats |
10. grove/
Grove (shared project workspace) integration.
Files
| File | Purpose |
|---|---|
Grove.tsx |
Main Grove integration UI component |
11. hooks/ (components/hooks/)
These are component-level hook subdirectory hooks, not the top-level src/hooks/. They are part of the hooks command settings UI.
Files
| File | Purpose |
|---|---|
HooksConfigMenu.tsx |
Configuration menu for Claude hooks (pre/post tool hooks) |
PromptDialog.tsx |
Dialog for entering a hook prompt/command |
SelectEventMode.tsx |
Select hook event type (PreToolUse, PostToolUse, etc.) |
SelectHookMode.tsx |
Select hook execution mode (allow, block, prompt) |
SelectMatcherMode.tsx |
Select how to match tools (all, specific, pattern) |
ViewHookMode.tsx |
Read-only view of an existing hook configuration |
12. HelpV2/
Second-generation help UI, shown by /help.
Files
| File | Purpose |
|---|---|
Commands.tsx |
Renders the commands reference tab |
General.tsx |
Renders the general help/tips tab |
HelpV2.tsx |
Top-level help screen with Tabs (General, Commands) |
13. TrustDialog/
Trust confirmation dialogs for files and workspace directories.
Files
| File | Purpose |
|---|---|
TrustDialog.tsx |
Dialog asking user to confirm trust for a directory or file |
utils.ts |
Trust decision helpers |
14. ManagedSettingsSecurityDialog/
Security warning for managed/policy settings.
Files
| File | Purpose |
|---|---|
ManagedSettingsSecurityDialog.tsx |
Warning dialog when policy settings override user preferences |
utils.ts |
Utilities for detecting managed setting conflicts |
15. ClaudeCodeHint/
Plugin/command hint menu.
Files
| File | Purpose |
|---|---|
PluginHintMenu.tsx |
Shows plugin-provided hints in a menu format |
16. HighlightedCode/
Syntax-highlighted code rendering.
Files
| File | Purpose |
|---|---|
Fallback.tsx |
Non-highlighted code block fallback |
The main HighlightedCode.tsx is in the parent components/ directory (not in this subdirectory); this subdirectory provides only the fallback.
17. LogoV2/
Animated logo/welcome screen and feed system.
Files
| File | Purpose |
|---|---|
AnimatedAsterisk.tsx |
Spinning asterisk logo animation |
AnimatedClawd.tsx |
Animated "Clawd" mascot version |
ChannelsNotice.tsx |
Notice about available channels |
Clawd.tsx |
Static Clawd mascot |
CondensedLogo.tsx |
Compact logo for limited space contexts |
EmergencyTip.tsx |
Urgent tip overlay |
Feed.tsx |
Scrollable feed of announcements/tips |
FeedColumn.tsx |
Column layout for feed items |
GuestPassesUpsell.tsx |
Upsell for guest passes feature |
LogoV2.tsx |
Main logo component (animated asterisk + welcome) |
Opus1mMergeNotice.tsx |
Notice about Opus 1M model merge |
OverageCreditUpsell.tsx |
Upsell for overage credit purchase |
VoiceModeNotice.tsx |
Notice about voice mode availability |
WelcomeV2.tsx |
Full welcome screen with logo and feed |
feedConfigs.tsx |
Configuration data for feed content |
18. DesktopUpsell/
Desktop app upsell during startup.
Files
| File | Purpose |
|---|---|
DesktopUpsellStartup.tsx |
Full-screen upsell shown at startup for desktop app |
19. FeedbackSurvey/
In-app feedback and survey system.
Files
| File | Purpose |
|---|---|
FeedbackSurvey.tsx |
Main survey container |
FeedbackSurveyView.tsx |
Renders a single survey question |
TranscriptSharePrompt.tsx |
Asks user whether to share conversation transcript |
submitTranscriptShare.ts |
API call to submit transcript share |
useDebouncedDigitInput.ts |
Hook for numeric rating inputs (debounced) |
useFeedbackSurvey.tsx |
Main hook managing survey display lifecycle |
useMemorySurvey.tsx |
Hook for memory-specific survey prompts |
usePostCompactSurvey.tsx |
Hook for post-compact operation survey |
useSurveyState.tsx |
Core survey state management hook |
20. LspRecommendation/
LSP/IDE integration recommendation UI.
Files
| File | Purpose |
|---|---|
LspRecommendationMenu.tsx |
Menu suggesting LSP/IDE plugin installation |
21. Passes/
Guest passes system UI.
Files
| File | Purpose |
|---|---|
Passes.tsx |
Displays and manages guest passes for Claude |
22. Spinner/
Animated spinner components.
Files
| File | Purpose |
|---|---|
FlashingChar.tsx |
Character that flashes on/off |
GlimmerMessage.tsx |
Full shimmer-animated message text |
ShimmerChar.tsx |
Individual character with shimmer animation |
SpinnerAnimationRow.tsx |
Single row of spinner animation |
SpinnerGlyph.tsx |
The animated spinner glyph itself |
TeammateSpinnerLine.tsx |
Spinner line for teammate/worker status |
TeammateSpinnerTree.tsx |
Tree of spinner lines for all teammates |
index.ts |
Re-exports Spinner as the main export |
teammateSelectHint.ts |
Returns keyboard hint for teammate selection |
useShimmerAnimation.ts |
Hook generating shimmer animation indices |
useStalledAnimation.ts |
Hook detecting when animation has stalled |
utils.ts |
Spinner utility functions |
SpinnerGlyph: Animated terminal spinner using Unicode braille or other characters, driven by a clock tick interval.
useShimmerAnimation: Returns [ref, glimmerIndex]. The glimmerIndex represents the leading edge of a shimmer animation sweep across the text.
23. PromptInput/
The main prompt input area at the bottom of the REPL screen.
Files
| File | Purpose |
|---|---|
HistorySearchInput.tsx |
Ctrl+R history search input overlay |
IssueFlagBanner.tsx |
Banner for flagged issues |
Notifications.tsx |
In-prompt notification bubbles |
PromptInput.tsx |
Top-level prompt input orchestrator |
PromptInputFooter.tsx |
Footer area (model name, token count, etc.) |
PromptInputFooterLeftSide.tsx |
Left side of footer (model indicator) |
PromptInputFooterSuggestions.tsx |
File/command suggestions dropdown |
PromptInputHelpMenu.tsx |
Quick help menu (shown on ?) |
PromptInputModeIndicator.tsx |
Shows current input mode (normal, plan, etc.) |
PromptInputQueuedCommands.tsx |
Shows queued commands waiting to run |
PromptInputStashNotice.tsx |
Shows stashed input notification |
SandboxPromptFooterHint.tsx |
Hint for sandbox mode in footer |
ShimmeredInput.tsx |
Text input with shimmer loading state |
VoiceIndicator.tsx |
Voice mode activity indicator |
inputModes.ts |
Input mode type definitions and transitions |
inputPaste.ts |
Paste handling logic |
useMaybeTruncateInput.ts |
Hook for truncating long inputs in display |
usePromptInputPlaceholder.ts |
Hook generating placeholder text |
useShowFastIconHint.ts |
Hook controlling fast-mode icon hint visibility |
useSwarmBanner.ts |
Hook for swarm status banner in prompt |
utils.ts |
Input utility functions |
24. CustomSelect/
Accessible terminal select/dropdown components.
Files
| File | Purpose |
|---|---|
SelectMulti.tsx |
Multi-select dropdown |
index.ts |
Re-exports |
option-map.ts |
Option data structure and utilities |
select-input-option.tsx |
Option rendering in input mode |
select-option.tsx |
Single option rendering |
select.tsx |
Main single-select component |
use-multi-select-state.ts |
State hook for multi-select |
use-select-input.ts |
Input handling hook for select |
use-select-navigation.ts |
Keyboard navigation hook |
use-select-state.ts |
State hook for single select |
Select Props (core):
type SelectProps<T extends string = string> = {
options: Array<{ value: T; label: string; description?: string; disabled?: boolean }>;
defaultValue?: T;
onChange: (value: T) => void;
onCancel?: () => void;
isDisabled?: boolean;
}
SelectMulti Props:
type SelectMultiProps<T extends string = string> = {
options: Array<{ value: T; label: string }>;
defaultValues?: T[];
onChange: (values: T[]) => void;
onCancel?: () => void;
}
25. Settings/
Settings slash-command screen (/config).
Files
| File | Purpose |
|---|---|
Config.tsx |
Configuration settings tab (API key, model, etc.) |
Settings.tsx |
Top-level settings screen with tabs |
Status.tsx |
Status tab showing connection and auth state |
Usage.tsx |
Usage statistics tab |
26. sandbox/
Sandbox configuration UI (shown by /sandbox).
Files
| File | Purpose |
|---|---|
SandboxConfigTab.tsx |
Sandbox enable/disable and mode selection |
SandboxDependenciesTab.tsx |
Shows dependencies inside sandbox |
SandboxDoctorSection.tsx |
Diagnostic section for sandbox health |
SandboxOverridesTab.tsx |
Per-project sandbox overrides |
SandboxSettings.tsx |
Top-level sandbox settings screen with tabs |
27. shell/
Shell output display components.
Files
| File | Purpose |
|---|---|
ExpandShellOutputContext.tsx |
Context provider for controlling shell output expansion state |
OutputLine.tsx |
Single line of shell output with ANSI support |
ShellProgressMessage.tsx |
In-progress shell command display with live output |
ShellTimeDisplay.tsx |
Shows elapsed/total time for a shell command |
28. skills/
Skills (slash commands from plugins) UI.
Files
| File | Purpose |
|---|---|
SkillsMenu.tsx |
Menu listing available skills with search |
29. ui/
General-purpose UI primitives not in design-system.
Files
| File | Purpose |
|---|---|
OrderedList.tsx |
Numbered list container |
OrderedListItem.tsx |
Single item in an ordered list |
TreeSelect.tsx |
Tree/hierarchical select component |
TreeSelect supports nested option trees where nodes can be expanded/collapsed. Used for hierarchical tool or directory selection.
Cross-Cutting Patterns
React Compiler Memoization
All components use import { c as _c } from "react/compiler-runtime" and the $ cache array pattern for React Compiler auto-memoization. This is a build-time transformation — the source TypeScript uses standard React patterns.
Theme Integration
- All color props accept
keyof Theme(semantic tokens like'permission','suggestion','success','error','warning','inactive') or raw CSS color strings. ThemedBoxandThemedTextresolve theme tokens to raw colors at render time viauseTheme().
Keybinding System
- Components use
useKeybinding(action, handler, { context, isActive })from../../keybindings/useKeybinding.js. - Contexts:
'Confirmation','Settings','Chat','Application'. - Standard actions:
'confirm:no'(Esc/N),'app:exit'(Ctrl+C),'app:interrupt'(Ctrl+D).
Permission Flow
- Tool use triggers permission check →
PermissionResultwith behavior'ask'/'allow'/'deny'/'passthrough'. 'ask'behavior →ToolUseConfirmobject created →PermissionRequestcomponent rendered.- User selects option →
onAllow(updatedInput, permissionUpdates)oronReject(feedback)called. - Permission updates stored in settings for future auto-approval.
Wizard Pattern
WizardProviderholds step array and accumulated data.- Each step calls
useWizard()to get navigation functions. - Steps call
updateWizardData(partial)thengoNext()/goToStep(n). - Final step calls external
onComplete(message)directly (not via wizard'sonComplete).
Agent File Format
---
name: agent-identifier
description: "When to use this agent..."
tools: BashTool, FileEditTool
model: sonnet
effort: 3
color: blue
memory: project
---
System prompt content here...