approvedTools Command
The approvedTools
command manages which tools Claude has permission to use in a given project.
Implementation
This command is implemented in commands/approvedTools.ts
and provides functionality to list and remove tools from the approved list. The implementation uses a simple handler pattern with two key functions:
handleListApprovedTools
: Lists all tools that are approved for use in the current directory.handleRemoveApprovedTool
: Removes a specific tool from the approved list.
The command follows a configurable pattern that supports dependency injection:
export type ProjectConfigHandler = {
getCurrentProjectConfig: () => ProjectConfig;
saveCurrentProjectConfig: (config: ProjectConfig) => void;
};
// Default config handler using the real implementation
const defaultConfigHandler: ProjectConfigHandler = {
getCurrentProjectConfig: getCurrentProjectConfigDefault,
saveCurrentProjectConfig: saveCurrentProjectConfigDefault,
};
This design makes the command testable by allowing the injection of mock config handlers.
CLI Integration
In cli.tsx
, the command is registered as a subcommand under the main claude
command:
const allowedTools = program
.command("approved-tools")
.description("Manage approved tools");
allowedTools
.command("list")
.description("List all approved tools")
.action(async () => {
const result = handleListApprovedTools(getCwd());
console.log(result);
process.exit(0);
});
allowedTools
.command("remove <tool>")
.description("Remove a tool from the list of approved tools")
.action(async (tool: string) => {
const result = handleRemoveApprovedTool(tool);
logEvent("tengu_approved_tool_remove", {
tool,
success: String(result.success),
});
console.log(result.message);
process.exit(result.success ? 0 : 1);
});
This allows users to use commands like:
claude approved-tools list
- To list all approved toolsclaude approved-tools remove <tool>
- To remove a specific tool from the approved list
Security Implications
The approvedTools
command plays an important security role in Claude Code's permission system. It allows users to revoke permissions for specific tools, providing a mechanism to limit what Claude can do in a project. This is particularly important for tools that have the potential to modify files or execute commands.
bug Command
The bug
command provides users with a way to submit bug reports and feedback directly from the CLI interface.
Implementation
The command is implemented in commands/bug.tsx
and leverages React components to create an interactive feedback form:
import { Command } from "../commands";
import { Bug } from "../components/Bug";
import * as React from "react";
import { PRODUCT_NAME } from "../constants/product";
const bug = {
type: "local-jsx",
name: "bug",
description: `Submit feedback about ${PRODUCT_NAME}`,
isEnabled: true,
isHidden: false,
async call(onDone) {
return <Bug onDone={onDone} />;
},
userFacingName() {
return "bug";
},
} satisfies Command;
export default bug;
Unlike pure command-line commands, this command uses the type: 'local-jsx'
designation, which allows it to render a React component as its output. This enables a rich, interactive interface for gathering bug reports.
UI Component
The core functionality is housed in the Bug
component in components/Bug.tsx
. Key aspects of this component include:
-
Multi-Step Form: The UI guides users through a multi-step process:
- User input (description of the bug)
- Consent for information collection
- Submission
- Completion
-
Information Collection: The component collects:
- User-provided bug description
- Environment information (platform, terminal, version)
- Git repository metadata (disabled in the current implementation)
- Model settings (without API keys)
-
GitHub Integration: After submission, users can create a GitHub issue with pre-filled information including:
- Bug description
- Environment info
- Model settings
-
Privacy Considerations: The component has been carefully designed to avoid collecting sensitive information:
- No API keys are included
- Personal identifiers have been removed
- Direct submission to Anthropic's feedback endpoint has been commented out
Technical Features
Several technical aspects of the implementation are worth noting:
-
Stateful Form Management: Uses React's
useState
to manage the form state through multiple steps. -
Terminal Adaptation: Adapts to terminal size using the
useTerminalSize
hook to ensure a good experience regardless of window size. -
Keyboard Navigation: Implements customized keyboard handling with
useInput
from Ink to enable intuitive navigation. -
Error Handling: Includes robust error handling for submission failures.
-
Title Generation: Originally included a capability to generate a concise title for the bug report using Claude's Haiku endpoint (currently commented out).
-
Browser Integration: Uses the
openBrowser
utility to open the user's default web browser to the GitHub issues page with pre-filled information.
Design Considerations
The bug command exemplifies several design principles of Claude Code's command system:
-
Rich Terminal UI: Unlike traditional CLI tools that might just accept arguments, the command provides a fully interactive experience with visual feedback.
-
Progressive Disclosure: Information about what will be collected is clearly shown before submission.
-
Simple Escape Paths: Users can easily cancel at any point using Escape or Ctrl+C/D.
-
Clear Status Indicators: The UI clearly shows the current step and available actions at all times.
This command demonstrates how Claude Code effectively leverages React and Ink to create sophisticated terminal user interfaces for commands that require complex interaction.
clear Command
The clear
command provides a way to reset the current conversation, clear the message history, and free up context space.
Implementation
The command is implemented in commands/clear.ts
as a type: 'local' command, which means it doesn't render a UI component but rather performs an operation directly:
import { Command } from "../commands";
import { getMessagesSetter } from "../messages";
import { getContext } from "../context";
import { getCodeStyle } from "../utils/style";
import { clearTerminal } from "../utils/terminal";
import { getOriginalCwd, setCwd } from "../utils/state";
import { Message } from "../query";
export async function clearConversation(context: {
setForkConvoWithMessagesOnTheNextRender: (
forkConvoWithMessages: Message[]
) => void;
}) {
await clearTerminal();
getMessagesSetter()([]);
context.setForkConvoWithMessagesOnTheNextRender([]);
getContext.cache.clear?.();
getCodeStyle.cache.clear?.();
await setCwd(getOriginalCwd());
}
const clear = {
type: "local",
name: "clear",
description: "Clear conversation history and free up context",
isEnabled: true,
isHidden: false,
async call(_, context) {
clearConversation(context);
return "";
},
userFacingName() {
return "clear";
},
} satisfies Command;
export default clear;
Functionality
The clear
command performs several key operations:
-
Terminal Cleaning: Uses
clearTerminal()
to visually reset the terminal display. -
Message History Reset: Sets the message array to empty using
getMessagesSetter()([])
. -
Context Clearing: Clears the cached context information using
getContext.cache.clear()
. -
Style Cache Reset: Clears the cached code style information with
getCodeStyle.cache.clear()
. -
Working Directory Reset: Resets the current working directory to the original one using
setCwd(getOriginalCwd())
. -
Conversation Forking Reset: Clears any pending conversation forks via the context parameter.
Technical Implementation Notes
The clear
command makes use of several architectural patterns in Claude Code:
-
Getter/Setter Pattern: Uses message setter functions obtained through
getMessagesSetter()
rather than directly manipulating a message store, allowing for changes to be reactive across the UI. -
Cache Invalidation: Explicitly clears caches for context and code style information to ensure fresh data when the user continues.
-
State Management: Demonstrates how state (like current working directory) is reset when clearing a conversation.
-
Context Parameter: Receives a context object from the command system that allows it to interact with the component rendering the REPL.
-
Separate Function: The core functionality is extracted into a separate
clearConversation
function, which allows it to be used by other parts of the system if needed.
User Experience Considerations
From a UX perspective, the clear
command provides several benefits:
-
Context Space Management: Allows users to free up context space when they hit limitations with model context windows.
-
Fresh Start: Provides a clean slate for starting a new conversation without entirely restarting the CLI.
-
Visual Reset: The terminal clearing provides immediate visual feedback that the conversation has been reset.
The clear
command is simple but vital for long-running CLI sessions, where context management becomes crucial for effective use of the LLM.
compact Command
The compact
command offers a sophisticated solution to context management by summarizing the conversation history before clearing it, thereby retaining essential context while freeing up token space.
Implementation
The command is implemented in commands/compact.ts
as a type: 'local' command:
import { Command } from "../commands";
import { getContext } from "../context";
import { getMessagesGetter, getMessagesSetter } from "../messages";
import { API_ERROR_MESSAGE_PREFIX, querySonnet } from "../services/claude";
import {
createUserMessage,
normalizeMessagesForAPI,
} from "../utils/messages.js";
import { getCodeStyle } from "../utils/style";
import { clearTerminal } from "../utils/terminal";
const compact = {
type: "local",
name: "compact",
description: "Clear conversation history but keep a summary in context",
isEnabled: true,
isHidden: false,
async call(
_,
{
options: { tools, slowAndCapableModel },
abortController,
setForkConvoWithMessagesOnTheNextRender,
}
) {
// Get existing messages before clearing
const messages = getMessagesGetter()();
// Add summary request as a new message
const summaryRequest = createUserMessage(
"Provide a detailed but concise summary of our conversation above. Focus on information that would be helpful for continuing the conversation, including what we did, what we're doing, which files we're working on, and what we're going to do next."
);
const summaryResponse = await querySonnet(
normalizeMessagesForAPI([...messages, summaryRequest]),
["You are a helpful AI assistant tasked with summarizing conversations."],
0,
tools,
abortController.signal,
{
dangerouslySkipPermissions: false,
model: slowAndCapableModel,
prependCLISysprompt: true,
}
);
// Extract summary from response, throw if we can't get it
const content = summaryResponse.message.content;
const summary =
typeof content === "string"
? content
: content.length > 0 && content[0]?.type === "text"
? content[0].text
: null;
if (!summary) {
throw new Error(
`Failed to generate conversation summary - response did not contain valid text content - ${summaryResponse}`
);
} else if (summary.startsWith(API_ERROR_MESSAGE_PREFIX)) {
throw new Error(summary);
}
// Substitute low token usage info so that the context-size UI warning goes
// away. The actual numbers don't matter too much: `countTokens` checks the
// most recent assistant message for usage numbers, so this estimate will
// be overridden quickly.
summaryResponse.message.usage = {
input_tokens: 0,
output_tokens: summaryResponse.message.usage.output_tokens,
cache_creation_input_tokens: 0,
cache_read_input_tokens: 0,
};
// Clear screen and messages
await clearTerminal();
getMessagesSetter()([]);
setForkConvoWithMessagesOnTheNextRender([
createUserMessage(
`Use the /compact command to clear the conversation history, and start a new conversation with the summary in context.`
),
summaryResponse,
]);
getContext.cache.clear?.();
getCodeStyle.cache.clear?.();
return ""; // not used, just for typesafety. TODO: avoid this hack
},
userFacingName() {
return "compact";
},
} satisfies Command;
export default compact;
Functionality
The compact
command implements a sophisticated workflow:
-
Conversation Summary Generation:
- Retrieves the current message history
- Creates a user message requesting a conversation summary
- Uses Claude API to generate a summary through the
querySonnet
function - Validates the summary to ensure it was successfully generated
-
Token Usage Management:
- Manipulates the usage data to prevent context-size warnings
- Sets input tokens to 0 to indicate the conversation has been compacted
-
Context Reset with Summary:
- Clears the terminal display
- Resets message history
- Creates a new conversation "fork" containing only:
- A user message indicating a compact operation occurred
- The generated summary response
- Clears context and code style caches
Technical Implementation Notes
The compact
command demonstrates several advanced patterns:
-
Meta-Conversation: The command uses Claude to talk about the conversation itself, leveraging the model's summarization abilities.
-
Model Selection: Explicitly uses the
slowAndCapableModel
option to ensure high-quality summarization. -
Content Extraction Logic: Implements robust parsing of the response content, handling different content formats (string vs. structured content).
-
Error Handling: Provides clear error messages for when summarization fails or when the API returns an error.
-
Token Manipulation: Intelligently manipulates token usage information to maintain a good user experience after compaction.
-
Conversation Forking: Uses the
setForkConvoWithMessagesOnTheNextRender
mechanism to create a new conversation branch with only the summary.
User Experience Benefits
The compact
command addresses several key pain points in AI assistant interactions:
-
Context Window Management: Helps users stay within token limits while preserving the essence of the conversation.
-
Conversation Continuity: Unlike a complete clear, it maintains the thread of discussion through the summary.
-
Work Session Persistence: Preserves information about files being edited and tasks in progress.
-
Smart Reset: Performs a targeted reset that balances clearing space with maintaining context.
The command is particularly valuable for long development sessions where context limits become an issue but completely starting over would lose important progress information.
config Command
The config
command provides an interactive terminal interface for viewing and editing Claude Code's configuration settings, including model settings, UI preferences, and API keys.
Implementation
The command is implemented in commands/config.tsx
as a type: 'local-jsx' command that renders a React component:
import { Command } from "../commands";
import { Config } from "../components/Config";
import * as React from "react";
const config = {
type: "local-jsx",
name: "config",
description: "Open config panel",
isEnabled: true,
isHidden: false,
async call(onDone) {
return <Config onClose={onDone} />;
},
userFacingName() {
return "config";
},
} satisfies Command;
export default config;
Like the bug
command, this command uses JSX to render an interactive UI component. The actual functionality is implemented in the Config
component located in components/Config.tsx
.
UI Component
The Config
component implements a rich terminal-based settings interface with the following features:
-
Settings Management: Displays a list of configurable settings with their current values.
-
Multiple Setting Types: Supports various setting types:
boolean
: Toggle settings (true/false)enum
: Options from a predefined liststring
: Text input valuesnumber
: Numeric values
-
Interactive Editing: Allows users to:
- Navigate settings with arrow keys
- Toggle boolean and enum settings with Enter/Space
- Edit string and number settings with a text input mode
- Exit configuration with Escape
-
Configuration Persistence: Saves settings to a configuration file using
saveGlobalConfig
.
Configuration Options
The component exposes numerous configuration options, including:
-
Model Configuration:
- AI Provider selection (anthropic, openai, custom)
- API keys for small and large models
- Model names for both small and large models
- Base URLs for API endpoints
- Max token settings
- Reasoning effort levels
-
User Interface:
- Theme selection (light, dark, light-daltonized, dark-daltonized)
- Verbose output toggle
-
System Settings:
- Notification preferences
- HTTP proxy configuration
Technical Implementation Notes
The Config
component demonstrates several advanced patterns:
-
State Management: Uses React's
useState
to track:- Current configuration state
- Selected setting index
- Editing mode state
- Current input text
- Input validation errors
-
Reference Comparison: Maintains a reference to the initial configuration using
useRef
to track changes. -
Keyboard Input Handling: Implements sophisticated keyboard handling for navigation and editing:
- Arrow keys for selection
- Enter/Space for toggling/editing
- Escape for cancellation
- Input handling with proper validation
-
Input Sanitization: Cleans input text to prevent control characters and other problematic input.
-
Visual Feedback: Provides clear visual indication of:
- Currently selected item
- Editing state
- Input errors
- Available actions
-
Change Tracking: Tracks and logs configuration changes when exiting.
User Experience Design
The config component showcases several UI/UX design principles for terminal applications:
-
Modal Interface: Creates a focused settings panel that temporarily takes over the terminal.
-
Progressive Disclosure: Shows relevant controls and options based on the current state.
-
Clear Instructions: Displays context-sensitive help text at the bottom of the interface.
-
Visual Highlighting: Uses color and indicators to show the current selection and editing state.
-
Immediate Feedback: Changes take effect immediately, with visual confirmation.
-
Multiple Input Methods: Supports keyboard navigation, toggling, and text input in a unified interface.
-
Safe Editing: Provides validation and escape routes for configuration editing.
The config
command demonstrates how Claude Code effectively combines the simplicity of terminal interfaces with the rich interaction capabilities typically associated with graphical applications, creating a powerful yet accessible configuration experience.
compact Command
The compact
command offers a sophisticated solution to context management by summarizing the conversation history before clearing it, thereby retaining essential context while freeing up token space.
Implementation
The command is implemented in commands/compact.ts
as a type: 'local' command:
import { Command } from "../commands";
import { getContext } from "../context";
import { getMessagesGetter, getMessagesSetter } from "../messages";
import { API_ERROR_MESSAGE_PREFIX, querySonnet } from "../services/claude";
import {
createUserMessage,
normalizeMessagesForAPI,
} from "../utils/messages.js";
import { getCodeStyle } from "../utils/style";
import { clearTerminal } from "../utils/terminal";
const compact = {
type: "local",
name: "compact",
description: "Clear conversation history but keep a summary in context",
isEnabled: true,
isHidden: false,
async call(
_,
{
options: { tools, slowAndCapableModel },
abortController,
setForkConvoWithMessagesOnTheNextRender,
}
) {
// Get existing messages before clearing
const messages = getMessagesGetter()();
// Add summary request as a new message
const summaryRequest = createUserMessage(
"Provide a detailed but concise summary of our conversation above. Focus on information that would be helpful for continuing the conversation, including what we did, what we're doing, which files we're working on, and what we're going to do next."
);
const summaryResponse = await querySonnet(
normalizeMessagesForAPI([...messages, summaryRequest]),
["You are a helpful AI assistant tasked with summarizing conversations."],
0,
tools,
abortController.signal,
{
dangerouslySkipPermissions: false,
model: slowAndCapableModel,
prependCLISysprompt: true,
}
);
// Extract summary from response, throw if we can't get it
const content = summaryResponse.message.content;
const summary =
typeof content === "string"
? content
: content.length > 0 && content[0]?.type === "text"
? content[0].text
: null;
if (!summary) {
throw new Error(
`Failed to generate conversation summary - response did not contain valid text content - ${summaryResponse}`
);
} else if (summary.startsWith(API_ERROR_MESSAGE_PREFIX)) {
throw new Error(summary);
}
// Substitute low token usage info so that the context-size UI warning goes
// away. The actual numbers don't matter too much: `countTokens` checks the
// most recent assistant message for usage numbers, so this estimate will
// be overridden quickly.
summaryResponse.message.usage = {
input_tokens: 0,
output_tokens: summaryResponse.message.usage.output_tokens,
cache_creation_input_tokens: 0,
cache_read_input_tokens: 0,
};
// Clear screen and messages
await clearTerminal();
getMessagesSetter()([]);
setForkConvoWithMessagesOnTheNextRender([
createUserMessage(
`Use the /compact command to clear the conversation history, and start a new conversation with the summary in context.`
),
summaryResponse,
]);
getContext.cache.clear?.();
getCodeStyle.cache.clear?.();
return ""; // not used, just for typesafety. TODO: avoid this hack
},
userFacingName() {
return "compact";
},
} satisfies Command;
export default compact;
Functionality
The compact
command implements a sophisticated workflow:
-
Conversation Summary Generation:
- Retrieves the current message history
- Creates a user message requesting a conversation summary
- Uses Claude API to generate a summary through the
querySonnet
function - Validates the summary to ensure it was successfully generated
-
Token Usage Management:
- Manipulates the usage data to prevent context-size warnings
- Sets input tokens to 0 to indicate the conversation has been compacted
-
Context Reset with Summary:
- Clears the terminal display
- Resets message history
- Creates a new conversation "fork" containing only:
- A user message indicating a compact operation occurred
- The generated summary response
- Clears context and code style caches
Technical Implementation Notes
The compact
command demonstrates several advanced patterns:
-
Meta-Conversation: The command uses Claude to talk about the conversation itself, leveraging the model's summarization abilities.
-
Model Selection: Explicitly uses the
slowAndCapableModel
option to ensure high-quality summarization. -
Content Extraction Logic: Implements robust parsing of the response content, handling different content formats (string vs. structured content).
-
Error Handling: Provides clear error messages for when summarization fails or when the API returns an error.
-
Token Manipulation: Intelligently manipulates token usage information to maintain a good user experience after compaction.
-
Conversation Forking: Uses the
setForkConvoWithMessagesOnTheNextRender
mechanism to create a new conversation branch with only the summary.
User Experience Benefits
The compact
command addresses several key pain points in AI assistant interactions:
-
Context Window Management: Helps users stay within token limits while preserving the essence of the conversation.
-
Conversation Continuity: Unlike a complete clear, it maintains the thread of discussion through the summary.
-
Work Session Persistence: Preserves information about files being edited and tasks in progress.
-
Smart Reset: Performs a targeted reset that balances clearing space with maintaining context.
The command is particularly valuable for long development sessions where context limits become an issue but completely starting over would lose important progress information.
ctx_viz Command
The ctx_viz
command provides a detailed visualization of token usage across different components of the Claude conversation context, helping users understand how their context window is being utilized.
Implementation
The command is implemented in commands/ctx_viz.ts
as a type: 'local' command that generates a formatted table of token usage:
import type { Command } from "../commands";
import type { Tool } from "../Tool";
import Table from "cli-table3";
import { getSystemPrompt } from "../constants/prompts";
import { getContext } from "../context";
import { zodToJsonSchema } from "zod-to-json-schema";
import { getMessagesGetter } from "../messages";
// Quick and dirty estimate of bytes per token for rough token counts
const BYTES_PER_TOKEN = 4;
interface Section {
title: string;
content: string;
}
interface ToolSummary {
name: string;
description: string;
}
function getContextSections(text: string): Section[] {
const sections: Section[] = [];
// Find first <context> tag
const firstContextIndex = text.indexOf("<context");
// Everything before first tag is Core Sysprompt
if (firstContextIndex > 0) {
const coreSysprompt = text.slice(0, firstContextIndex).trim();
if (coreSysprompt) {
sections.push({
title: "Core Sysprompt",
content: coreSysprompt,
});
}
}
let currentPos = firstContextIndex;
let nonContextContent = "";
const regex = /<context\s+name="([^"]*)">([\s\S]*?)<\/context>/g;
let match: RegExpExecArray | null;
while ((match = regex.exec(text)) !== null) {
// Collect text between context tags
if (match.index > currentPos) {
nonContextContent += text.slice(currentPos, match.index);
}
const [, name = "Unnamed Section", content = ""] = match;
sections.push({
title: name === "codeStyle" ? "CodeStyle + KODING.md's" : name,
content: content.trim(),
});
currentPos = match.index + match[0].length;
}
// Collect remaining text after last tag
if (currentPos < text.length) {
nonContextContent += text.slice(currentPos);
}
// Add non-contextualized content if present
const trimmedNonContext = nonContextContent.trim();
if (trimmedNonContext) {
sections.push({
title: "Non-contextualized Content",
content: trimmedNonContext,
});
}
return sections;
}
function formatTokenCount(bytes: number): string {
const tokens = bytes / BYTES_PER_TOKEN;
const k = tokens / 1000;
return `${Math.round(k * 10) / 10}k`;
}
function formatByteCount(bytes: number): string {
const kb = bytes / 1024;
return `${Math.round(kb * 10) / 10}kb`;
}
function createSummaryTable(
systemText: string,
systemSections: Section[],
tools: ToolSummary[],
messages: unknown
): string {
const table = new Table({
head: ["Component", "Tokens", "Size", "% Used"],
style: { head: ["bold"] },
chars: {
mid: "─",
"left-mid": "├",
"mid-mid": "┼",
"right-mid": "┤",
},
});
const messagesStr = JSON.stringify(messages);
const toolsStr = JSON.stringify(tools);
// Calculate total for percentages
const total = systemText.length + toolsStr.length + messagesStr.length;
const getPercentage = (n: number) => `${Math.round((n / total) * 100)}%`;
// System prompt and its sections
table.push([
"System prompt",
formatTokenCount(systemText.length),
formatByteCount(systemText.length),
getPercentage(systemText.length),
]);
for (const section of systemSections) {
table.push([
` ${section.title}`,
formatTokenCount(section.content.length),
formatByteCount(section.content.length),
getPercentage(section.content.length),
]);
}
// Tools
table.push([
"Tool definitions",
formatTokenCount(toolsStr.length),
formatByteCount(toolsStr.length),
getPercentage(toolsStr.length),
]);
for (const tool of tools) {
table.push([
` ${tool.name}`,
formatTokenCount(tool.description.length),
formatByteCount(tool.description.length),
getPercentage(tool.description.length),
]);
}
// Messages and total
table.push(
[
"Messages",
formatTokenCount(messagesStr.length),
formatByteCount(messagesStr.length),
getPercentage(messagesStr.length),
],
["Total", formatTokenCount(total), formatByteCount(total), "100%"]
);
return table.toString();
}
const command: Command = {
name: "ctx-viz",
description:
"[ANT-ONLY] Show token usage breakdown for the current conversation context",
isEnabled: true,
isHidden: false,
type: "local",
userFacingName() {
return this.name;
},
async call(_args: string, cmdContext: { options: { tools: Tool[] } }) {
// Get tools and system prompt with injected context
const [systemPromptRaw, sysContext] = await Promise.all([
getSystemPrompt(),
getContext(),
]);
const rawTools = cmdContext.options.tools;
// Full system prompt with context sections injected
let systemPrompt = systemPromptRaw.join("\n");
for (const [name, content] of Object.entries(sysContext)) {
systemPrompt += `\n<context name="${name}">${content}</context>`;
}
// Get full tool definitions including prompts and schemas
const tools = rawTools.map((t) => {
// Get full prompt and schema
const fullPrompt = t.prompt({ dangerouslySkipPermissions: false });
const schema = JSON.stringify(
"inputJSONSchema" in t && t.inputJSONSchema
? t.inputJSONSchema
: zodToJsonSchema(t.inputSchema)
);
return {
name: t.name,
description: `${fullPrompt}\n\nSchema:\n${schema}`,
};
});
// Get current messages from REPL
const messages = getMessagesGetter()();
const sections = getContextSections(systemPrompt);
return createSummaryTable(systemPrompt, sections, tools, messages);
},
};
export default command;
Functionality
The ctx_viz
command provides a detailed breakdown of token usage across different components of the conversation context:
-
System Prompt Analysis:
- Parses the system prompt to identify its separate sections
- Extracts
<context>
tags and their contents for individual analysis - Identifies core system prompt sections vs. injected context
-
Token Usage Calculation:
- Estimates token usage based on a bytes-per-token approximation
- Presents data in kilobytes and estimated token counts
- Calculates percentage usage for each component of the context
-
Tool Definitions Analysis:
- Extracts complete tool definitions including prompts and JSON schemas
- Calculates token usage per tool
- Shows the total footprint of tool definitions in the context
-
Conversation Message Analysis:
- Includes the current message history in the analysis
- Shows what portion of the context window is used by the conversation
-
Structured Presentation:
- Outputs a formatted ASCII table with columns for component, tokens, size, and percentage
- Uses hierarchical indentation to show the structure of the context
- Includes totals for complete context usage
Technical Implementation Notes
The ctx_viz
command demonstrates several sophisticated implementation patterns:
-
Regex-Based Context Parsing: Uses regular expressions to parse the context sections from the system prompt, handling nested tags and multi-line content.
-
Parallel Resource Loading: Uses
Promise.all
to concurrently fetch system prompt and context data for efficiency. -
Tool Schema Introspection: Extracts JSON schemas from tool definitions using either explicit schemas or by converting Zod schemas to JSON Schema format.
-
Token Approximation: Implements a simple but effective token estimation approach based on byte length, which provides a reasonable approximation without requiring a tokenizer.
-
Table Formatting: Uses the
cli-table3
library to create a formatted ASCII table with custom styling, making the output readable in a terminal environment. -
Context Section Management: Special-cases certain context sections like "codeStyle" with custom labeling for clarity.
User Experience Benefits
The ctx_viz
command addresses several important needs for developers using Claude Code:
-
Context Window Transparency: Gives users insight into how their limited context window is being utilized.
-
Optimization Opportunities: Helps identify large components that might be consuming excessive context, enabling targeted optimization.
-
Debugging Aid: Provides a debugging tool for situations where context limitations are affecting Claude's performance.
-
System Prompt Visibility: Makes the usually hidden system prompt and context visible to users for better understanding of Claude's behavior.
The command is particularly valuable for advanced users and developers who need to understand and optimize their context usage to get the most out of Claude's capabilities within token limitations.
doctor Command
The doctor
command provides a diagnostic tool for checking the health of the Claude Code installation, with a focus on npm permissions required for proper auto-updating functionality.
Implementation
The command is implemented in commands/doctor.ts
as a type: 'local-jsx' command that renders a React component:
import React from "react";
import type { Command } from "../commands";
import { Doctor } from "../screens/Doctor";
const doctor: Command = {
name: "doctor",
description: "Checks the health of your Claude Code installation",
isEnabled: true,
isHidden: false,
userFacingName() {
return "doctor";
},
type: "local-jsx",
call(onDone) {
const element = React.createElement(Doctor, {
onDone,
doctorMode: true,
});
return Promise.resolve(element);
},
};
export default doctor;
The command uses the Doctor
screen component defined in screens/Doctor.tsx
, passing the special doctorMode
flag to indicate it's being used as a diagnostic tool rather than during initialization.
Functionality
The doctor
command implements a comprehensive installation health check focused on npm permissions:
-
Permissions Verification:
- Checks if the npm global installation directory has correct write permissions
- Determines the current npm prefix path
- Validates if auto-updates can function correctly
-
Status Reporting:
- Provides clear success or failure messages about installation health
- Shows a green checkmark and confirmation message for healthy installations
- Presents an interactive dialog for resolving permission issues
-
Problem Resolution:
- Offers three remediation options when permission problems are detected:
- Manual Fix: Provides a sudo/icacls command to fix permissions on the current npm prefix
- New Prefix: Guides the user through creating a new npm prefix in their home directory
- Skip: Allows deferring the fix until later
- Offers three remediation options when permission problems are detected:
-
Installation Repair:
- For the "new prefix" option, provides a guided, step-by-step process to:
- Create a new directory for npm global packages
- Configure npm to use the new location
- Update shell PATH configurations
- Reinstall Claude Code globally
- For the "new prefix" option, provides a guided, step-by-step process to:
Technical Implementation Notes
The command demonstrates several sophisticated implementation patterns:
-
Component-Based Architecture: Uses React components for the UI, allowing for a rich interactive experience.
-
Platform-Aware Logic: Implements different permission-fixing approaches for Windows vs. Unix-like systems:
- Windows: Uses
icacls
for permission management andsetx
for PATH updates - Unix: Uses
sudo chown/chmod
for permission fixes and shell config file updates
- Windows: Uses
-
Shell Detection: For Unix platforms, identifies and updates multiple possible shell configuration files:
- .bashrc and .bash_profile for Bash
- .zshrc for Zsh
- config.fish for Fish shell
-
Status Management: Uses React state to track:
- Permission check status
- Selected remediation option
- Custom prefix path (if chosen)
- Step-by-step installation progress
-
Lock-Based Concurrency Control: Implements a file-based locking mechanism to prevent multiple processes from attempting auto-updates simultaneously.
-
Error Handling: Provides detailed error reporting and recovery options:
- Shows precisely which operation failed
- Offers alternative approaches when errors occur
- Logs error details for debugging
User Experience Benefits
The doctor
command addresses several important pain points for CLI tool users:
-
Installation Troubleshooting: Provides clear diagnostics and fixes for common problems:
- Permission issues that prevent updates
- Global npm configuration problems
- PATH configuration issues
-
Security-Conscious Design: Offers both privileged (sudo) and non-privileged (new prefix) solutions, allowing users to choose based on their security preferences.
-
Multi-Platform Support: Works identically across Windows, macOS, and Linux with platform-appropriate solutions.
-
Shell Environment Enhancement: Automatically updates shell configuration files to ensure the installation works correctly across terminal sessions.
-
Visual Progress Feedback: Uses spinners and checkmarks to keep users informed about long-running operations.
The command provides a comprehensive diagnostics and repair tool that helps maintain a healthy Claude Code installation, particularly focusing on the auto-update capability which is crucial for keeping the tool current with new features and improvements.
help Command
The help
command provides users with information about Claude Code's usage, available commands, and general guidance for effective interaction with the tool.
Implementation
The command is implemented in commands/help.tsx
as a type: 'local-jsx' command that renders a React component:
import { Command } from "../commands";
import { Help } from "../components/Help";
import * as React from "react";
const help = {
type: "local-jsx",
name: "help",
description: "Show help and available commands",
isEnabled: true,
isHidden: false,
async call(onDone, { options: { commands } }) {
return <Help commands={commands} onClose={onDone} />;
},
userFacingName() {
return "help";
},
} satisfies Command;
export default help;
The command delegates to the Help
component in components/Help.tsx
, passing the list of available commands and an onClose
callback to handle when the help screen should be dismissed.
Functionality
The Help
component implements a progressive disclosure pattern for displaying information:
-
Basic Information:
- Shows the product name and version
- Displays a brief description of Claude Code's capabilities and limitations
- Presents a disclaimer about the beta nature of the product
-
Usage Modes (shown after a brief delay):
- Explains the two primary ways to use Claude Code:
- REPL (interactive session)
- Non-interactive mode with the
-p
flag for one-off questions
- Mentions that users can run
claude -h
for additional command-line options
- Explains the two primary ways to use Claude Code:
-
Common Tasks (shown after a longer delay):
- Lists examples of typical use cases:
- Asking questions about the codebase
- Editing files
- Fixing errors
- Running commands
- Running bash commands
- Lists examples of typical use cases:
-
Available Commands (shown after the longest delay):
- Displays a comprehensive list of all enabled slash commands
- Shows command names and descriptions
- Filters out hidden commands
-
Additional Resources:
- Provides links for getting more help
- Shows different resources based on user type (internal vs. external)
Technical Implementation Notes
The help
command demonstrates several effective patterns:
-
Progressive Disclosure: Uses a time-based mechanism to gradually reveal information:
const [count, setCount] = React.useState(0); React.useEffect(() => { const timer = setTimeout(() => { if (count < 3) { setCount(count + 1); } }, 250); return () => clearTimeout(timer); }, [count]);
This approach avoids overwhelming users with too much information at once, showing more details as they spend time on the help screen.
-
Filtering System: Uses
filter
to show only non-hidden commands:const filteredCommands = commands.filter((cmd) => !cmd.isHidden);
This keeps the help screen focused on commands relevant to users.
-
Dynamic Resource Links: Changes help resources based on user type:
const isInternal = process.env.USER_TYPE === "ant"; const moreHelp = isInternal ? "[ANT-ONLY] For more help: go/claude-cli or #claude-cli-feedback" : `Learn more at: ${MACRO.README_URL}`;
This customizes the experience for different user populations.
-
Input Handling: Uses Ink's
useInput
hook to detect when the user presses Enter:useInput((_, key) => { if (key.return) onClose(); });
This allows for clean dismissal of the help screen.
-
Conditional Rendering: Uses the
count
state to progressively show different sections:{ count >= 1 && ( <Box flexDirection="column" marginTop={1}> <Text bold>Usage Modes:</Text> {/* Usage content */} </Box> ); }
This creates the staggered reveal effect for information groups.
User Experience Benefits
The help
command addresses several important needs for CLI tool users:
-
Onboarding Assistance: Provides new users with immediate guidance on how to use the tool effectively.
-
Command Discovery: Makes it easy to see what slash commands are available without having to memorize them.
-
Progressive Learning: The staggered reveal of information allows users to absorb basics first before seeing more advanced options.
-
Usage Examples: Shows concrete examples of common use cases, helping users understand practical applications.
-
Quick Reference: Serves as a compact reference for command options during regular use.
The help command exemplifies Claude Code's approach to user experience: it's focused on being informative while remaining concise and unobtrusive, with multiple levels of detail available as users need them.
init Command
The init
command helps users initialize a new project for use with Claude Code by creating a KODING.md file that contains key information about the codebase and project.
Implementation
The command is implemented in commands/init.ts
as a type: 'prompt' command that passes a specific request to Claude:
import type { Command } from "../commands";
import { markProjectOnboardingComplete } from "../ProjectOnboarding";
const command = {
type: "prompt",
name: "init",
description: "Initialize a new KODING.md file with codebase documentation",
isEnabled: true,
isHidden: false,
progressMessage: "analyzing your codebase",
userFacingName() {
return "init";
},
async getPromptForCommand(_args: string) {
// Mark onboarding as complete when init command is run
markProjectOnboardingComplete();
return [
{
role: "user",
content: [
{
type: "text",
text: `Please analyze this codebase and create a KODING.md file containing:
1. Build/lint/test commands - especially for running a single test
2. Code style guidelines including imports, formatting, types, naming conventions, error handling, etc.
The file you create will be given to agentic coding agents (such as yourself) that operate in this repository. Make it about 20 lines long.
If there's already a KODING.md, improve it.
If there are Cursor rules (in .cursor/rules/ or .cursorrules) or Copilot rules (in .github/copilot-instructions.md), make sure to include them.`,
},
],
},
];
},
} satisfies Command;
export default command;
Unlike many other commands that directly perform actions, the init
command is implemented as a 'prompt' type command that simply formulates a specific request to Claude to analyze the codebase and generate a KODING.md file.
Functionality
The init
command serves several important functions:
-
Project Configuration Generation:
- Instructs Claude to analyze the codebase structure, conventions, and patterns
- Generates a KODING.md file with essential project information
- Focuses on capturing build/lint/test commands and code style guidelines
-
Existing File Enhancement:
- Checks if a KODING.md file already exists
- Improves the existing file with additional information if present
- Preserves existing content while enhancing where needed
-
Integration with Other Tools:
- Looks for Cursor rules (in .cursor/rules/ or .cursorrules)
- Looks for Copilot instructions (in .github/copilot-instructions.md)
- Incorporates these rules into the KODING.md file for a unified guidance document
-
Onboarding Status Tracking:
- Calls
markProjectOnboardingComplete()
to update the project configuration - This flags the project as having completed onboarding steps
- Prevents repeated onboarding prompts in future sessions
- Calls
Technical Implementation Notes
The init
command demonstrates several interesting technical aspects:
-
Command Type: Uses the 'prompt' type rather than 'local' or 'local-jsx', which means it sets up a specific request to Claude rather than executing custom logic or rendering a UI component.
-
Progress Message: Includes a
progressMessage
property ("analyzing your codebase") that's displayed to users while Claude processes the request, providing feedback during what could be a longer operation. -
Project Onboarding Integration: The command is part of the project onboarding workflow, tracking completion state in the project configuration:
export function markProjectOnboardingComplete(): void { const projectConfig = getCurrentProjectConfig(); if (!projectConfig.hasCompletedProjectOnboarding) { saveCurrentProjectConfig({ ...projectConfig, hasCompletedProjectOnboarding: true, }); } }
-
External Tool Recognition: Explicitly looks for configuration files from other AI coding tools (Cursor, Copilot) to create a unified guidance document, showing awareness of the broader AI coding tool ecosystem.
-
Conciseness Guidance: Explicitly requests a document of around 20 lines, balancing comprehensive information with brevity for practical usage.
User Experience Benefits
The init
command provides several important benefits for Claude Code users:
-
Simplified Project Setup: Makes it easy to prepare a codebase for effective use with Claude Code with a single command.
-
Consistent Memory: Creates a standardized document that Claude Code will access in future sessions, providing consistent context.
-
Command Discovery: By capturing build/test/lint commands, it helps Claude remember the correct commands for the project, reducing the need for users to repeatedly provide them.
-
Code Style Guidance: Helps Claude generate code that matches the project's conventions, improving integration of AI-generated code.
-
Onboarding Pathway: Serves as a key step in the onboarding flow for new projects, guiding users toward the most effective usage patterns.
The init
command exemplifies Claude Code's overall approach to becoming more effective over time by creating persistent context that improves future interactions. By capturing project-specific information in a standardized format, it enables Claude to provide more tailored assistance for each unique codebase.
listen Command
The listen
command provides macOS users with the ability to dictate to Claude Code using speech recognition, enhancing accessibility and offering an alternative input method.
Implementation
The command is implemented in commands/listen.ts
as a type: 'local' command that invokes macOS's built-in dictation feature:
import { Command } from "../commands";
import { logError } from "../utils/log";
import { execFileNoThrow } from "../utils/execFileNoThrow";
const isEnabled =
process.platform === "darwin" &&
["iTerm.app", "Apple_Terminal"].includes(process.env.TERM_PROGRAM || "");
const listen: Command = {
type: "local",
name: "listen",
description: "Activates speech recognition and transcribes speech to text",
isEnabled: isEnabled,
isHidden: isEnabled,
userFacingName() {
return "listen";
},
async call(_, { abortController }) {
// Start dictation using AppleScript
const script = `tell application "System Events" to tell ¬
(the first process whose frontmost is true) to tell ¬
menu bar 1 to tell ¬
menu bar item "Edit" to tell ¬
menu "Edit" to tell ¬
menu item "Start Dictation" to ¬
if exists then click it`;
const { stderr, code } = await execFileNoThrow(
"osascript",
["-e", script],
abortController.signal
);
if (code !== 0) {
logError(`Failed to start dictation: ${stderr}`);
return "Failed to start dictation";
}
return "Dictation started. Press esc to stop.";
},
};
export default listen;
The command uses AppleScript to trigger macOS's built-in dictation feature, automating the process of selecting "Start Dictation" from the Edit menu.
Functionality
The listen
command provides a simple but effective accessibility enhancement:
-
Platform Integration:
- Invokes macOS's built-in dictation feature
- Uses AppleScript to navigate the application's menu structure
- Triggers the "Start Dictation" menu item in the Edit menu
-
Status Reporting:
- Returns clear success or error messages
- Provides user instructions on how to stop dictation
- Logs detailed error information when dictation fails to start
-
Platform-Specific Availability:
- Only enabled on macOS platforms
- Further restricted to specific terminal applications (iTerm.app and Apple_Terminal)
- Hidden from command listings on unsupported platforms
Technical Implementation Notes
The listen
command demonstrates several interesting technical approaches:
-
Platform Detection: Uses environment variables and platform checks to determine when the command should be available:
const isEnabled = process.platform === "darwin" && ["iTerm.app", "Apple_Terminal"].includes(process.env.TERM_PROGRAM || "");
-
AppleScript Integration: Uses a complex AppleScript command to navigate through application menus:
const script = `tell application "System Events" to tell ¬ (the first process whose frontmost is true) to tell ¬ menu bar 1 to tell ¬ menu bar item "Edit" to tell ¬ menu "Edit" to tell ¬ menu item "Start Dictation" to ¬ if exists then click it`;
This script navigates the UI hierarchy to find and click the dictation menu item.
-
Command Visibility Control: Uses the same conditions for both
isEnabled
andisHidden
, ensuring the command is simultaneously enabled and hidden on supported platforms:isEnabled: isEnabled, isHidden: isEnabled,
This unusual pattern makes the command available but not visible in help listings, suggesting it's an internal or experimental feature.
-
Error Handling: Implements robust error handling with detailed logging:
if (code !== 0) { logError(`Failed to start dictation: ${stderr}`); return "Failed to start dictation"; }
User Experience Considerations
While simple in implementation, the listen
command addresses several important user needs:
-
Accessibility Enhancement: Provides an alternative input method for users who prefer or require speech recognition.
-
Workflow Efficiency: Eliminates the need to manually navigate menus to start dictation, streamlining the process.
-
Integrated Experience: Keeps users within the Claude Code interface rather than requiring them to use separate dictation tools.
-
Platform Integration: Leverages native OS capabilities rather than implementing custom speech recognition, ensuring high-quality transcription.
The listen
command demonstrates Claude Code's commitment to accessibility and platform integration, even if the implementation is relatively simple. By leveraging existing OS capabilities rather than reinventing them, it provides a valuable feature with minimal code complexity.
login Command
The login
command provides users with a secure OAuth 2.0 authentication flow to connect Claude Code with their Anthropic Console account, enabling API access and proper billing.
Implementation
The command is implemented in commands/login.tsx
as a type: 'local-jsx' command that renders a React component for the authentication flow:
import * as React from "react";
import type { Command } from "../commands";
import { ConsoleOAuthFlow } from "../components/ConsoleOAuthFlow";
import { clearTerminal } from "../utils/terminal";
import { isLoggedInToAnthropic } from "../utils/auth";
import { useExitOnCtrlCD } from "../hooks/useExitOnCtrlCD";
import { Box, Text } from "ink";
import { clearConversation } from "./clear";
export default () =>
({
type: "local-jsx",
name: "login",
description: isLoggedInToAnthropic()
? "Switch Anthropic accounts"
: "Sign in with your Anthropic account",
isEnabled: true,
isHidden: false,
async call(onDone, context) {
await clearTerminal();
return (
<Login
onDone={async () => {
clearConversation(context);
onDone();
}}
/>
);
},
userFacingName() {
return "login";
},
} satisfies Command);
function Login(props: { onDone: () => void }) {
const exitState = useExitOnCtrlCD(props.onDone);
return (
<Box flexDirection="column">
<ConsoleOAuthFlow onDone={props.onDone} />
<Box marginLeft={3}>
<Text dimColor>
{exitState.pending ? (
<>Press {exitState.keyName} again to exit</>
) : (
""
)}
</Text>
</Box>
</Box>
);
}
The command uses a factory function to dynamically create a command object that adapts its description based on the current login state. The main logic is delegated to the ConsoleOAuthFlow
component, which handles the OAuth flow with the Anthropic API.
Functionality
The login
command implements a comprehensive authentication flow:
-
OAuth 2.0 Integration:
- Uses OAuth 2.0 with PKCE (Proof Key for Code Exchange) for security
- Opens a browser for the user to log in to Anthropic Console
- Handles both automatic browser redirect and manual code entry flows
- Securely exchanges authorization codes for access tokens
-
Account Management:
- Creates and stores API keys for authenticated users
- Normalizes and securely saves keys in the global configuration
- Tracks account information including account UUID and organization details
- Provides context-aware descriptions ("Sign in" vs "Switch accounts")
-
Security Features:
- Implements state verification to prevent CSRF attacks
- Uses code verifiers and challenges for secure code exchange
- Validates all tokens and responses from the authentication server
- Provides clear error messages for authentication failures
-
UI Experience:
- Clears the terminal for a clean login experience
- Provides a progressive disclosure flow with appropriate status messages
- Offers fallback mechanisms for cases where automatic browser opening fails
- Shows loading indicators during asynchronous operations
Technical Implementation Notes
The login command demonstrates several sophisticated technical approaches:
-
Local HTTP Server: Creates a temporary HTTP server for OAuth callback handling:
this.server = http.createServer( (req: IncomingMessage, res: ServerResponse) => { const parsedUrl = url.parse(req.url || "", true); if (parsedUrl.pathname === "/callback") { // Handle OAuth callback } } );
-
PKCE Implementation: Implements the Proof Key for Code Exchange extension to OAuth:
function generateCodeVerifier(): string { return base64URLEncode(crypto.randomBytes(32)); } async function generateCodeChallenge(verifier: string): Promise<string> { const encoder = new TextEncoder(); const data = encoder.encode(verifier); const digest = await crypto.subtle.digest("SHA-256", data); return base64URLEncode(Buffer.from(digest)); }
-
Parallel Authentication Paths: Supports both automatic and manual authentication flows:
const { autoUrl, manualUrl } = this.generateAuthUrls(codeChallenge, state); await authURLHandler(manualUrl); // Show manual URL in UI await openBrowser(autoUrl); // Try automatic browser opening
-
Promise-Based Flow Control: Uses promises to coordinate the asynchronous authentication flow:
const { authorizationCode, useManualRedirect } = await new Promise<{ authorizationCode: string; useManualRedirect: boolean; }>((resolve, reject) => { this.pendingCodePromise = { resolve, reject }; this.startLocalServer(state, onReady); });
-
State Management with React: Uses React state and hooks for UI management:
const [oauthStatus, setOAuthStatus] = useState<OAuthStatus>({ state: "idle", });
-
Error Recovery: Implements sophisticated error handling with retry mechanisms:
if (oauthStatus.state === "error" && oauthStatus.toRetry) { setPastedCode(""); setOAuthStatus({ state: "about_to_retry", nextState: oauthStatus.toRetry, }); }
User Experience Benefits
The login
command addresses several important user needs:
-
Seamless Authentication: Provides a smooth authentication experience without requiring manual API key creation or copying.
-
Cross-Platform Compatibility: Works across different operating systems and browsers.
-
Fallback Mechanisms: Offers manual code entry when automatic browser redirection fails.
-
Clear Progress Indicators: Shows detailed status messages throughout the authentication process.
-
Error Resilience: Provides helpful error messages and retry options when authentication issues occur.
-
Account Switching: Allows users to easily switch between different Anthropic accounts.
The login command exemplifies Claude Code's approach to security and user experience, implementing a complex authentication flow with attention to both security best practices and ease of use.
logout Command
The logout
command provides users with the ability to sign out from their Anthropic account, removing stored authentication credentials and API keys from the local configuration.
Implementation
The command is implemented in commands/logout.tsx
as a type: 'local-jsx' command that handles the logout process and renders a confirmation message:
import * as React from "react";
import type { Command } from "../commands";
import { getGlobalConfig, saveGlobalConfig } from "../utils/config";
import { clearTerminal } from "../utils/terminal";
import { Text } from "ink";
export default {
type: "local-jsx",
name: "logout",
description: "Sign out from your Anthropic account",
isEnabled: true,
isHidden: false,
async call() {
await clearTerminal();
const config = getGlobalConfig();
config.oauthAccount = undefined;
config.primaryApiKey = undefined;
config.hasCompletedOnboarding = false;
if (config.customApiKeyResponses?.approved) {
config.customApiKeyResponses.approved = [];
}
saveGlobalConfig(config);
const message = (
<Text>Successfully logged out from your Anthropic account.</Text>
);
setTimeout(() => {
process.exit(0);
}, 200);
return message;
},
userFacingName() {
return "logout";
},
} satisfies Command;
Unlike the more complex login
command, the logout
command is relatively straightforward, focusing on removing authentication data from the configuration and providing a clean exit.
Functionality
The logout
command performs several critical operations:
-
Credential Removal:
- Clears the OAuth account information from the global configuration
- Removes the primary API key used for authentication
- Erases the list of approved API keys from storage
- Resets the onboarding completion status
-
User Experience:
- Clears the terminal before displaying the logout message
- Provides a clear confirmation message about successful logout
- Exits the application completely after a short delay
- Ensures a clean break with the authenticated session
-
Security Focus:
- Removes all sensitive authentication data from the local configuration
- Ensures the next application start will require re-authentication
- Prevents accidental API usage with old credentials
- Provides a clean slate for a new login if desired
Technical Implementation Notes
Despite its relative simplicity, the logout
command demonstrates several interesting implementation details:
-
Configuration Management: Uses the global configuration system to handle persistent state:
const config = getGlobalConfig(); config.oauthAccount = undefined; config.primaryApiKey = undefined; config.hasCompletedOnboarding = false; if (config.customApiKeyResponses?.approved) { config.customApiKeyResponses.approved = []; } saveGlobalConfig(config);
-
Graceful Exit Strategy: Uses a timeout to allow the message to be displayed before exiting:
setTimeout(() => { process.exit(0); }, 200);
This ensures the user sees confirmation before the application closes.
-
Type Safety: Uses the
satisfies Command
pattern to ensure type correctness:export default { // Command implementation } satisfies Command;
-
Terminal Management: Clears the terminal before displaying the logout confirmation:
await clearTerminal();
This creates a clean visual experience for the logout process.
-
Optional Field Handling: Carefully checks for the existence of optional configuration fields:
if (config.customApiKeyResponses?.approved) { config.customApiKeyResponses.approved = []; }
User Experience Benefits
The logout
command addresses several important user needs:
-
Account Security: Provides a clear way to remove credentials when sharing devices or ending a session.
-
User Confidence: Confirms successful logout with a clear message, reassuring users their credentials have been removed.
-
Clean Exit: Exits the application completely, avoiding any state confusion in the current process.
-
Simplicity: Keeps the logout process straightforward and quick, with minimal user interaction required.
-
Fresh Start: Resets the onboarding status, ensuring a proper re-onboarding flow on next login.
The logout
command provides a necessary counterpart to the login
command, completing the authentication lifecycle with a secure, clean way to end a session. While much simpler than its login counterpart, it maintains the same attention to security and user experience that characterizes Claude Code's approach to authentication management.
model Command
[!WARNING] This command implementation is specific to the anon-kode fork of Claude Code and is not part of the original Claude Code codebase. The analysis below pertains to this specific implementation rather than standard Claude Code functionality.
The model
command provides users with a comprehensive interface to configure and customize the AI models used by Claude Code, enabling fine-grained control over model selection, parameters, and provider settings.
Implementation
The command is implemented in commands/model.tsx
as a type: 'local-jsx' command that renders a React component for model configuration:
import React from "react";
import { render } from "ink";
import { ModelSelector } from "../components/ModelSelector";
import { enableConfigs } from "../utils/config";
export const help = "Change your AI provider and model settings";
export const description = "Change your AI provider and model settings";
export const isEnabled = true;
export const isHidden = false;
export const name = "model";
export const type = "local-jsx";
export function userFacingName(): string {
return name;
}
export async function call(
onDone: (result?: string) => void,
{ abortController }: { abortController?: AbortController }
): Promise<React.ReactNode> {
enableConfigs();
abortController?.abort?.();
return (
<ModelSelector
onDone={() => {
onDone();
}}
/>
);
}
The command uses a different export style than other commands, directly exporting properties and functions rather than a single object. The main functionality is handled by the ModelSelector
component, which provides an interactive UI for configuring model settings.
Functionality
The model
command provides a sophisticated model selection and configuration workflow:
-
Multi-Model Management:
- Allows configuring both "large" and "small" models separately or together
- Provides different models for different task complexities for optimal cost/performance
- Shows current configuration information for reference
-
Provider Selection:
- Supports multiple AI providers (Anthropic, OpenAI, Gemini, etc.)
- Dynamically fetches available models from the selected provider's API
- Handles provider-specific API requirements and authentication
-
Model Parameters:
- Configures maximum token settings for response length control
- Offers reasoning effort controls for supported models (low/medium/high)
- Preserves provider-specific configuration options
-
Search and Filtering:
- Provides search functionality to filter large model lists
- Displays model capabilities including token limits and feature support
- Organizes models with sensible sorting and grouping
-
API Key Management:
- Securely handles API keys for different providers
- Masks sensitive information during input and display
- Stores keys securely in the local configuration
Technical Implementation Notes
The model
command demonstrates several sophisticated technical approaches:
-
Multi-Step Navigation: Implements a screen stack pattern for intuitive flow navigation:
const [screenStack, setScreenStack] = useState< Array< | "modelType" | "provider" | "apiKey" | "model" | "modelParams" | "confirmation" > >(["modelType"]); // Current screen is always the last item in the stack const currentScreen = screenStack[screenStack.length - 1]; // Function to navigate to a new screen const navigateTo = ( screen: | "modelType" | "provider" | "apiKey" | "model" | "modelParams" | "confirmation" ) => { setScreenStack((prev) => [...prev, screen]); }; // Function to go back to the previous screen const goBack = () => { if (screenStack.length > 1) { // Remove the current screen from the stack setScreenStack((prev) => prev.slice(0, -1)); } else { // If we're at the first screen, call onDone to exit onDone(); } };
-
Dynamic Model Loading: Fetches available models directly from provider APIs:
async function fetchModels() { setIsLoadingModels(true); setModelLoadError(null); try { // Provider-specific logic... const openai = new OpenAI({ apiKey: apiKey, baseURL: baseURL, dangerouslyAllowBrowser: true, }); // Fetch the models const response = await openai.models.list(); // Transform the response into our ModelInfo format const fetchedModels = []; // Process models... return fetchedModels; } catch (error) { setModelLoadError(`Failed to load models: ${error.message}`); throw error; } finally { setIsLoadingModels(false); } }
-
Form Focus Management: Implements sophisticated form navigation with keyboard support:
// Handle Tab key for form navigation in model params screen useInput((input, key) => { if (currentScreen === "modelParams" && key.tab) { const formFields = getFormFieldsForModelParams(); // Move to next field setActiveFieldIndex((current) => (current + 1) % formFields.length); return; } // Handle Enter key for form submission in model params screen if (currentScreen === "modelParams" && key.return) { const formFields = getFormFieldsForModelParams(); if (activeFieldIndex === formFields.length - 1) { // If on the Continue button, submit the form handleModelParamsSubmit(); } return; } });
-
Provider-Specific Handling: Implements custom logic for different AI providers:
// For Gemini, use the separate fetchGeminiModels function if (selectedProvider === "gemini") { const geminiModels = await fetchGeminiModels(); setAvailableModels(geminiModels); navigateTo("model"); return geminiModels; }
-
Configuration Persistence: Carefully updates global configuration with new model settings:
function saveConfiguration(provider: ProviderType, model: string) { const baseURL = providers[provider]?.baseURL || ""; // Create a new config object based on the existing one const newConfig = { ...config }; // Update the primary provider regardless of which model we're changing newConfig.primaryProvider = provider; // Update the appropriate model based on the selection if (modelTypeToChange === "both" || modelTypeToChange === "large") { newConfig.largeModelName = model; newConfig.largeModelBaseURL = baseURL; newConfig.largeModelApiKey = apiKey || config.largeModelApiKey; newConfig.largeModelMaxTokens = parseInt(maxTokens); // Save reasoning effort for large model if supported if (supportsReasoningEffort) { newConfig.largeModelReasoningEffort = reasoningEffort; } else { newConfig.largeModelReasoningEffort = undefined; } } // Similar handling for small model... // Save the updated configuration saveGlobalConfig(newConfig); }
User Experience Benefits
The model
command provides several important benefits for Claude Code users:
-
Customization Control: Gives users fine-grained control over the AI models powering their interaction.
-
Cost Optimization: Allows setting different models for different complexity tasks, optimizing for cost and speed.
-
Provider Flexibility: Enables users to choose from multiple AI providers based on preference, cost, or feature needs.
-
Parameter Tuning: Offers advanced users the ability to tune model parameters for optimal performance.
-
Progressive Disclosure: Uses a step-by-step flow that makes configuration accessible to both novice and advanced users.
-
Intuitive Navigation: Implements keyboard navigation with clear indicators for a smooth configuration experience.
The model
command exemplifies Claude Code's approach to giving users control and flexibility while maintaining an accessible interface, keeping advanced configuration options available but not overwhelming.
cost Command
The cost
command provides users with visibility into the cost and duration of their current Claude Code session, helping them monitor their API usage and expenses.
Implementation
The command is implemented in commands/cost.ts
as a simple type: 'local' command that calls a formatting function:
import type { Command } from "../commands";
import { formatTotalCost } from "../cost-tracker";
const cost = {
type: "local",
name: "cost",
description: "Show the total cost and duration of the current session",
isEnabled: true,
isHidden: false,
async call() {
return formatTotalCost();
},
userFacingName() {
return "cost";
},
} satisfies Command;
export default cost;
This command relies on the cost tracking system implemented in cost-tracker.ts
, which maintains a running total of API costs and session duration.
Cost Tracking System
The cost tracking system is implemented in cost-tracker.ts
and consists of several key components:
-
State Management: Maintains a simple singleton state object tracking:
totalCost
: Running total of API costs in USDtotalAPIDuration
: Cumulative time spent waiting for API responsesstartTime
: Timestamp when the session began
-
Cost Accumulation: Provides a function to add costs as they occur:
export function addToTotalCost(cost: number, duration: number): void { STATE.totalCost += cost; STATE.totalAPIDuration += duration; }
-
Reporting: Formats cost information in a human-readable format:
export function formatTotalCost(): string { return chalk.grey( `Total cost: ${formatCost(STATE.totalCost)} Total duration (API): ${formatDuration(STATE.totalAPIDuration)} Total duration (wall): ${formatDuration(getTotalDuration())}` ); }
-
Persistence: Uses a React hook to save session cost data when the process exits:
export function useCostSummary(): void { useEffect(() => { const f = () => { process.stdout.write("\n" + formatTotalCost() + "\n"); // Save last cost and duration to project config const projectConfig = getCurrentProjectConfig(); saveCurrentProjectConfig({ ...projectConfig, lastCost: STATE.totalCost, lastAPIDuration: STATE.totalAPIDuration, lastDuration: getTotalDuration(), lastSessionId: SESSION_ID, }); }; process.on("exit", f); return () => { process.off("exit", f); }; }, []); }
UI Components
The cost tracking system is complemented by two UI components:
-
Cost Component: A simple display component used in the debug panel to show the most recent API call cost:
export function Cost({ costUSD, durationMs, debug, }: Props): React.ReactNode { if (!debug) { return null; } const durationInSeconds = (durationMs / 1000).toFixed(1); return ( <Box flexDirection="column" minWidth={23} width={23}> <Text dimColor> Cost: ${costUSD.toFixed(4)} ({durationInSeconds}s) </Text> </Box> ); }
-
CostThresholdDialog: A warning dialog shown when users exceed a certain cost threshold:
export function CostThresholdDialog({ onDone }: Props): React.ReactNode { // Handle Ctrl+C, Ctrl+D and Esc useInput((input, key) => { if ((key.ctrl && (input === "c" || input === "d")) || key.escape) { onDone(); } }); return ( <Box flexDirection="column" borderStyle="round" padding={1} borderColor={getTheme().secondaryBorder} > <Box marginBottom={1} flexDirection="column"> <Text bold>You've spent $5 on the Anthropic API this session.</Text> <Text>Learn more about how to monitor your spending:</Text> <Link url="https://docs.anthropic.com/s/claude-code-cost" /> </Box> <Box> <Select options={[ { value: "ok", label: "Got it, thanks!", }, ]} onChange={onDone} /> </Box> </Box> ); }
Technical Implementation Notes
The cost tracking system demonstrates several design considerations:
-
Singleton State: Uses a single state object with a clear comment warning against adding more state.
-
Persistence Across Sessions: Saves cost data to the project configuration, allowing for tracking across sessions.
-
Formatting Flexibility: Uses different decimal precision based on the cost amount (4 decimal places for small amounts, 2 for larger ones).
-
Multiple Time Metrics: Tracks both wall clock time and API request time separately.
-
Environment-Aware Testing: Includes a reset function that's only available in test environments.
-
Exit Hooks: Uses process exit hooks to ensure cost data is saved and displayed even if the application exits unexpectedly.
User Experience Considerations
The cost tracking system addresses several user needs:
-
Transparency: Provides clear visibility into API usage costs.
-
Usage Monitoring: Helps users track and manage their API spending.
-
Efficiency Insights: Shows both total runtime and API time, helping identify bottlenecks.
-
Threshold Warnings: Alerts users when they've spent significant amounts.
-
Documentation Links: Provides resources for learning more about cost management.
The /cost
command and associated systems represent Claude Code's approach to transparent cost management, giving users control over their API usage while maintaining a simple, unobtrusive interface.
onboarding Command
The onboarding
command provides a guided first-run experience for new users, helping them configure Claude Code to their preferences and introducing them to the tool's capabilities.
Implementation
The command is implemented in commands/onboarding.tsx
as a type: 'local-jsx' command that renders a React component:
import * as React from "react";
import type { Command } from "../commands";
import { Onboarding } from "../components/Onboarding";
import { clearTerminal } from "../utils/terminal";
import { getGlobalConfig, saveGlobalConfig } from "../utils/config";
import { clearConversation } from "./clear";
export default {
type: "local-jsx",
name: "onboarding",
description: "[ANT-ONLY] Run through the onboarding flow",
isEnabled: true,
isHidden: false,
async call(onDone, context) {
await clearTerminal();
const config = getGlobalConfig();
saveGlobalConfig({
...config,
theme: "dark",
});
return (
<Onboarding
onDone={async () => {
clearConversation(context);
onDone();
}}
/>
);
},
userFacingName() {
return "onboarding";
},
} satisfies Command;
The command delegates to the Onboarding
component in components/Onboarding.tsx
, which handles the multi-step onboarding flow.
Functionality
The onboarding
command implements a comprehensive first-run experience:
-
Multi-Step Flow:
- Walks users through a series of configuration steps with a smooth, guided experience
- Includes theme selection, usage guidance, and model selection
- Uses a stack-based navigation system for intuitive flow between steps
-
Theme Configuration:
- Allows users to choose between light and dark themes
- Includes colorblind-friendly theme options for accessibility
- Provides a live preview of the selected theme using a code diff example
-
Usage Guidelines:
- Introduces users to effective ways of using Claude Code
- Explains how to provide clear context and work with the tool
- Sets appropriate expectations for the tool's capabilities
-
Model Selection:
- Guides users through configuring AI provider and model settings
- Uses the
ModelSelector
component for a consistent model selection experience - Allows configuration of both small and large models for different tasks
-
Configuration Persistence:
- Saves user preferences to the global configuration
- Marks onboarding as complete to prevent repeat runs
- Clears the conversation after onboarding to provide a clean start
Technical Implementation Notes
The onboarding
command demonstrates several sophisticated patterns:
-
Screen Navigation Stack: Implements a stack-based navigation system for multi-step flow:
const [screenStack, setScreenStack] = useState< Array< | "modelType" | "provider" | "apiKey" | "model" | "modelParams" | "confirmation" > >(["modelType"]); // Current screen is always the last item in the stack const currentScreen = screenStack[screenStack.length - 1]; // Function to navigate to a new screen const navigateTo = (screen) => { setScreenStack((prev) => [...prev, screen]); }; // Function to go back to the previous screen const goBack = () => { if (screenStack.length > 1) { setScreenStack((prev) => prev.slice(0, -1)); } else { onDone(); } };
-
Progressive Disclosure: Presents information in digestible chunks across multiple steps.
-
Terminal UI Adaptation: Uses Ink components optimized for terminal rendering:
<Box flexDirection="column" gap={1} paddingLeft={1}> <Text bold>Using {PRODUCT_NAME} effectively:</Text> <Box flexDirection="column" width={70}> <OrderedList> <OrderedList.Item> <Text> Start in your project directory <Newline /> <Text color={theme.secondaryText}> Files are automatically added to context when needed. </Text> <Newline /> </Text> </OrderedList.Item> {/* Additional list items */} </OrderedList> </Box> <PressEnterToContinue /> </Box>
-
Interactive Components: Uses custom select components for theme selection with previews:
<Select options={[ { label: "Light text", value: "dark" }, { label: "Dark text", value: "light" }, { label: "Light text (colorblind-friendly)", value: "dark-daltonized", }, { label: "Dark text (colorblind-friendly)", value: "light-daltonized", }, ]} onFocus={handleThemePreview} onChange={handleThemeSelection} />
-
Exit Handling: Implements
useExitOnCtrlCD
to provide users with a clear way to exit the flow:const exitState = useExitOnCtrlCD(() => process.exit(0));
-
Conditional Rendering: Uses state to conditionally show different screens:
// If we're showing the model selector screen, render it directly if (showModelSelector) { return <ModelSelector onDone={handleModelSelectionDone} />; }
User Experience Benefits
The onboarding
command addresses several key needs for new users:
-
Guided Setup: Provides a structured introduction to Claude Code rather than dropping users into a blank interface.
-
Preference Customization: Allows users to set their preferences immediately, increasing comfort with the tool.
-
Learning Opportunity: Teaches best practices for using the tool effectively from the start.
-
Accessibility Awareness: Explicitly offers colorblind-friendly themes, demonstrating attention to accessibility.
-
Progressive Complexity: Introduces features gradually, avoiding overwhelming new users.
The onboarding
command exemplifies Claude Code's attention to user experience, ensuring new users can quickly set up the tool according to their preferences and learn how to use it effectively from the beginning.
pr_comments Command
The pr_comments
command provides a specialized interface for retrieving and displaying GitHub pull request comments, helping users review feedback on their code without leaving the terminal.
Implementation
The command is implemented in commands/pr_comments.ts
as a type: 'prompt' command that formulates a specialized request to Claude:
import { Command } from "../commands";
export default {
type: "prompt",
name: "pr-comments",
description: "Get comments from a GitHub pull request",
progressMessage: "fetching PR comments",
isEnabled: true,
isHidden: false,
userFacingName() {
return "pr-comments";
},
async getPromptForCommand(args: string) {
return [
{
role: "user",
content: [
{
type: "text",
text: `You are an AI assistant integrated into a git-based version control system. Your task is to fetch and display comments from a GitHub pull request.
Follow these steps:
1. Use \`gh pr view --json number,headRepository\` to get the PR number and repository info
2. Use \`gh api /repos/{owner}/{repo}/issues/{number}/comments\` to get PR-level comments
3. Use \`gh api /repos/{owner}/{repo}/pulls/{number}/comments\` to get review comments. Pay particular attention to the following fields: \`body\`, \`diff_hunk\`, \`path\`, \`line\`, etc. If the comment references some code, consider fetching it using eg \`gh api /repos/{owner}/{repo}/contents/{path}?ref={branch} | jq .content -r | base64 -d\`
4. Parse and format all comments in a readable way
5. Return ONLY the formatted comments, with no additional text
Format the comments as:
## Comments
[For each comment thread:]
- @author file.ts#line:
\`\`\`diff
[diff_hunk from the API response]
\`\`\`
> quoted comment text
[any replies indented]
If there are no comments, return "No comments found."
Remember:
1. Only show the actual comments, no explanatory text
2. Include both PR-level and code review comments
3. Preserve the threading/nesting of comment replies
4. Show the file and line number context for code review comments
5. Use jq to parse the JSON responses from the GitHub API
${args ? "Additional user input: " + args : ""}
`,
},
],
},
];
},
} satisfies Command;
Unlike commands that directly render UI components, the pr_comments
command is a 'prompt' type command that formulates a specific request to Claude, instructing it to perform a complex sequence of operations using the GitHub CLI and API.
Functionality
The pr_comments
command provides several key capabilities:
-
GitHub Integration:
- Uses the GitHub CLI (
gh
) to interact with GitHub's API - Retrieves both PR-level comments (issue comments) and review comments (inline code comments)
- Handles authentication and API access through the existing GitHub CLI configuration
- Uses the GitHub CLI (
-
Comment Retrieval:
- Fetches PR metadata to determine repository and PR information
- Makes API calls to retrieve different types of comments
- Handles pagination and JSON parsing using
jq
utility
-
Context Preservation:
- Retrieves code context for review comments using the
diff_hunk
field - Shows file paths and line numbers for specific comments
- Preserves the hierarchical structure of comment threads and replies
- Retrieves code context for review comments using the
-
Formatted Output:
- Creates a well-structured, readable display of comments
- Uses Markdown formatting for readability
- Shows comments in a hierarchical, threaded view
-
Progress Indication:
- Shows a progress message ("fetching PR comments") while the operation is in progress
- Provides clear indication when no comments are found
Technical Implementation Notes
The pr_comments
command demonstrates several sophisticated approaches:
-
Prompt-Based Implementation: Unlike UI commands, this command uses Claude itself to execute a complex sequence of operations through a carefully crafted prompt.
-
GitHub CLI Utilization: Leverages the GitHub CLI's capabilities to interact with GitHub's API, taking advantage of existing authentication and configuration.
-
API Interaction Patterns: Provides a detailed workflow for accessing and processing data from different GitHub API endpoints:
gh api /repos/{owner}/{repo}/issues/{number}/comments gh api /repos/{owner}/{repo}/pulls/{number}/comments
-
JSON Processing with JQ: Uses the
jq
command-line JSON processor for parsing complex API responses. -
Complex Data Formatting: Provides explicit formatting instructions to ensure consistent, readable output:
- @author file.ts#line: ```diff [diff_hunk from the API response]
quoted comment text
[any replies indented]
-
Arguments Passthrough: Allows users to provide additional arguments that are appended to the prompt, enabling refinement of the command's behavior.
User Experience Benefits
The pr_comments
command addresses several important needs for developers:
-
Context Switching Reduction: Allows reviewing PR comments without leaving the terminal or switching to a browser.
-
Comment Aggregation: Brings together comments from different locations (PR-level and code-specific) in a single view.
-
Reading Optimization: Formats comments with proper context, improving readability compared to raw API responses.
-
Workflow Integration: Enables PR review activities to be part of the normal development workflow in the terminal.
-
GitHub Integration: Takes advantage of existing GitHub CLI authentication and configuration.
The pr_comments
command exemplifies how Claude Code can leverage Claude's capabilities to implement complex workflows that would otherwise require significant custom code. By using a prompt-based approach, it achieves powerful GitHub integration with minimal implementation complexity.
release-notes Command
The release-notes
command provides users with a simple way to view the changes and new features introduced in each version of Claude Code, helping them stay informed about updates.
Implementation
The command is implemented in commands/release-notes.ts
as a type: 'local' command that formats and displays release notes from a constant:
import { MACRO } from "../constants/macros.js";
import type { Command } from "../commands";
import { RELEASE_NOTES } from "../constants/releaseNotes";
const releaseNotes: Command = {
description: "Show release notes for the current or specified version",
isEnabled: false,
isHidden: false,
name: "release-notes",
userFacingName() {
return "release-notes";
},
type: "local",
async call(args) {
const currentVersion = MACRO.VERSION;
// If a specific version is requested, show that version's notes
const requestedVersion = args ? args.trim() : currentVersion;
// Get the requested version's notes
const notes = RELEASE_NOTES[requestedVersion];
if (!notes || notes.length === 0) {
return `No release notes available for version ${requestedVersion}.`;
}
const header = `Release notes for version ${requestedVersion}:`;
const formattedNotes = notes.map((note) => `• ${note}`).join("\n");
return `${header}\n\n${formattedNotes}`;
},
};
export default releaseNotes;
This command demonstrates a simple but effective approach to displaying versioned information, using a constant defined in constants/releaseNotes.ts
as the data source.
Functionality
The release-notes
command provides a straightforward information display:
-
Version Selection:
- Defaults to showing notes for the current version
- Allows explicit version selection through command arguments
- Handles cases where notes are unavailable for a version
-
Note Formatting:
- Displays a clear header indicating the version
- Formats individual notes as bullet points
- Presents notes in a readable, consistent format
-
No Dependencies:
- Doesn't require external API calls or complex processing
- Works entirely with data embedded in the application
-
Error Handling:
- Provides a friendly message when notes aren't available
- Gracefully handles empty or missing note arrays
Technical Implementation Notes
While simpler than many other commands, the release-notes
command demonstrates several effective patterns:
-
Constant-Based Data Store: Uses a predefined constant for storing release notes data:
// Example from constants/releaseNotes.ts export const RELEASE_NOTES: Record<string, string[]> = { "0.0.22": [ "Added proxy configuration support via --proxy flag or HTTP_PROXY environment variable", "Improved error handling for API connectivity issues", "Fixed issue with terminal output formatting in certain environments", ], "0.0.21": [ "Enhanced model selection interface with provider-specific options", "Improved documentation and help text for common commands", "Fixed bug with conversation state persistence", ], };
-
Default Value Pattern: Uses the current version as a default if no specific version is requested:
const currentVersion = MACRO.VERSION; const requestedVersion = args ? args.trim() : currentVersion;
-
Array Transformation: Uses map and join for clean formatting of bullet points:
const formattedNotes = notes.map((note) => `• ${note}`).join("\n");
-
Null-Safe Access: Checks for undefined or empty notes before attempting to display them:
if (!notes || notes.length === 0) { return `No release notes available for version ${requestedVersion}.`; }
-
Command Availability Control: The command is marked as disabled with
isEnabled: false
, suggesting it may be under development or available only in certain builds.
User Experience Benefits
Despite its simplicity, the release-notes
command provides several valuable benefits:
-
Update Awareness: Helps users understand what has changed between versions.
-
Feature Discovery: Introduces users to new capabilities they might not otherwise notice.
-
Version Verification: Allows users to confirm which version they're currently using.
-
Historical Context: Provides access to past release information for reference.
-
Simplified Format: Presents notes in a clean, readable format without requiring browser access.
The release-notes
command exemplifies how even simple commands can provide valuable functionality through clear organization and presentation of information. It serves as part of Claude Code's approach to transparency and user communication.
resume Command
The resume
command allows users to continue previous conversations with Claude, providing a way to revisit and extend past interactions without losing context.
Implementation
The command is implemented in commands/resume.tsx
as a type: 'local-jsx' command that renders a React component for selecting and resuming past conversations:
import * as React from "react";
import type { Command } from "../commands";
import { ResumeConversation } from "../screens/ResumeConversation";
import { render } from "ink";
import { CACHE_PATHS, loadLogList } from "../utils/log";
export default {
type: "local-jsx",
name: "resume",
description: "[ANT-ONLY] Resume a previous conversation",
isEnabled: true,
isHidden: false,
userFacingName() {
return "resume";
},
async call(onDone, { options: { commands, tools, verbose } }) {
const logs = await loadLogList(CACHE_PATHS.messages());
render(
<ResumeConversation
commands={commands}
context={{ unmount: onDone }}
logs={logs}
tools={tools}
verbose={verbose}
/>
);
// This return is here for type only
return null;
},
} satisfies Command;
The command delegates to the ResumeConversation
component in screens/ResumeConversation.tsx
, passing the list of previous conversations and necessary context.
Functionality
The resume
command implements a sophisticated conversation history management system:
-
Conversation Retrieval:
- Loads previously saved conversation logs from the cache directory
- Uses the
loadLogList
utility to parse and organize log files - Presents a navigable list of past conversations
-
Context Restoration:
- Allows users to select a specific past conversation to resume
- Loads the complete message history for the selected conversation
- Reinstates the context of the previous interaction
-
Selection Interface:
- Provides a visual interface for browsing conversation history
- Shows metadata about each conversation (date, duration, topic)
- Enables keyboard navigation through the history list
-
Seamless Transition:
- Integrates resumed conversations into the current CLI session
- Passes necessary tooling and command context to the resumed conversation
- Maintains configuration settings across resumed sessions
Technical Implementation Notes
The resume
command demonstrates several sophisticated implementation patterns:
-
Custom Rendering Approach: Unlike most commands that return a React element, this command uses a direct render call:
render( <ResumeConversation commands={commands} context={{ unmount: onDone }} logs={logs} tools={tools} verbose={verbose} /> );
This approach gives it more direct control over the rendering lifecycle.
-
Log Loading and Parsing: Implements careful log handling with the loadLogList utility:
// From utils/log.ts export async function loadLogList(directory: string): Promise<LogFile[]> { // Reads log directory // Parses log files // Extracts metadata // Sorts by recency // Returns formatted log list }
-
Context Passing: Passes the full command and tool context to ensure the resumed conversation has access to all capabilities:
<ResumeConversation commands={commands} context={{ unmount: onDone }} logs={logs} tools={tools} verbose={verbose} />
-
Path Management: Uses a centralized path management system for log files:
// From utils/log.ts export const CACHE_PATHS = { messages: () => path.join(getConfigRoot(), "messages"), // Other path definitions... };
-
ANT-ONLY Flag: Uses the
[ANT-ONLY]
prefix in the description, indicating it's a feature specific to internal Anthropic usage and potentially not available in all distributions.
User Experience Benefits
The resume
command addresses several important user needs:
-
Conversation Continuity: Allows users to pick up where they left off in previous sessions.
-
Context Preservation: Maintains the full context of previous interactions, reducing repetition.
-
Work Session Management: Enables users to organize work across multiple sessions.
-
History Access: Provides a browsable interface to previous conversations.
-
Interrupted Work Recovery: Helps recover from interrupted work sessions or system crashes.
The resume
command exemplifies Claude Code's approach to persistent user experience, ensuring that valuable conversation context isn't lost between sessions. This is particularly important for complex coding tasks that may span multiple work sessions.
review Command
The review
command provides a specialized workflow for reviewing GitHub pull requests, leveraging Claude's code analysis capabilities to generate comprehensive code reviews.
Implementation
The command is implemented in commands/review.ts
as a type: 'prompt' command that formulates a specific request to Claude:
import { Command } from "../commands";
import { BashTool } from "../tools/BashTool/BashTool";
export default {
type: "prompt",
name: "review",
description: "Review a pull request",
isEnabled: true,
isHidden: false,
progressMessage: "reviewing pull request",
userFacingName() {
return "review";
},
async getPromptForCommand(args) {
return [
{
role: "user",
content: [
{
type: "text",
text: `
You are an expert code reviewer. Follow these steps:
1. If no PR number is provided in the args, use ${BashTool.name}("gh pr list") to show open PRs
2. If a PR number is provided, use ${BashTool.name}("gh pr view <number>") to get PR details
3. Use ${BashTool.name}("gh pr diff <number>") to get the diff
4. Analyze the changes and provide a thorough code review that includes:
- Overview of what the PR does
- Analysis of code quality and style
- Specific suggestions for improvements
- Any potential issues or risks
Keep your review concise but thorough. Focus on:
- Code correctness
- Following project conventions
- Performance implications
- Test coverage
- Security considerations
Format your review with clear sections and bullet points.
PR number: ${args}
`,
},
],
},
];
},
} satisfies Command;
Like the pr_comments
command, the review
command is a 'prompt' type command that formulates a specific request to Claude, instructing it to perform a complex sequence of operations using the GitHub CLI.
Functionality
The review
command implements a comprehensive PR review workflow:
-
PR Discovery and Selection:
- Lists open pull requests if no PR number is specified
- Retrieves details for a specific PR when a number is provided
- Presents options for users to select which PR to review
-
Code Analysis:
- Fetches the PR diff to understand code changes
- Analyzes code quality, style, and potential issues
- Evaluates changes in the context of the project's conventions
-
Review Generation:
- Creates a structured code review with logical sections
- Highlights potential improvements and issues
- Provides specific, actionable feedback on code changes
-
Focus Areas:
- Analyzes code correctness and logical issues
- Evaluates adherence to project conventions
- Assesses performance implications of changes
- Reviews test coverage of new code
- Identifies potential security considerations
-
Progress Indication:
- Shows a "reviewing pull request" message during analysis
- Provides a clear visual indication that processing is underway
Technical Implementation Notes
The review
command demonstrates several important implementation patterns:
-
Tool Reference in Prompt: Explicitly references the BashTool by name in the prompt to ensure proper tool usage:
use ${BashTool.name}("gh pr list")
This ensures the correct tool is used regardless of how Claude might interpret the instruction.
-
GitHub CLI Integration: Leverages the GitHub CLI's capabilities for PR interaction:
gh pr list - Show open PRs gh pr view <number> - Get PR details gh pr diff <number> - Get the diff
-
Comprehensive Analysis Instructions: Provides Claude with a detailed framework for analysis:
Analyze the changes and provide a thorough code review that includes: - Overview of what the PR does - Analysis of code quality and style - Specific suggestions for improvements - Any potential issues or risks
-
Focus Guidance: Directs Claude's analysis toward specific aspects of code quality:
Focus on: - Code correctness - Following project conventions - Performance implications - Test coverage - Security considerations
-
Formatting Guidance: Ensures consistent output format with clear instructions:
Format your review with clear sections and bullet points.
User Experience Benefits
The review
command provides several valuable benefits for developers:
-
Code Review Automation: Reduces the manual effort required for initial PR reviews.
-
Consistent Review Quality: Ensures all PRs receive a thorough analysis covering key areas.
-
Learning Opportunity: Exposes developers to alternative perspectives on their code.
-
Workflow Integration: Fits seamlessly into GitHub-based development workflows.
-
Time Efficiency: Quickly generates comprehensive reviews that serve as a starting point for human reviewers.
The review
command exemplifies how Claude Code can leverage Claude's code analysis capabilities to add value to existing development workflows. It transforms Claude from a conversational assistant into an active participant in the code review process.
terminalSetup Command
The terminalSetup
command enhances the user experience by configuring terminal-specific keyboard shortcuts, specifically implementing Shift+Enter for newlines in terminals like iTerm2 and VS Code.
Implementation
The command is implemented in commands/terminalSetup.ts
as a type: 'local' command that configures terminal-specific settings:
import { Command } from "../commands";
import { EOL, platform, homedir } from "os";
import { execFileNoThrow } from "../utils/execFileNoThrow";
import chalk from "chalk";
import { getTheme } from "../utils/theme";
import { env } from "../utils/env";
import { getGlobalConfig, saveGlobalConfig } from "../utils/config";
import { markProjectOnboardingComplete } from "../ProjectOnboarding";
import { readFileSync, writeFileSync } from "fs";
import { join } from "path";
import { safeParseJSON } from "../utils/json";
import { logError } from "../utils/log";
const terminalSetup: Command = {
type: "local",
name: "terminal-setup",
userFacingName() {
return "terminal-setup";
},
description:
"Install Shift+Enter key binding for newlines (iTerm2 and VSCode only)",
isEnabled:
(platform() === "darwin" && env.terminal === "iTerm.app") ||
env.terminal === "vscode",
isHidden: false,
async call() {
let result = "";
switch (env.terminal) {
case "iTerm.app":
result = await installBindingsForITerm2();
break;
case "vscode":
result = installBindingsForVSCodeTerminal();
break;
}
// Update global config to indicate Shift+Enter key binding is installed
const config = getGlobalConfig();
config.shiftEnterKeyBindingInstalled = true;
saveGlobalConfig(config);
// Mark onboarding as complete
markProjectOnboardingComplete();
return result;
},
};
export function isShiftEnterKeyBindingInstalled(): boolean {
return getGlobalConfig().shiftEnterKeyBindingInstalled === true;
}
export default terminalSetup;
The command includes specialized implementation functions for different terminal types, with unique approaches for iTerm2 and VS Code.
Functionality
The terminalSetup
command provides a targeted terminal enhancement:
-
Terminal Detection:
- Determines the current terminal environment automatically
- Supports iTerm2 on macOS and VS Code's integrated terminal
- Only enables the command when in compatible terminals
-
Keyboard Shortcut Configuration:
- Configures Shift+Enter to insert a newline without submitting input
- Uses terminal-specific mechanisms for each supported terminal
- For iTerm2, uses the defaults command to modify keybindings
- For VS Code, modifies the keybindings.json configuration file
-
Configuration Status Tracking:
- Updates global configuration to track installation state
- Provides a utility function to check if bindings are installed
- Avoids redundant installations by checking state
-
Onboarding Integration:
- Marks project onboarding as complete after setup
- Integrates with the broader onboarding workflow
- Provides a smooth setup experience for new users
Technical Implementation Notes
The terminalSetup
command demonstrates several sophisticated technical approaches:
-
Platform-Specific Implementations: Implements different strategies based on the terminal type:
switch (env.terminal) { case "iTerm.app": result = await installBindingsForITerm2(); break; case "vscode": result = installBindingsForVSCodeTerminal(); break; }
-
macOS Defaults System: For iTerm2, uses the macOS defaults system to modify key bindings:
async function installBindingsForITerm2(): Promise<string> { const { code } = await execFileNoThrow("defaults", [ "write", "com.googlecode.iterm2", "GlobalKeyMap", "-dict-add", "0xd-0x20000-0x24", `<dict> <key>Text</key> <string>\\n</string> <key>Action</key> <integer>12</integer> <key>Version</key> <integer>1</integer> <key>Keycode</key> <integer>13</integer> <key>Modifiers</key> <integer>131072</integer> </dict>`, ]); // Error handling and success message... }
-
VS Code Configuration File Handling: For VS Code, directly modifies the keybindings.json file:
function installBindingsForVSCodeTerminal(): string { const vscodeKeybindingsPath = join( homedir(), platform() === "win32" ? join("AppData", "Roaming", "Code", "User") : platform() === "darwin" ? join("Library", "Application Support", "Code", "User") : join(".config", "Code", "User"), "keybindings.json" ); try { const content = readFileSync(vscodeKeybindingsPath, "utf-8"); const keybindings: VSCodeKeybinding[] = (safeParseJSON(content) as VSCodeKeybinding[]) ?? []; // Check for existing bindings... // Add new binding... // Write updated file... } catch (e) { // Error handling... } }
-
Cross-Platform Path Handling: Uses the path.join utility along with platform detection to handle OS-specific paths:
const vscodeKeybindingsPath = join( homedir(), platform() === "win32" ? join("AppData", "Roaming", "Code", "User") : platform() === "darwin" ? join("Library", "Application Support", "Code", "User") : join(".config", "Code", "User"), "keybindings.json" );
-
Safe JSON Parsing: Uses a utility function for safe JSON parsing to handle potential errors:
const keybindings: VSCodeKeybinding[] = (safeParseJSON(content) as VSCodeKeybinding[]) ?? [];
User Experience Benefits
The terminalSetup
command addresses a specific pain point in terminal interaction:
-
Improved Input Experience: Allows multi-line input with Shift+Enter without submitting prematurely.
-
Workflow Enhancement: Makes it easier to compose complex prompts or code snippets.
-
Consistency Across Environments: Provides similar behavior in different terminal environments.
-
Seamless Integration: Configures the terminal without requiring users to understand terminal-specific configuration files.
-
Visual Feedback: Provides clear success messages when binding installation completes.
The terminalSetup
command exemplifies Claude Code's attention to detail in the user experience, addressing a specific friction point in terminal interaction to create a more seamless interaction pattern for complex inputs.