avatar


1.概述

简介

ClaudeCode是Anthropic推出的命令行AI编程工具。
第一眼看上去,像一个装在终端里的聊天窗口;但聊天窗口只会输出文字,Claude Code却会真的读文件、真的改代码、真的执行命令。
那么,一个只会生成文本的大模型,如何安全地作用于真实代码库的呢?

工具调用循环(agent loop):模型提出要做的动作,ClaudeCode代为执行,再把结果喂回模型。
而这个循环始又终受一个硬约束支配:模型一次能看到的内容是有限的。

即,ClaudeCode的本质是"大模型+工具调用循环+有限上下文窗口"

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

工具调用循环

工具调用

大模型的输入是文本,输出也是文本。大模型可以"说出"一段正确的补丁,但"说出"不等于"改掉"。
要让大模型作用于真实工程环境,必须有一个执行者,把模型的意图翻译成动作,再把动作的结果翻译回文本。
工具调用就是这层翻译的标准形式:大模型输出一个结构化请求(调用哪个工具、参数是什么),ClaudeCode执行该结构化请求,再把执行结果作为新的上下文交还给模型。

工具调用循环

但是单次工具调用不足以完成任务,真实的工程任务靠循环完成。
一次循环有三个阶段,如果跑不通就带着新信息再来一轮。

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

注意,这里循环的每一步都可以被打断。

(我们在使用ClaudeCode时候,按下的ESC,打断的就是这个循环。)

工具的五大类

ClaudeCode的内置工具可以分为五大类:

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

工具集决定了循环的能力边界:能读到什么、能跑什么,循环就能做成什么。

有限的上下文窗口

概述

循环每转一圈,读过的文件、命令的输出、模型自身的推理,都会进入上下文窗口,而窗口是有限的。
后续我们的讨论,都是如何在有限的上下文中,让ClaudeCode完成既定的任务。

一些斜杠命令

我们可能见过ClaudeCode的如下三个命令,这三个都是和上下文管理有关的。

  1. /context:可视化当前窗口的占用情况,用来判断还剩多少空间、什么占了大头。
  2. /compact:压缩上下文。
    在窗口接近上限时,ClaudeCode也会自动压缩早期对话,把老的往来内容替换成摘要(保留原始请求与关键代码)
  3. /model:模型切换。
    会话中途切换模型,全部对话历史要在新模型上重新处理,之前积累的prompt cache(提示词缓存,对已处理过的上下文前缀的复用机制)无法复用。所以,切换后的下一轮会明显更慢、更贵。

安装

有四种安装方式,主要差别在于是否自动更新。

方式 适用平台 自动更新
原生安装脚本(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,见《7.Headless》

进入会话后,有三种基本输入:

  • 自然语言
    直接描述任务,这是主要的交互方式。
  • @file
    @引用文件,把它加入上下文。注意:@只是加载内容,不授予修改该文件的权限。
  • !前缀
    !开头的输入直接作为bash命令执行,不经过模型。

常用斜杠命令

会话内以/开头的输入是斜杠命令,用来控制ClaudeCode本身而非下发任务。

命令 作用
/help 列出可用命令
/model 查看与切换模型
/clear 清空上下文,开启新会话
/resume 从历史会话列表中选择并恢复
/compact 手动压缩对话以节省token
/context 可视化上下文占用
/cost 查看成本统计
/doctor 诊断安装问题,按f可自动修复
/permissions 交互式管理权限规则
/config 打开设置界面
/diff 交互式查看文件改动
/plan 进入只读计划模式,探索但不修改源文件
/init 生成CLAUDE.md,见《2.Memory》

权限系统

权限系统对每一次工具调用只做一个判断:直接放行、先问我、还是拒绝。做这个判断的是两套机制——全局的权限模式与精确的权限规则。本节先分别看这两套机制,再看它们如何合并成最终结果。

机制一:权限模式

权限模式是全局的默认姿态,同一时刻只有一种,Shift+Tab可循环切换。

最基础的是default模式,它按风险把工具分三层对待:

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

其余五种模式,本质是在这条基线上整体调松或调紧放行的尺度:

模式 行为
default 首次使用某工具时提示(即上面的三层)
acceptEdits 自动接受文件编辑,以及mkdirtouchmvcp等文件系统命令
plan 只读探索,不修改源文件
auto 后台安全检查通过即自动批准(研究预览阶段)
dontAsk 自动拒绝,除非已通过/permissions预先批准
bypassPermissions 跳过全部权限提示

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

机制二:权限规则

模式是一刀切的,权限规则则能精确到具体命令或路径,为个别工具调用单独定规矩。规则写在Settings的permissions字段里,或用/permissions交互式管理,分为allow、ask、deny三类。规则的格式是ToolTool(specifier):只写工具名匹配该工具的全部调用,括号里的specifier进一步收窄匹配范围。

示例代码:

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域名的网页抓取。

三类规则之间的评估优先级固定为deny > ask > allow:deny最先检查,命中即拒绝。deny没有例外机制——即便存在一条更具体的allow,也豁免不了;并且deny跨作用域生效,写在任何一层配置里都拦得住。如果需要给某个deny"开口子",唯一的办法是收窄这条deny的specifier本身。

另外,Bash里的一批常用读类命令内置了免提示放行:lscatpwdheadtailgrepfindwccd。这批命令对应的正是default模式里"只读操作不提示"那一层;如果想对其中某条强制确认,可以为它写一条ask规则。

两者如何合并

对每一次工具调用,Claude Code先按规则判定,规则没管到的再交给模式兜底:

  1. 规则优先,顺序deny > ask > allow,任一命中即定,其中deny绝对优先、没有例外。
  2. 模式兜底,规则都没命中时由当前模式给出默认处置:default就是上面那三层,acceptEdits让编辑自动放行,plan挡下所有写操作,bypassPermissions则连提示都不出、一路放行。

一句话:模式定下基线的松紧,规则在具体的点上再收紧或放开,而deny永远压在最上面。

权限系统与沙盒不是一回事。权限系统工作在Claude的决策层,决定一次工具调用是否放行;沙盒工作在操作系统层,限制进程本身能读写什么。两者可以组合,构成纵深防御。

Settings配置

上一节的规则要落到文件里。ClaudeCode的配置体系围绕settings.json展开,同一个字段可以出现在多个作用域,高优先级覆盖低优先级:

优先级 作用域 位置 生效范围 是否共享
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层。

关键字段:

字段 类型 作用
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"
}
}

注意:大部分设置改动自动生效,不需要重启Claude Code。

文章作者: Kaka Wan Yifan
文章链接: https://kakawanyifan.com/12801
版权声明: 本博客所有文章版权为文章作者所有,未经书面许可,任何机构和个人不得以任何形式转载、摘编或复制。

留言板