This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
terminal-aichat is a CLI tool for AI/LLM chat in terminal:
- Written in Rust (2024 edition), lightweight (~6.5MB binary), very fast
- Multi-platform: Windows, Linux, macOS
- Uses OpenAI-compatible
/v1/chat/completionAPI - Extremely simple and easy to use
cargo build # Development build
cargo build --release # Release build (optimized)
cargo build --profile dist # Dist profile (optimized with thin LTO)cargo test # Run all tests
cargo test <test_name> # Run specific test
cargo test --verbose # Run tests with verbose outputcargo clippy # Run linter
cargo clippy --fix --bin "aichat" # Auto-fix suggestionscargo run -- [args] # Run development binary
cargo run -- --help # Show helpsrc/
├── main.rs # Entry point
├── chat.rs # API communication with OpenAI
├── cli/ # CLI parsing & command handling
│ ├── cli.rs # Main command handler
│ ├── structs.rs # clap argument definitions
│ ├── interactive.rs # Interactive input mode
│ └── response_render.rs # Response rendering with typewriter effect
├── config/ # Configuration management
│ ├── structs.rs # Serialization/deserialization models
│ ├── manager.rs # File I/O operations
│ ├── builder.rs # ConfigBuilder for fluent API
│ ├── resolver.rs # Config merging logic
│ └── display.rs # Pretty-printing for config listing
└── utils/ # Utility functions
├── logger.rs # Logging system
└── string.rs # String extensions and masking
-
Configuration System:
ConfigBuilderpattern for fluent config creation- Config resolution order: CLI args > file config > defaults
- Cross-platform storage via
dirscrate
-
Command Handling:
- clap with derive attributes for declarative CLI
- Subcommands:
set,use,delete,list - Pipe input detection and interactive mode support
-
API Communication:
async-openaicrate for OpenAI-compatible endpoints- Streaming and non-streaming response handling
- API key override via
OPENAI_API_KEYenv var
-
Response Rendering:
ResponseRendererwith typewriter effect (30 chars/second)- Status bar with model/prompt info
- Pure mode for clean output
- Linux:
~/.config/terminal-aichat/config.json - macOS:
~/Library/Application Support/terminal-aichat/config.json - Windows:
%APPDATA%\terminal-aichat\config.json
- async-openai: OpenAI API client
- clap: CLI framework with derive
- crossterm: Terminal handling
- tokio: Async runtime (full features)
- serde_json: JSON configuration
- dirs: Cross-platform config directories
{
"models": {
"sample_model_gpt": {
"model_name": "gpt-5-mini",
"base_url": "https://api.openai.com/v1",
"api_key": null,
"temperature": null
}
},
"prompts": {
"sample_prompt": {
"content": "You are a terminal assistant. \nYou are giving help to user in the terminal.\nGive concise responses whenever possible.\nBecause of terminal cannot render markdown, DO NOT contain any markdown syntax(`,```, #, ...) in your response, use plain text only.\n"
}
},
"default-model": "sample_model_gpt",
"default-prompt": "sample_prompt",
"disable-stream": false,
"pure": false,
"verbose": false
}A more complete example with multiple models:
{
"models": {
"openai_gpt4": {
"model_name": "gpt-4o",
"base_url": "https://api.openai.com/v1",
"api_key": "sk-...",
"temperature": 0.7
},
"openrouter": {
"model_name": "openai/gpt-oss-20b:free",
"base_url": "https://openrouter.ai/api/v1",
"api_key": "sk-or-...",
"temperature": 0.3
}
},
"prompts": {
"sample_prompt": {
"content": "You are a terminal assistant. You are giving help to user in the terminal. Give concise responses whenever possible. Because of terminal cannot render markdown, DO NOT contain any markdown syntax(`,```, #, ...) in your response, use plain text only.\n"
},
"concise": {
"content": "Use plain text, give extremely concise output"
}
},
"default-model": "openai_gpt4",
"default-prompt": "sample_prompt",
"disable-stream": false,
"pure": false,
"verbose": false
}简化配置方式,面向开发者,移除复杂的 CLI 配置命令,改为直接编辑配置文件。
- 本工具面向开发者,不需要复杂的 CLI 来进行配置
- 直接编辑配置文件更简单、更灵活
- 减少代码维护成本
-
CLI 结构改革
- 删除
set、use、delete子命令, 保留list子命令(后续实现: ),保留--model/-m参数(后续实现), - 启用
--config参数,允许手动指定配置文件路径 - 在
-h/--help输出中提示默认配置文件位置 - 更新 CLI 的 about 信息
- 删除
-
配置文件解析改革
- 添加
jsonc依赖库 - 修改配置读取逻辑:先尝试读取
.json,再尝试读取.jsonc - 使用 jsonc 库解析配置文件
- 添加
-
Model 配置结构完全更改
- 重新设计
Config结构体 - 新结构:
providers: { "<provider_key>": { name?: string, baseUrl: string, apiKey: ..., models: { "<model_key>": { name?: string, temperature: ... } } } } - provider 的 name 可以为空,为空时以 key 作为 name
- model 的 name 可以为空,为空时以 key 作为 name
- 更新默认配置生成逻辑
- 保持
prompts配置结构不变 - 保持其他参数(
disable-stream、pure、verbose)不变
- 重新设计
-
配置管理模块重构
- 删除
builder.rs(不再需要 ConfigBuilder) - 删除
resolver.rs(简化配置合并逻辑) - 修改
display.rs以适配新的 list 命令显示逻辑(provider-name: - model-names) - 重构
manager.rs以适应新的配置结构 - 更新
structs.rs定义新的配置结构
- 删除
-
Chat 模块适配
- 更新
chat.rs以适配新的 provider/model 配置结构 - 更新 API 调用逻辑
- 更新
-
CLI 处理模块更新
- 重构
cli/cli.rs删除set/use/delete子命令处理逻辑 - 修改
list子命令实现,显示新的配置结构, 显示简要配置列表:provider-name: - model-names - 更新
cli/structs.rs移除set/use/delete子命令定义 - 实现
--model/-m参数的新逻辑:遍历 providers 的所有模型,直到命中一个 - 保持
interactive.rs和response_render.rs不变
- 重构
-
更新示例配置
- 更新 CLAUDE.md 中的示例配置为新格式
注:
- provider 的
name为null或省略时,使用 key(如"local")作为 name - model 的
name为null或省略时,使用 key(如"llama3.1")作为 name
阶段 1:配置结构重构
- 更新
Cargo.toml添加 jsonc 依赖 - 重写
config/structs.rs定义新结构(provider + models 二级结构,name 可选) - 更新默认配置逻辑
阶段 2:CLI 调整
- 修改
cli/structs.rs移除set/use/delete子命令,保留list子命令 - 启用
--config参数 - 更新 help 信息,提示默认配置文件位置
- 保留
--model/-m参数定义
阶段 3:配置管理重构
- 删除
builder.rs、resolver.rs - 修改
display.rs适配新的 list 命令显示逻辑(provider-name: - model-names) - 重写
manager.rs - 更新配置读取逻辑:先尝试 .json,再尝试 .jsonc
阶段 4:CLI 处理逻辑更新
- 重构
cli/cli.rs删除set/use/delete处理逻辑 - 实现新的
list命令显示逻辑 - 实现
--model/-m参数新逻辑:遍历 providers 所有模型直到命中
阶段 5:Chat 模块适配
- 更新
chat.rs使用新配置结构
阶段 6:清理和测试
- 删除无用代码
- 运行测试
- 更新 CLAUDE.md 示例配置
{ "providers": { "openai": { "name": "OpenAI", "baseUrl": "https://api.openai.com/v1", "apiKey": "sk-...", "models": { "gpt-4o": { "name": "gpt-4o", "temperature": 0.7 }, "gpt-5-mini": { "name": "gpt-5-mini", "temperature": 0.5 } } }, "openrouter": { "name": "OpenRouter", "baseUrl": "https://openrouter.ai/api/v1", "apiKey": "sk-or-...", "models": { "llama-3": { "name": "meta-llama/llama-3-70b-instruct", "temperature": 0.3 } } }, "local": { "name": null, "baseUrl": "http://localhost:11434/v1", "apiKey": null, "models": { "llama3.1": { "name": null, "temperature": 0.8 } } } }, "prompts": { "sample_prompt": { "content": "You are a terminal assistant. You are giving help to user in the terminal. Give concise responses whenever possible. Because of terminal cannot render markdown, DO NOT contain any markdown syntax(`,```, #, ...) in your response, use plain text only.\n" }, "concise": { "content": "Use plain text, give extremely concise output" } }, "default-provider": "openai", "default-model": "gpt-5-mini", "default-prompt": "sample_prompt", "disable-stream": false, "pure": false, "verbose": false }