avatar


1.Start

引子

在2023年的年初,只有ChatGPT聊天网页,还没有ClaudeCode或Cursor的时候,我们是怎么借助ChatGPT聊天网页写代码的?
我们把代码复制到聊天框,描述遇到的问题,ChatGPT提出修改建议,我们按照ChatGPT提出的建议,自己在IDE上修改,如果问题没有被解决,我们再反馈给ChatGPT。

现在上述重复的动作可以由ClaudeCode代为执行,这就是工具调用循环(agent loop)。这个循环始又始终受AI的"缺陷"约束,AI很聪明,但它的记忆容量有限(上下文窗口有限),这份有限的记忆必须精打细算地使用(上下文管理)。

这也就是ClaudeCode的本质:大模型+工具调用循环+上下文管理

官方文档:https://code.claude.com/docs

工具调用循环

我们先把"工具调用循环"讲清楚。
至于"上下文管理"是本系列文章的主线,会在后续章节逐个讨论。

什么是工具调用循环

大模型的输入是文本,输出也是文本。
大模型可以"说出"一段正确的"补丁",但"说出"不等于"改掉"。
要让大模型作用于真实工程环境,必须有一个执行者,把模型的意图翻译成动作,再把动作的结果翻译回文本。

工具调用就是这层翻译的标准形式:大模型输出一个结构化请求(调用哪个工具、参数是什么),ClaudeCode执行该结构化请求,再把执行结果作为新的上下文交还给模型。

把这层翻译反复连接起来,就是工具调用循环

一次循环有三个阶段:

  1. 收集上下文
    搜索、读文件、看报错,理清现状。
  2. 执行操作
    改文件、跑命令。
  3. 验证结果
    跑测试、检查产物;如不满意,回到第一阶段重复。

五大类工具

ClaudeCode可以使用的工具分为五大类:

类别 代表 用途
文件操作 ReadEdit 读取、修改文件
搜索 GrepGlob 按内容、按文件名定位代码
执行 Bash(Windows下为PowerShell) 运行构建、测试等任意命令
网络 WebFetch 抓取网页与在线文档
代码智能 IDE类工具 诊断、跳转等编辑器能力

上下文管理

循环每转一圈,读过的文件、命令的输出、模型自身的推理,都会进入上下文窗口,而窗口是有限的。

如何最大限度地利用有限的窗口,就是上下文管理,也是我们后续章节讨论的重点:

权限系统

通过上文的讨论,我们知道了,只会生成文本的大模型,是如何作用于真实的工程环境的。
现在,我们要回答,如何安全地作用于真实的工程环境。
即,权限怎么管?

什么是权限系统

权限系统对每一次工具调用只做一次判断:直接放行、先问我、还是拒绝。

做这个判断的是两套机制:

  1. 全局的权限模式
  2. 精确的权限规则

权限模式

权限模式是全局的默认姿态,同一时刻只有一种,Shift+Tab可循环切换。最基础的是default模式,按风险把工具分三层对待:

  • 只读操作
    读文件、搜索等,不提示,直接执行。
  • Bash命令
    执行类操作,需要批准。
  • 文件修改
    Edit等写操作,需要批准,批准后本会话内不再重复提示。

除了default模式,还有五种模式(acceptEditsplanautodontAskbypassPermissions),都是在这条基线上调松或调紧。
这六种模式的完整行为表见后文「实践」。

权限规则

权限规则则能精确到具体命令或路径。
我们可以基于此为个别工具调用单独定规矩。

规则分为allow放行、ask先问、deny拒绝,共三类。
三类规则之间的优先级为deny > ask > allow

即,deny的优先级最高。deny最先检查,命中即拒绝。
deny没有例外机制,即便存在一条更具体的allow,也豁免不了。并且deny跨作用域生效,写在任何一层配置里都拦得住。

如果需要给某个deny"开口子",唯一的办法是收窄这条deny的specifier本身。

规则的具体语法与示例见后文「实践」。

两套机制如何合并

两套机制如何合并成最终结果?对每一次工具调用,ClaudeCode先按规则判定,规则没管到的再交给模式兜底。

即:

  1. 规则优先
    任何一条规则命中即定,三类规则之间的评估顺序见上文「权限规则」。
  2. 模式兜底
    规则都没命中时,由当前模式给出默认处置: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
2
3
4
5
# macOS / Linux / WSL
curl -fsSL https://claude.ai/install.sh | bash

# Homebrew
brew install --cask claude-code
1
2
3
4
5
# Windows PowerShell
irm https://claude.ai/install.ps1 | iex

# WinGet
winget install Anthropic.ClaudeCode

启动命令

命令 行为
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 自动接受文件编辑,以及mkdirtouchmvcp等文件系统命令。
plan 只读探索,不修改源文件。
auto 后台安全检查通过即自动批准(研究预览阶段)。
dontAsk 自动拒绝,除非已通过/permissions预先批准。
bypassPermissions 跳过全部权限提示。

bypassPermissions会让ClaudeCode不经任何确认地修改文件、执行命令。

权限规则

权限规则写在Settings的permissions字段里(可以用/permissions交互式管理),分allow放行、ask先问、deny拒绝,共三类。

示例代码:

1
2
3
4
5
6
7
{
"permissions": {
"allow": ["Bash(npm *)", "Read(/src/**)"],
"ask": ["WebFetch(domain:*.com)"],
"deny": ["Read(/secrets/**)"]
}
}

三条典型规则的含义:

  • Bash(npm *)
    匹配所有以npm 开头的命令。放进allow后,跑npm testnpm run build不再需要逐次批准。
  • Read(/src/**)
    匹配对/src/目录下所有文件的读取。
  • WebFetch(domain:*.com)
    匹配对.com域名的网页抓取。

Bash里的一批常用读类命令内置了免提示放行:lscatpwdheadtailgrepfindwccd。如果想对其中某条强制确认,可以为它写一条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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"permissions": {
"allow": [
"Bash(npm *)",
"Read(/src/**)"
],
"ask": [
"WebFetch(domain:*.com)"
],
"deny": [
"Read(/secrets/**)"
]
},
"env": {
"NODE_ENV": "development"
}
}
文章作者: Kaka Wan Yifan
文章链接: https://kakawanyifan.com/12801
版权声明: 本博客所有文章版权为文章作者所有,未经书面许可,任何机构和个人不得以任何形式转载、摘编或复制。