### Dialog Component Design Considerations Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/components/03-platform-components.md Highlights specific design features of the Dialog component, such as built-in confirmation, cancel handling, custom input guides, and pending exit prompts. Useful for understanding how the system manages user input and potential conflicts. ```typescript 内建 confirm:no 支持 isCancelActive 支持自定义 input guide 支持 Ctrl+C/D 的 pending exit 提示 ``` -------------------------------- ### Agent Memory Prompt Loading Logic Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/04-agent-memory.md Illustrates the steps involved in loading agent memory prompts, including scope note generation, directory calculation, asynchronous directory creation, and building the memory prompt with extra guidelines. ```text loadAgentMemoryPrompt() -> 根据 scope 生成 scopeNote -> 算出 memoryDir -> fire-and-forget ensureMemoryDirExists(memoryDir) -> buildMemoryPrompt({ displayName: 'Persistent Agent Memory', memoryDir, extraGuidelines: [scopeNote, ...可能的环境附加规则] }) ``` -------------------------------- ### Submit Transcript Share Function Call Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/06b-negative-keyword-analysis.md Example of calling the submitTranscriptShare function after a user selects 'good' or 'bad' feedback, triggering a transcript prompt. ```typescript const result = await submitTranscriptShare(messagesRef.current, trigger_0, appearanceId_2); ``` -------------------------------- ### Agent Memory Snapshot Initialization Logic Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/04-agent-memory.md Explains the processes for initializing local agent memory from a snapshot, including copying files and updating synchronization metadata, with variations for direct replacement or marking as synced. ```text snapshot 目录 -> 复制除 snapshot.json 之外的文件 -> 写入本地 agent memory 目录 -> 保存 .snapshot-synced.json 而 replaceFromSnapshot() 会更激进: 本地 agent memory 目录 -> 先删除已有 .md 文件 -> 再复制 snapshot -> 再写 synced metadata 还提供了 markSnapshotSynced(): - 不改正文 - 只更新同步元数据 ``` -------------------------------- ### Team Memory Service Implementation References Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/04-agent-memory.md Provides references to the key files involved in the Team Memory synchronization service, highlighting its focus on controlled synchronization for shared team knowledge. ```text src/services/teamMemorySync/index.ts src/services/teamMemorySync/watcher.ts src/memdir/teamMemPaths.ts ``` -------------------------------- ### Create Skill Command Instance Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/04c-skills-implementation.md Instantiates a skill command, handling prompt content expansion, including CLI arguments and built-in variables like skill directory and session ID. It also processes embedded shell commands for trusted skill sources. ```typescript export function createSkillCommand({ skillName, markdownContent, allowedTools, loadedFrom, baseDir, paths, shell, ...rest }: SkillCommandOptions): Command { return { type: 'prompt', name: skillName, paths, // 条件技能触发路径 isHidden: !userInvocable, // ... // 核心执行逻辑:getPromptForCommand 在模型调用技能时触发 async getPromptForCommand(args, toolUseContext) { let finalContent = markdownContent // 原始 Markdown 内容 // 1. 展开 CLI 参数占位符 finalContent = substituteArguments(finalContent, args, true, argumentNames) // 2. 展开内置变量(skill 目录、session ID) if (baseDir) { const skillDir = baseDir.replace(/\\/g, '/') // Windows 路径标准化 finalContent = finalContent.replace(/\${CLAUDE_SKILL_DIR}/g, skillDir) } finalContent = finalContent.replace(/\${CLAUDE_SESSION_ID}/g, getSessionId()) // 3. 执行 prompt 内嵌 Shell 命令(只对受信任来源执行,MCP 来源跳过) if (loadedFrom !== 'mcp') { finalContent = await executeShellCommandsInPrompt( finalContent, toolUseContext, `/${skillName}`, shell ) } return [{ type: 'text', text: finalContent }] }, } } ``` -------------------------------- ### Discover Skills from Filesystem Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/04c-skills-implementation.md Loads skills from local directories, including user-defined, managed, and project-specific locations. It handles bare mode and uses memoization for efficiency. Deduplication is performed based on real file paths to prevent loading the same skill multiple times, especially via symlinks. ```typescript export const getSkillDirCommands = memoize( async (cwd: string): Promise => { const userSkillsDir = join(getClaudeConfigHomeDir(), 'skills') // ~/.claude/skills const managedSkillsDir = join(getManagedFilePath(), '.claude', 'skills') // 策略管理目录 const projectSkillsDirs = getProjectDirsUpToHome('skills', cwd) // 项目目录向上爬取 // --bare 模式:跳过自动发现,只加载 --add-dir 显式指定的路径 if (isBareMode()) { return additionalDirs.flatMap(dir => loadSkillsFromSkillsDir(join(dir, '.claude', 'skills'), 'projectSettings') ) } // 正常模式:并行加载所有来源 const [managedSkills, userSkills, projectSkillsNested, additionalSkillsNested, legacyCommands] = await Promise.all([ loadSkillsFromSkillsDir(managedSkillsDir, 'policySettings'), // 策略级技能 loadSkillsFromSkillsDir(userSkillsDir, 'userSettings'), // 用户级技能 Promise.all(projectSkillsDirs.map(dir => loadSkillsFromSkillsDir(dir, 'projectSettings'))), // 项目级技能(多目录) Promise.all(additionalDirs.map(dir => loadSkillsFromSkillsDir(join(dir, '.claude', 'skills'), 'projectSettings'))), // --add-dir loadSkillsFromCommandsDir(cwd), // 旧版 /commands/ 目录 ]) // 合并 + 去重(inode 级别,防止软链重复) return deduplicateByRealpath([ ...managedSkills, ...userSkills, ...projectSkillsNested.flat(), ...additionalSkillsNested.flat(), ...legacyCommands, ]) } ) ``` -------------------------------- ### Run Pre-ToolUse Hooks Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/04b-tool-call-implementation.md Executes pre-tool use hooks sequentially to perform validation, permission checks, and potentially modify input before the tool is called. If an interception occurs, tool invocation is halted. ```typescript export async function* runPreToolUseHooks( tool: Tool, toolUseID: string, input: { [key: string]: unknown }, // ... ): AsyncGenerator { // 按顺序触发前置拦截校验逻辑,甚至可能直接修改传入的 input 结构... } ``` -------------------------------- ### Agent Memory Typical Workflow Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/04-agent-memory.md Describes the end-to-end process of agent memory usage, from agent definition and prompt injection to agent operation, memory updates, and subsequent recall. ```text 加载 agent 定义 -> agent.memory = user / project / local -> 自动补 FileRead / FileWrite / FileEdit -> getSystemPrompt() 追加 Agent Memory prompt spawn agent -> prompt 中已经包含: 1. memory 使用规则 2. memory 目录位置 3. 当前 MEMORY.md 索引内容 agent 工作中发现需要记住的信息 -> 先读 MEMORY.md 或已有 memory 文件 -> 新增或更新某条 memory -> 再维护 MEMORY.md 索引 后续再次调用同一 agent -> 再次读取同一目录的 MEMORY.md -> 获得上次沉淀下来的长期记忆 ``` -------------------------------- ### Agent Memory Snapshot Directory Structure Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/04-agent-memory.md Specifies the fixed directory structure for agent memory snapshots and identifies the key metadata files used to track synchronization status. ```text /.claude/agent-memory-snapshots// 其中关键文件有两个: - snapshot.json 记录 snapshot 的 updatedAt - .snapshot-synced.json 记录本地当前是从哪个 snapshot 时间点同步过来的 ``` -------------------------------- ### Assemble Tool Pool with Built-in and MCP Tools Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/04b-tool-call-implementation.md Combines built-in tools with external MCP tools, prioritizing built-in tools in case of name conflicts. Ensures that potentially malicious MCP tools with names matching built-in tools are filtered out. ```typescript export function assembleToolPool( permissionContext: ToolPermissionContext, mcpTools: Tools, ): Tools { const builtInTools = getTools(permissionContext) // 过滤出未被拦截的 MCP Server 工具 const allowedMcpTools = filterToolsByDenyRules(mcpTools, permissionContext) const byName = (a: Tool, b: Tool) => a.name.localeCompare(b.name) // 合并、排序、并在名字冲突时优先保留内建的工具 return uniqBy( [...builtInTools].sort(byName).concat(allowedMcpTools.sort(byName)), 'name', ) } ``` -------------------------------- ### Overall Structure Diagram Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/06b-negative-keyword-analysis.md A diagram outlining the flow from user text input through keyword matching, event logging, and potential higher-level frustration detection leading to transcript sharing. ```text 用户输入文本 | v matchesNegativeKeyword() | +--> is_negative = true/false | v logEvent('tengu_input_prompt', { is_negative }) | v 正常进入 query / 会话 | v 更高层 frustration detection | +--> 如果识别到用户明显 frustrated | v FeedbackSurvey / TranscriptSharePrompt | v submitTranscriptShare(trigger='frustration') ``` -------------------------------- ### Control Flow Diagram for User Operations Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/components/03-platform-components.md Illustrates the relationship between user operations and different dialogs (BackgroundTasksDialog, TeamsDialog, PermissionRequest) and their respective backend interactions. Useful for understanding the system's architecture. ```text 用户操作 -> BackgroundTasksDialog -> AppState.tasks -> agent / shell / workflow / remote runtime -> TeamsDialog -> teammate mailbox / swarm backends / pane state -> agent / shell / workflow / remote runtime -> PermissionRequest/* -> ToolUseConfirm / permission rules / classifier state -> agent / shell / workflow / remote runtime ``` -------------------------------- ### Assemble MCP and Built-in Tool Pool Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/04d-mcp-implementation.md Combines built-in tools with filtered MCP tools into a unified tool pool, prioritizing built-in tools and ensuring uniqueness. ```typescript // src/tools.ts(伪代码) export function assembleToolPool( permissionContext: ToolPermissionContext, mcpTools: Tool[], ): Tool[] { const builtinTools = getTools(permissionContext) return [ ...builtinTools, // 内建工具优先 ...mcpTools.filter(isIncludedMcpTool), // MCP 工具白名单过滤 ] .sort((a, b) => a.name.localeCompare(b.name)) // 排序 .filter(deduplicateByName()) // 去重(内建优先) } ``` -------------------------------- ### ThemeProvider Component Features Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/components/03-platform-components.md Details the capabilities of the ThemeProvider component, including persistence, preview, auto-theming, and listening to system theme changes. This is crucial for managing the application's visual theme. ```typescript theme setting 持久化 preview theme auto theme 监听终端系统主题变化 ``` -------------------------------- ### Agent Tool Injection for Memory Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/04-agent-memory.md Shows the conditional injection of file-related tools into an agent's toolset when memory features are enabled, enabling agents to read, write, and edit memory files. ```text 如果 memory 开启,且 auto memory 开启: 强制把以下工具加入 agent tools: - FileWriteTool - FileEditTool - FileReadTool ``` -------------------------------- ### Core Design System Components Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/components/03-platform-components.md Lists key foundational components of the terminal design system. These include dialogs, panes, tabs, list items, and theming providers, essential for building a consistent UI. ```typescript Dialog.tsx Pane.tsx Tabs.tsx ListItem.tsx ThemeProvider.tsx ThemedBox ThemedText KeyboardShortcutHint Byline ``` -------------------------------- ### Agent Memory Read/Write/Edit Cycle Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/04-agent-memory.md Outlines the minimal closed-loop functionality provided to agents with memory enabled, covering reading, creating, and updating memory files. ```text 读索引 -> FileReadTool 新建记忆 -> FileWriteTool 更新记忆 -> FileEditTool ``` -------------------------------- ### Higher-Level Frustration Linkage Pseudocode Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/06b-negative-keyword-analysis.md Pseudocode showing how frustration detection in the REPL can lead to feedback surveys or transcript sharing prompts, specifically using 'frustration' as a trigger. ```text during REPL runtime: frustrationDetection = useFrustrationDetection(messages, ...) if frustrationDetection decides user looks frustrated: show feedback survey / transcript share prompt if user agrees: submitTranscriptShare(messages, trigger="frustration", ...) ``` -------------------------------- ### Handle OAuth Token Refresh for claude.ai Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/04d-mcp-implementation.md Wraps fetch requests to automatically refresh OAuth tokens and retry when a 401 Unauthorized response is received from claude.ai endpoints. ```typescript // src/services/mcp/client.ts:372 export function createClaudeAiProxyFetch(innerFetch: FetchLike): FetchLike { return async (url, init) => { const response = await innerFetch(url, init) // 若 claude.ai 返回 401(Token 过期),主动触发 OAuth Token Refresh 后重试 if (response.status === 401) { await refreshOAuthToken() return innerFetch(url, { ...init, headers: { ...getUpdatedAuthHeaders() } }) } return response } } ``` -------------------------------- ### Input Tagging Layer Pseudocode Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/06b-negative-keyword-analysis.md Pseudocode illustrating the input tagging process where user prompts are analyzed for negative and keep-going keywords before logging an event. ```text on user text prompt: userPromptText = extractText(input) isNegative = matchesNegativeKeyword(userPromptText) isKeepGoing = matchesKeepGoingKeyword(userPromptText) logEvent("tengu_input_prompt", { is_negative: isNegative, is_keep_going: isKeepGoing }) continue normal query flow ``` -------------------------------- ### Agent Memory Snapshot State Determination Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/04-agent-memory.md Details the logic for determining the state of an agent memory snapshot, categorizing it into 'none', 'initialize', or 'prompt-update' based on file existence and timestamps. ```text 如果项目里没有 snapshot.json: -> none 如果本地 agent memory 目录里没有任何 .md 文件: -> initialize 如果本地已有 memory,但: - 没有 .snapshot-synced.json - 或 snapshot.updatedAt > syncedFrom -> prompt-update 否则: -> none ``` -------------------------------- ### Layered Memory System Responsibilities Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/04-agent-memory.md Summarizes the distinct responsibilities of various memory types within the system, clarifying their roles in long-term user/project collaboration, session context, agent-specific memory, and team knowledge sharing. ```text Auto Memory 解决:用户 / 项目长期协作信息沉淀 Relevant Recall 解决:本轮只召回少量相关 memory,避免 prompt 污染 Session Memory 解决:长会话摘要与 compact 稳定性 Agent Memory 解决:某个 agent 类型的长期专属记忆 Agent Memory Snapshot 解决:agent 记忆的初始化、分发、升级 Team Memory 解决:团队共享知识同步 ``` -------------------------------- ### Agent Memory Snapshot Check Trigger Conditions Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/04-agent-memory.md Lists the conditions that must be met for the agent memory snapshot check to be triggered, emphasizing feature flags, agent type, and memory scope. ```text feature('AGENT_MEMORY_SNAPSHOT') isAutoMemoryEnabled() agent 是 custom agent 并且当前实现里只对 memory === 'user' 的 agent 执行初始化检查 ``` -------------------------------- ### Whitelist Allowed IDE Tools for MCP Source: https://github.com/liuup/claude-code-analysis/blob/main/analysis/04d-mcp-implementation.md Filters MCP tools to only allow specific IDE-related functions, preventing unauthorized access from non-approved IDE tools. ```typescript // src/services/mcp/client.ts:569 const ALLOWED_IDE_TOOLS = [ 'mcp__ide__getDiagnostics', 'mcp__ide__getOpenEditorFiles', // ... 仅少数高权限工具通过白名单 ] function isIncludedMcpTool(tool: Tool): boolean { // non-IDE 工具全部允许;IDE 工具只允许白名单内的 return !tool.name.startsWith('mcp__ide__') || ALLOWED_IDE_TOOLS.includes(tool.name) } ```