文件操作工具
文件操作是 Claude Code 最基础的能力,由三个工具组成:FileReadTool(读取)、FileEditTool(编辑)、FileWriteTool(写入)。
注意: 以下所有工具的
call()方法均为普通async函数,返回Promise<ToolResult>,不是 AsyncGenerator。代码示例中的yield toolResult(...)为伪代码表示返回结果。
FileReadTool — 文件读取
输入 Schema
typescript
const inputSchema = z.object({
file_path: z.string().describe('要读取的文件的绝对路径'),
offset: z.number().optional().describe('起始行号(1-indexed)'),
limit: z.number().optional().describe('读取的最大行数'),
})执行逻辑
FileReadTool 的 call() 方法执行流程:
- 路径解析(
safeResolvePath) - 二进制检测(基于文件扩展名)
- 文件大小检查(超过阈值提示使用 offset/limit)
- 读取文件内容
- 记录时间戳(用于后续编辑冲突检测)
- 添加行号并返回
权限
isReadOnly()=trueisConcurrencySafe()=true- 无需权限确认
FileEditTool — 精确编辑
FileEditTool 使用 查找-替换 模式进行精确编辑。
输入 Schema
typescript
const inputSchema = z.strictObject({
file_path: z.string().describe('要编辑的文件绝对路径'),
old_string: z.string().describe('要替换的精确文本'),
new_string: z.string().describe('替换后的新文本'),
replace_all: z.boolean().default(false).optional()
.describe('是否替换所有匹配。默认 false'),
})执行逻辑
FileEditTool 的 call() 方法执行流程:
- 路径解析
- 读取当前文件内容
- 冲突检测——检查文件是否在上次读取后被外部修改
- 查找匹配并执行替换
- 写入文件
- 更新时间戳
- 生成 diff 并返回
权限
isReadOnly()=falseisDestructive()=trueisConcurrencySafe()=false(文件系统竞争)- 需要权限确认:
FileEdit(path_pattern)
UI 渲染
typescript
// FileEditToolDiff.tsx — 差异显示组件
type Props = {
file_path: string
edits: FileEdit[] // from src/tools/FileEditTool/types.ts
}
type FileEdit = {
old_string: string
new_string: string
replace_all: boolean
}
function FileEditToolDiff({ file_path, edits }: Props) {
return (
<StructuredDiff
edits={edits}
filePath={file_path}
showLineNumbers
/>
)
}FileWriteTool — 文件写入
输入 Schema
typescript
const inputSchema = z.object({
file_path: z.string().describe('要创建或覆写的文件绝对路径'),
content: z.string().describe('文件的完整内容'),
})执行逻辑
FileWriteTool 的 call() 方法执行流程:
- 路径解析
- 内容大小检查
- 确保目录存在
- 写入文件
- 更新时间戳
权限
isReadOnly()=falseisDestructive()=true- 需要权限确认:
FileWrite(path_pattern) - 新文件创建 vs 覆写有不同提示文本
文件操作安全机制
路径安全验证
路径安全检查通过 safeResolvePath 等内部函数实现,主要规则:
- 必须是绝对路径
- 禁止路径遍历(
..) - 必须在允许目录内(工作目录 + additionalDirectories)
读后写冲突检测
t=0: FileRead("/src/app.ts") → readFileTimestamps["/src/app.ts"] = t0
t=1: 用户在外部编辑 /src/app.ts → mtime = t1
t=2: FileEdit("/src/app.ts") → 检测 mtime(t1) > lastRead(t0) → 拒绝!
→ "File has been modified since last read"