Claude Code 与新一代终端 AI 编程工具
凌晨 2:13 点,我看着一个终端编码智能体消耗了 1.8 百万个输入 token,只为“修复那个失败的测试”。实际的 bug 只是三行代码中的 schema 不匹配。这个智能体并不笨,只是缺乏恰当的约束。它不断重读仓库、重新运行大范围的测试命令、把巨大的堆栈跟踪粘贴回模型,还要求重写整个文件,而原本只需一个精准的小范围 diff 就能解决问题。
那次事件改变了我使用 CLI 编码智能体的方式。
Claude Code、Aider、Cline 和 OpenCode 这样的工具,并不只是带有一个 git diff 按钮的聊天机器人。它们是由 API 驱动的控制循环,围绕你的 shell、编辑器、文件系统,有时还包括浏览器运行。它们可以极大地提高生产力,尤其是搭配 Claude Opus 4.8、Sonnet 4.6、GPT-5.5、Gemini 3 等强大模型,以及 Fable 5 等长上下文系统时。但它们也可能悄无声息地消耗大量 token,其速度会让习惯了单轮 API 调用的团队感到意外。
本文侧重实践:终端编码智能体究竟在做什么、如何使用模型 API、为什么智能体循环会改变 token 的成本结构,以及我如何配置它们,让长时间的会话始终有用,而不是变成昂贵的表演。
CLI 编码智能体究竟是什么
终端编码智能体通常由五个部分组合而成:
- 与前沿模型或开放模型交互的聊天循环
- 仓库索引器或文件发现层
- 用于执行 shell 命令和编辑文件的工具执行层
- 补丁应用机制
- 用于保存对话历史和会话状态的持久化层
它与自动补全的关键区别在于自主行动能力。自动补全预测光标位置的代码。智能体则可以决定查看文件、运行测试、修改代码、检查失败原因,并持续迭代。
典型的循环如下:
User task
↓
Agent builds prompt from instructions + repo context + prior messages
↓
Model proposes actions: read file, edit file, run command
↓
CLI executes allowed actions
↓
Results are added back into context
↓
Model plans next step
↓
Repeat until done or stopped
这个循环让这些工具显得强大,也让它们的成本和延迟表现不同于普通的“问一个问题、得到一个答案”的 API 使用方式。
在实践中,大多数意外成本都来自反馈路径:命令输出、文件内容、先前的消息和 diff 被反复纳入后续轮次。
Claude Code、Aider、Cline 和 OpenCode:同一模式的不同形态
这些工具的交互方式各不相同,但核心工程模式类似。
| 工具 | 主要交互界面 | 典型优势 | 常见成本风险 |
|---|---|---|---|
| Claude Code | 终端原生智能体 | 紧密衔接 shell 与仓库的工作流,强大的规划与编辑循环 | 长时间自主运行的会话不断积累上下文 |
| Aider | 具备 Git 感知能力的 CLI 结对编程工具 | 以 diff 为中心的编辑,明确指定目标文件 | 向上下文添加过多文件 |
| Cline | 以编辑器为中心的智能体 | 与 VS Code 集成,工具使用过程可见 | 大量终端或浏览器输出进入上下文 |
| OpenCode | 终端与编辑器中的智能体工作流 | 灵活选择模型,掌控本地工作流 | 提供商配置错误或大范围仓库扫描 |
重要的区别并不是“哪个最聪明”,而是工具发送多少上下文、如何选择文件、如何总结历史,以及你对 shell 执行拥有多大的控制权。
例如,当你有意识地添加相关文件时,Aider 往往表现不错。Claude Code 更具自主行动能力,用起来像是一位在仓库中开展工作的资深工程师,但这种自主性也意味着你应当审慎设置权限和任务范围。Cline 在编辑器内使用很方便,尤其适合希望观察操作过程的场景,但编辑器带来的便利也容易让你批准过多成本高昂的步骤。
OpenCode 风格的工作流很适合希望灵活选择提供商的团队:使用 Claude 处理复杂的架构工作,使用 GPT 进行实现,使用 Gemini 检查大规模上下文,或者使用 Qwen、DeepSeek、Kimi、MiniMax 和 Llama 等开放模型,以较低成本进行本地或自托管处理。
这些智能体如何使用 API
一个“修复这个 bug”的请求可能会变成数十次 API 调用。
智能体单个步骤的简化请求体如下:
{
"model": "claude-sonnet-4.6",
"messages": [
{
"role": "system",
"content": "You are a coding agent. Follow repo instructions. Use tools safely."
},
{
"role": "user",
"content": "Fix the failing invoice total test."
},
{
"role": "assistant",
"content": "I will inspect the test and related invoice code."
},
{
"role": "tool",
"name": "read_file",
"content": "tests/test_invoice_totals.py contents..."
}
],
"tools": [
{ "name": "read_file" },
{ "name": "apply_patch" },
{ "name": "run_shell" }
]
}
实际实现各不相同,但模式是一致的:
- CLI 收集上下文。
- 模型决定下一步操作。
- CLI 执行该操作。
- 结果反馈给模型。
- 模型继续处理。
工具通常通过两种方式提供给模型。
基于文本的工具协议
有些智能体要求模型输出结构化文本:
RUN: pytest tests/test_invoice_totals.py -q
CLI 解析并执行这些文本。这种方式简单且便于移植,但比较脆弱。如果模型生成的命令格式不规范,执行框架就需要防护机制。
原生函数调用
另一些智能体使用模型 API 的工具调用或函数调用功能。模型返回结构化的工具调用:
{
"tool_name": "run_shell",
"arguments": {
"command": "pytest tests/test_invoice_totals.py -q",
"timeout_seconds": 60
}
}
这种方式更容易验证。智能体可以拒绝符合危险模式的命令、要求网络访问获得批准,或将写入操作限制在工作区内。
在这两种设计中,成本高的都不是 shell 命令本身,而是围绕 shell 命令不断增长的提示词。
为什么智能体循环会改变 token 成本结构
普通 API 集成可能发送 2,000 个输入 token,并接收 500 个输出 token。智能体编程会话可能会这样运行:
| 步骤 | 发生的操作 | 输入 token 特征 | 输出 token 特征 |
|---|---|---|---|
| 1 | 用户请求修复 | 少 | 计划 |
| 2 | 智能体读取文件 | 中等 | 工具请求 |
| 3 | 智能体编辑代码 | 中等偏多 | 补丁 |
| 4 | 测试失败 | 若包含完整日志,则较多 | 诊断 |
| 5 | 智能体读取更多文件 | 因历史记录而进一步增加 | 工具请求 |
| 6 | 智能体重试 | 再次增加 | 补丁 |
| 7 | 运行完整测试时,其他地方出现失败 | 若原样粘贴输出,则非常多 | 总结/问题分诊 |
容易忽略的一点是:输入 token 往往占大头。每轮循环都可能重新发送系统指令、对话历史、选定文件、工具输出和摘要。即使使用缓存或上下文压缩,长时间的自主会话也可能成本高昂,因为模型需要掌握足够的状态信息,才能避免盲目操作。
常见的 token 用量放大因素有四个:
- 完整文件上下文:只有两个函数与任务相关,却发送了 900 行的文件。
- 冗长的测试输出:包含依赖项警告、进度条和无关的失败信息。
- 反复扫描代码仓库:大范围运行
find,tree,或rg并将输出重新注入上下文。 - 不设上限的对话历史:保留每次失败的尝试,而不是总结已做出的决定。
混乱的会话中实际发生的并不是“智能体思考得更深入”。它往往只是看到了更多过时的上下文。如果相关信息被淹没,更多 token 反而会让模型更慢、更不准确。
思维模型:按循环而非按提示词制定预算
估算费用时,我会以循环为单位来考虑。
一个范围明确的小任务可能是:
8 turns × 12k input tokens average = 96k input tokens
8 turns × 1.5k output tokens average = 12k output tokens
一个不断偏离方向的任务可能是:
35 turns × 55k input tokens average = 1.9M input tokens
35 turns × 3k output tokens average = 105k output tokens
同样的用户提示词,成本却截然不同。
无需知道确切价格,也能看出问题的基本形态。智能体会话的规模随以下因素增长:
total cost ≈ Σ(input_tokens_per_step × input_price)
+ Σ(output_tokens_per_step × output_price)
+ tool/runtime overhead
输出 token 是可见的,因为你能看到智能体在输入。输入 token 则是隐藏的,因为它们由 CLI 组装。正是在这个看不见的环节,控制预算尤为重要。
为智能体任务选择模型
我很少用一个模型处理所有任务。
对于终端智能体,模型选择应与任务阶段相匹配:
| 阶段 | 最适合的模型类型 | 原因 |
|---|---|---|
| 代码仓库初步调查 | 长上下文模型,或价格更低且能力足够的模型 | 需要广泛阅读,无需完美编辑 |
| 架构决策 | 推理能力强的模型 | 需要判断取舍 |
| 生成补丁 | 编程能力强的模型 | 需要精确的差异内容 |
| 测试失败分诊 | 速度快的中档模型 | 通常是模式匹配 |
| 机械性重构 | 配有防护机制的低成本模型或开放模型 | 重复且可验证的工作 |
一种实用的配置方式是:使用 Sonnet 级别的模型处理大多数编码任务,使用 Opus/GPT-5.5 级别的模型处理复杂调试或设计,使用 Gemini/Fable 类型的长上下文模型进行大规模检查,并使用开放模型在本地进行类似代码检查的重构。具体名称会变化,但这种模式依然适用。
一个常见错误是在整个循环中都使用最昂贵的模型。这样一来,昂贵的模型就会耗费高价 token 来读取 node_modules周边的无关信息、测试警告和生成文件。把最强的模型留给真正需要它的决策。
关键配置建议
最佳配置不是“最大程度的自主性”,而是“快速反馈与有限权限”。
1. 忽略生成文件和第三方依赖文件
每个编程智能体都应该有一份忽略列表。先从你在搜索和审查时排除的那些内容开始:
node_modules/
dist/
build/
coverage/
.venv/
__pycache__/
target/
vendor/
*.lock
*.min.js
*.map
如果任务涉及依赖解析,我通常不会全局排除锁文件,但会将其排除在默认上下文之外。需要时,可以显式将锁文件加入上下文。
2. 使用范围明确的测试命令
不要让智能体默认在每次迭代中运行整个测试套件。为它提供一套逐级扩大的命令:
# First loop: fastest relevant test
pytest tests/billing/test_invoice_totals.py -q
# Second loop: nearby package
pytest tests/billing -q
# Final confidence check
pytest -q
对于 JavaScript 或 TypeScript:
pnpm test invoice-total.test.ts -- --runInBand
pnpm lint src/billing
pnpm test
重点不只是运行时间。输出越少,下一轮循环的提示词也越小。
3. 限制命令输出
如果你的智能体支持输出限制,就启用它。如果不支持,就自行封装命令:
pytest tests/billing -q 2>&1 | tail -120
对于输出繁杂的构建,也可以这样做:
pnpm test 2>&1 | grep -E "FAIL|Error|Expected|Received|at " | head -200
请注意:过滤可能隐藏有用的上下文。我会在首次失败之后使用这种方式,而不是之前。先了解失败的整体情况,再限制重复运行时的输出。
4. 要求提供差异,而不是重写
对于大文件,请明确告诉智能体:
Make the smallest safe patch. Do not rewrite unrelated functions.
Show a concise diff summary before running tests.
这能降低风险,通常也能减少输出 token。更重要的是,它能让代码审查保持清晰可控。
5. 将规划与执行分开
对于复杂的改动,我通常会先这样做:
Inspect the relevant files and propose a plan. Do not edit yet.
Limit repo inspection to payment, invoice, and tax modules unless needed.
然后我批准计划,让它开始实现。这样可以避免“智能体还没理解就开始编辑”的失败模式。
控制长时间会话的支出
长时间会话既是 CLI 智能体发挥优势的场景,也是它们容易带来风险的场景。
以下是我在实际工作中使用的支出控制清单:
- 设定会话目标:“让
test_invoice_rounding通过”,而不是“修复计费功能”。 - 尽可能指定文件:提供确切路径,而不是让智能体自行查找所有内容。
- 任务转向后重置上下文:任务发生变化时,用一份摘要开启新会话。
- 手动总结失败情况:粘贴重要的 30 行,而不是一份长达 3,000 行的日志。
- 有意识地升级模型:只有遇到明确的阻碍后,才使用更强的模型。
- 反复陷入循环后停止:如果智能体以同样的方式失败两次,就进行干预。
一个好的重置提示词如下所示:
We are fixing invoice rounding.
Known facts:
- Failure is in tests/billing/test_invoice_totals.py::test_round_half_even
- Expected 10.24, actual 10.25
- Decimal quantization happens in src/billing/money.py
- Tax calculation calls round_money() from src/billing/tax.py
Continue from this summary. Inspect only those files first.
与继续携带整段失败的对话相比,这样的提示词成本可能更低,也更清晰。
API 密钥、提供商与路由
大多数 CLI 智能体可以直接调用模型提供商的 API,也可以通过兼容的网关调用。主要的工程关注点包括:
- 身份验证:API 密钥存放在哪里,以及是否会泄露到 shell 历史记录或日志中。
- 模型路由:由哪个模型处理哪个阶段。
- 速率限制:智能体循环可能在短时间内发出大量请求。
- 可观测性:按会话报告 token 用量和成本。
- 数据边界:是否允许将代码发送到外部 API。
最基本的环境配置通常如下所示:
export ANTHROPIC_API_KEY="..."
export OPENAI_API_KEY="..."
export GEMINI_API_KEY="..."
对于团队,我更倾向于使用封装脚本来选择模型并记录用量:
#!/usr/bin/env bash
set -euo pipefail
export AGENT_MODEL="${AGENT_MODEL:-sonnet}"
export AGENT_MAX_OUTPUT_TOKENS="${AGENT_MAX_OUTPUT_TOKENS:-4096}"
export AGENT_SESSION_BUDGET_USD="${AGENT_SESSION_BUDGET_USD:-10}"
coding-agent "$@"
如果你使用多模型网关,可以在这里通过统一接口路由 Claude、GPT、Gemini 或开放模型的流量。重要的功能不是展示了多少品牌标志,而是能否提供可靠的用量统计和模型级控制。
我会在仓库指令中写些什么
大多数智能体都会遵循某种形式的仓库指令文件。我会让自己的指令保持简短,并聚焦实际操作:
## Agent Instructions
- Prefer minimal diffs over rewrites.
- Do not run full test suites until targeted tests pass.
- Never edit generated files in `dist/`, `build/`, or `coverage/`.
- Use `rg` for search.
- Before large refactors, propose a plan and wait.
- If a command emits more than 200 lines, rerun with a narrower command.
这与礼貌无关。这些指令会塑造整个循环。智能体仍然会犯错,但好的指令能减少重复的浪费。
一个常见陷阱是:过长的指令文件会变成背景噪声。如果你的智能体指令是长达 300 行的风格理念,模型可能会忽略真正重要的三项操作约束。把价值最高的规则放在最前面。
延迟:另一种成本
即使 token 支出可以接受,延迟也可能打断工作节奏。
智能体的延迟来自:
- 模型推理时间
- 工具执行时间
- 文件索引时间
- 测试运行时间
- 等待人工批准的时间
对于紧凑的循环,我会优化“获得下一条有用观察结果所需的时间”。耗时 15 秒的针对性测试优于耗时 6 分钟的完整 CI 模拟。能在 4 秒内正确识别语法错误的小模型,优于花 45 秒生成精美解释的高端模型。
最好的会话感觉就像结对编程:
inspect → patch → targeted test → inspect failure → patch → targeted test → final suite
最糟糕的会话感觉就像在装模作样地跑 CI:
scan repo → edit many files → run everything → drown in logs → repeat局限与失败模式
终端智能体很有用,但并非无所不能。
它们在以下情况下会遇到困难:
- 仓库存在测试未涵盖的隐藏运行时依赖。
- 任务需要产品判断,而不是代码转换。
- 错误取决于外部服务或不稳定的状态。
- 代码库中存在误导性的抽象或过时的文档。
- 智能体无法运行相关的验证命令。
它们也可能生成看似合理却错误的修复。当测试不充分时,这种情况尤其常见。如果智能体无法验证行为,就应把它的输出视为初级工程师尚未经审核的补丁:可能有用,但绝不能自动信任。
安全也很重要。在不了解工具的审批机制之前,不要在敏感仓库中授予智能体不受限制的 shell 访问权限。除非加以限制,否则“运行命令”也包括打印环境变量、修改文件、安装软件包或访问网络的能力。
实践要点
- 将 CLI 编程工具视为由 API 驱动的控制循环,而不是单个提示词。
- 通过减少循环次数和上下文大小来优化成本,尤其要减少命令输出。
- 将强大的模型用于困难的推理,而不是每一个机械性步骤。
- 让仓库指令保持简短、可执行,并聚焦智能体行为。
- 优先进行针对性测试,最后再进行更全面的验证。
- 用简洁的摘要重置长时间会话,而不是继续携带过时的历史记录。
- 关注输入 token;它们是智能体编程中隐藏的主要成本来源。
- 当智能体重复采用同一种失败策略时,停止并进行干预。
Claude Code、Aider、Cline 和 OpenCode 代表了一场真实的转变:编程辅助正从建议引擎转向原生于终端的协作者。获益最多的团队不会只是“启用智能体”的团队,而是精心设计整个循环的团队:限定上下文、使用安全的工具、让支出可观测,并在每一步进行验证。
一个 API 密钥即可使用 Claude Opus 5.5、Sonnet 5、Haiku 4.5 和 Fable 5.1,以及 GPT-6 个模型。按量付费,无需订阅。
获取 API 密钥 →