引子
在2023年的年初,只有ChatGPT聊天网页,还没有ClaudeCode或Cursor的时候,我们是怎么借助ChatGPT聊天网页写代码的?
我们把代码复制到聊天框,描述遇到的问题,ChatGPT提出修改建议,我们按照ChatGPT提出的建议,自己在IDE上修改,如果问题没有被解决,我们再反馈给ChatGPT。
现在上述重复的动作可以由ClaudeCode代为执行,这就是工具调用循环(agent loop)。这个循环始又始终受AI的"缺陷"约束,AI很聪明,但它的记忆容量有限(上下文窗口有限),这份有限的记忆必须精打细算地使用(上下文管理)。
这也就是ClaudeCode的本质:大模型+工具调用循环+上下文管理。
官方文档:https://code.claude.com/docs
工具调用循环
我们先把"工具调用循环"讲清楚。
至于"上下文管理"是本系列文章的主线,会在后续章节逐个讨论。
什么是工具调用循环
大模型的输入是文本,输出也是文本。
大模型可以"说出"一段正确的"补丁",但"说出"不等于"改掉"。
要让大模型作用于真实工程环境,必须有一个执行者,把模型的意图翻译成动作,再把动作的结果翻译回文本。
工具调用就是这层翻译的标准形式:大模型输出一个结构化请求(调用哪个工具、参数是什么),ClaudeCode执行该结构化请求,再把执行结果作为新的上下文交还给模型。
把这层翻译反复连接起来,就是工具调用循环。
一次循环有三个阶段:
- 收集上下文
搜索、读文件、看报错,理清现状。 - 执行操作
改文件、跑命令。 - 验证结果
跑测试、检查产物;如不满意,回到第一阶段重复。
五大类工具
ClaudeCode可以使用的工具分为五大类:
| 类别 | 代表 | 用途 |
|---|---|---|
| 文件操作 | Read、Edit |
读取、修改文件 |
| 搜索 | Grep、Glob |
按内容、按文件名定位代码 |
| 执行 | Bash(Windows下为PowerShell) |
运行构建、测试等任意命令 |
| 网络 | WebFetch |
抓取网页与在线文档 |
| 代码智能 | IDE类工具 | 诊断、跳转等编辑器能力 |
上下文管理
循环每转一圈,读过的文件、命令的输出、模型自身的推理,都会进入上下文窗口,而窗口是有限的。
如何最大限度地利用有限的窗口,就是上下文管理,也是我们后续章节讨论的重点:
- 稳定知识的持久注入:《2.Memory》
- 成段指令的按需注入:《3.Skill》
- 高噪声任务的隔离:《4.SubAgent》
权限系统
通过上文的讨论,我们知道了,只会生成文本的大模型,是如何作用于真实的工程环境的。
现在,我们要回答,如何安全地作用于真实的工程环境。
即,权限怎么管?
什么是权限系统
权限系统对每一次工具调用只做一次判断:直接放行、先问我、还是拒绝。
做这个判断的是两套机制:
- 全局的权限模式
- 精确的权限规则
权限模式
权限模式是全局的默认姿态,同一时刻只有一种,Shift+Tab可循环切换。最基础的是default模式,按风险把工具分三层对待:
- 只读操作
读文件、搜索等,不提示,直接执行。 Bash命令
执行类操作,需要批准。- 文件修改
Edit等写操作,需要批准,批准后本会话内不再重复提示。
除了default模式,还有五种模式(acceptEdits、plan、auto、dontAsk、bypassPermissions),都是在这条基线上调松或调紧。
这六种模式的完整行为表见后文「实践」。
权限规则
权限规则则能精确到具体命令或路径。
我们可以基于此为个别工具调用单独定规矩。
规则分为allow放行、ask先问、deny拒绝,共三类。
三类规则之间的优先级为deny > ask > allow。
即,deny的优先级最高。deny最先检查,命中即拒绝。
deny没有例外机制,即便存在一条更具体的allow,也豁免不了。并且deny跨作用域生效,写在任何一层配置里都拦得住。
如果需要给某个deny"开口子",唯一的办法是收窄这条deny的specifier本身。
规则的具体语法与示例见后文「实践」。
两套机制如何合并
两套机制如何合并成最终结果?对每一次工具调用,ClaudeCode先按规则判定,规则没管到的再交给模式兜底。
即:
- 规则优先
任何一条规则命中即定,三类规则之间的评估顺序见上文「权限规则」。 - 模式兜底
规则都没命中时,由当前模式给出默认处置:default的效果在上文提到了,acceptEdits让编辑自动放行,plan挡下所有写操作,bypassPermissions则连提示都不出、一路放行。
Settings
什么是Settings
那么?权限规则配置落在哪?配置文件,settings.json。
需要注意的是,settings.json是整个ClaudeCode的配置文件,而不仅仅是权限规则的配置文件。
优先级
ClaudeCode的配置体系围绕settings.json展开,同一个字段可以出现在多个作用域,高优先级覆盖低优先级。
| 优先级(1最高) | 作用域 | 位置 | 生效范围 | 是否共享 |
|---|---|---|---|---|
| 1 | Managed | 由组织统一下发 | 全组织或整台机器 | 是 |
| 2 | CLI临时参数 | 启动claude时的命令行参数 |
本次会话 | 否 |
| 3 | Local | .claude/settings.local.json |
当前用户在本仓库 | 否 |
| 4 | Project | .claude/settings.json |
仓库全部协作者 | 是 |
| 5 | User | ~/.claude/settings.json |
当前用户的全部项目 | 否 |
- Managed层不可被覆盖,这是企业锁定安全策略的手段。
- Project层随仓库提交,用来沉淀团队共识。
- 个人偏好放User层,只属于自己。
- 不想提交的本仓库设置放Local层。
Settings的关键字段与完整示例见后文「实践」。
实践
安装
有四种安装方式,主要差别在于是否自动更新。
| 方式 | 适用平台 | 自动更新 |
|---|---|---|
| 原生安装脚本(curl) | macOS、Linux、WSL | 是 |
| 原生安装脚本(PowerShell) | Windows | 是 |
| Homebrew | macOS | 否 |
| WinGet | Windows | 否 |
示例代码:
1 | macOS / Linux / WSL |
1 | # Windows PowerShell |
启动命令
| 命令 | 行为 |
|---|---|
claude |
启动交互式REPL |
claude "task" |
启动REPL并直接下发第一个任务 |
claude -c |
续接最近一次会话 |
claude -p "query" |
非交互执行、输出后退出,面向脚本与CI |
基本输入:自然语言、@file、!前缀
进入会话后,有三种基本输入:
- 自然语言
直接描述任务,这是主要的交互方式。 @file
用@引用文件,把它加入上下文。注意:@只是加载内容,不授予修改该文件的权限。!前缀
以!开头的输入直接作为bash命令执行,不经过模型。
常用斜杠命令
会话内以/开头的输入是斜杠命令,用来控制ClaudeCode本身而非下发任务。
| 命令 | 作用 | 备注 |
|---|---|---|
/help |
列出可用命令 | |
/model |
查看与切换模型 | 会话中途切换会使prompt cache失效,下一轮明显更慢、更贵,原因见前文「上下文管理」 |
/clear |
清空上下文,开启新会话 | 历史彻底丢弃、不生成摘要,与/compact不同 |
/resume |
从历史会话列表中选择并恢复 | |
/compact |
手动压缩对话以节省token | 把老的往来内容替换成摘要(保留原始请求与关键代码);窗口接近上限时ClaudeCode也会自动触发 |
/context |
可视化上下文占用 | 用来判断还剩多少空间、什么占了大头 |
/cost |
查看成本统计 | |
/doctor |
诊断安装问题 | 按f可自动修复 |
/permissions |
交互式管理权限规则 | 管理前文「权限系统」讲的allow/ask/deny规则 |
/config |
打开设置界面 | |
/diff |
交互式查看文件改动 | |
/plan |
进入只读计划模式 | 只探索、不修改源文件,对应plan权限模式 |
/init |
生成CLAUDE.md |
在《2.Memory》会重点讨论 |
权限管理
权限模式
六种权限模式的完整行为如下:
| 模式 | 行为 |
|---|---|
default |
首次使用某工具时提示。 |
acceptEdits |
自动接受文件编辑,以及mkdir、touch、mv、cp等文件系统命令。 |
plan |
只读探索,不修改源文件。 |
auto |
后台安全检查通过即自动批准(研究预览阶段)。 |
dontAsk |
自动拒绝,除非已通过/permissions预先批准。 |
bypassPermissions |
跳过全部权限提示。 |
bypassPermissions会让ClaudeCode不经任何确认地修改文件、执行命令。
权限规则
权限规则写在Settings的permissions字段里(可以用/permissions交互式管理),分allow放行、ask先问、deny拒绝,共三类。
示例代码:
1 | { |
三条典型规则的含义:
Bash(npm *)
匹配所有以npm开头的命令。放进allow后,跑npm test、npm run build不再需要逐次批准。Read(/src/**)
匹配对/src/目录下所有文件的读取。WebFetch(domain:*.com)
匹配对.com域名的网页抓取。
Bash里的一批常用读类命令内置了免提示放行:ls、cat、pwd、head、tail、grep、find、wc、cd。如果想对其中某条强制确认,可以为它写一条ask规则。
Settings配置
关键字段
Settings的关键字段:
| 字段 | 类型 | 作用 |
|---|---|---|
model |
string | 默认模型 |
defaultMode |
string | 默认权限模式,六种取值见前文「权限模式」 |
permissions.allow/permissions.deny/permissions.ask |
array | 权限规则列表 |
permissions.additionalDirectories |
array | 工作目录之外额外允许访问的目录 |
env |
object | 注入会话的环境变量 |
enabledPlugins |
object | 插件开关 |
例子
例如my-project的项目级配置.claude/settings.json:
1 | { |