SDK 权限

Claude Code SDK 提供强大的权限控制功能,允许您管理 Claude 在应用程序中如何使用工具。 本指南涵盖如何使用 canUseTool 回调、钩子和 settings.json 权限规则来实现权限系统。有关完整的 API 文档,请参阅 TypeScript SDK 参考

概述

Claude Code SDK 提供四种互补的方式来控制工具使用:
  1. 权限模式 - 影响所有工具的全局权限行为设置
  2. canUseTool 回调 - 用于处理其他规则未涵盖情况的运行时权限处理器
  3. 钩子 - 通过自定义逻辑对每个工具执行进行细粒度控制
  4. 权限规则 (settings.json) - 具有集成 bash 命令解析的声明式允许/拒绝规则
每种方法的用例:
  • 权限模式 - 设置整体权限行为(规划、自动接受编辑、绕过检查)
  • canUseTool - 对未涵盖情况的动态批准,提示用户获取权限
  • 钩子 - 对所有工具执行的程序化控制
  • 权限规则 - 具有智能 bash 命令解析的静态策略

权限流程图

处理顺序: PreToolUse 钩子 → 询问规则 → 拒绝规则 → 权限模式检查 → 允许规则 → canUseTool 回调 → PostToolUse 钩子

权限模式

权限模式提供对 Claude 如何使用工具的全局控制。您可以在调用 query() 时设置权限模式,或在流式会话期间动态更改它。

可用模式

SDK 支持四种权限模式,每种都有不同的行为:
模式描述工具行为
default标准权限行为应用正常权限检查
plan规划模式 - 无执行Claude 只能使用只读工具;在执行前呈现计划 (SDK 中当前不支持)
acceptEdits自动接受文件编辑文件编辑和文件系统操作自动批准
bypassPermissions绕过所有权限检查所有工具无需权限提示即可运行(谨慎使用)

设置权限模式

您可以通过两种方式设置权限模式:

1. 初始配置

创建查询时设置模式:
import { query } from "@anthropic-ai/claude-code";

const result = await query({
  prompt: "帮我重构这段代码",
  options: {
    permissionMode: 'default'  // 标准权限模式
  }
});

2. 动态模式更改(仅限流式)

在流式会话期间更改模式:
import { query } from "@anthropic-ai/claude-code";

// 为流式输入创建异步生成器
async function* streamInput() {
  yield { 
    type: 'user',
    message: { 
      role: 'user', 
      content: "让我们从默认权限开始" 
    }
  };
  
  // 稍后在对话中...
  yield {
    type: 'user',
    message: {
      role: 'user',
      content: "现在让我们加快开发速度"
    }
  };
}

const q = query({
  prompt: streamInput(),
  options: {
    permissionMode: 'default'  // 以默认模式开始
  }
});

// 动态更改模式
await q.setPermissionMode('acceptEdits');

// 处理消息
for await (const message of q) {
  console.log(message);
}

模式特定行为

接受编辑模式 (acceptEdits)

在接受编辑模式下:
  • 所有文件编辑自动批准
  • 文件系统操作(mkdir、touch、rm 等)自动批准
  • 其他工具仍需要正常权限
  • 当您信任 Claude 的编辑时加快开发速度
  • 适用于快速原型设计和迭代
自动批准的操作:
  • 文件编辑(Edit、MultiEdit、Write 工具)
  • Bash 文件系统命令(mkdir、touch、rm、mv、cp)
  • 文件创建和删除

绕过权限模式 (bypassPermissions)

在绕过权限模式下:
  • 所有工具使用都自动批准
  • 不出现权限提示
  • 钩子仍然执行(仍可阻止操作)
  • 极其谨慎使用 - Claude 拥有完整系统访问权限
  • 仅建议在受控环境中使用

权限流程中的模式优先级

权限模式在权限流程的特定点进行评估:
  1. 钩子首先执行 - 可以覆盖任何模式
  2. 检查拒绝规则 - 无论模式如何都阻止工具
  3. bypassPermissions 模式 - 如果激活,允许所有剩余工具
  4. 检查允许规则
  5. 其他模式 影响特定工具行为
  6. canUseTool 回调 - 处理剩余情况
这意味着:
  • 钩子始终可以阻止工具使用,即使在 bypassPermissions 模式下
  • 明确的拒绝规则覆盖所有权限模式
  • bypassPermissions 模式覆盖允许规则和 canUseTool

最佳实践

  1. 使用默认模式 进行受控执行和正常权限检查
  2. 使用 acceptEdits 模式 处理隔离文件或目录时
  3. 避免在生产环境或敏感数据系统上使用 bypassPermissions
  4. 将模式与钩子结合 进行细粒度控制
  5. 根据任务进度和信心动态切换模式
模式进展示例:
// 以默认模式开始进行受控执行
permissionMode: 'default'

// 切换到 acceptEdits 进行快速迭代
await q.setPermissionMode('acceptEdits')

canUseTool

canUseTool 回调在调用 query 函数时作为选项传递。它接收工具名称和输入参数,必须返回决定 - 允许或拒绝。 当 Claude Code 会向用户显示权限提示时,canUseTool 会触发,例如钩子和权限规则不涵盖它且不在自动接受模式下。 以下是显示如何实现交互式工具批准的完整示例:
import { query } from "@anthropic-ai/claude-code";

async function promptForToolApproval(toolName: string, input: any) {
  console.log("\n🔧 工具请求:");
  console.log(`   工具: ${toolName}`);
  
  // 显示工具参数
  if (input && Object.keys(input).length > 0) {
    console.log("   参数:");
    for (const [key, value] of Object.entries(input)) {
      let displayValue = value;
      if (typeof value === 'string' && value.length > 100) {
        displayValue = value.substring(0, 100) + "...";
      } else if (typeof value === 'object') {
        displayValue = JSON.stringify(value, null, 2);
      }
      console.log(`     ${key}: ${displayValue}`);
    }
  }
  
  // 获取用户批准(用您的 UI 逻辑替换)
  const approved = await getUserApproval();
  
  if (approved) {
    console.log("   ✅ 已批准\n");
    return {
      behavior: "allow",
      updatedInput: input
    };
  } else {
    console.log("   ❌ 已拒绝\n");
    return {
      behavior: "deny",
      message: "用户拒绝了此工具的权限"
    };
  }
}

// 使用权限回调
const result = await query({
  prompt: "帮我分析这个代码库",
  options: {
    canUseTool: async (toolName, input) => {
      return promptForToolApproval(toolName, input);
    }
  }
});

使用钩子进行工具控制

钩子在各个阶段提供对工具执行的程序化控制。钩子为每个工具使用调用,为您提供对权限管道的完全控制。

钩子实现

import { query } from "@anthropic-ai/claude-code";

const result = await query({
  prompt: "帮我重构这段代码",
  options: {
    hooks: {
      PreToolUse: [{
        hooks: [async (input, toolUseId, { signal }) => {
          console.log(`工具请求: ${input.tool_name}`);
          
          // 自己解析和验证工具输入
          if (input.tool_name === "Bash") {
            const command = input.tool_input.command;
            if (command.startsWith("rm -rf")) {
              return {
                decision: "block",
                reason: "危险命令已阻止"
              };
            }
          }
          
          return { continue: true };
        }]
      }],
      PostToolUse: [{
        hooks: [async (input, toolUseId, { signal }) => {
          console.log(`工具完成: ${input.tool_name}`);
          // 记录或审计工具结果
          return { continue: true };
        }]
      }]
    }
  }
});

与 canUseTool 的主要区别

  • 范围:钩子为所有工具使用调用;canUseTool 处理权限规则未涵盖的情况
  • 控制:钩子需要您自己解析和验证输入
  • 事件:钩子支持多个事件(PreToolUse、PostToolUse 等)用于不同阶段

使用权限规则 (settings.json)

settings.json 中的权限规则提供具有内置 bash 命令解析的声明式控制。这些规则在调用 canUseTool 之前进行评估。有关设置配置的更多详细信息,请参阅 Claude Code 设置文档

配置结构

{
  "permissions": {
    "allow": [
      "Bash(npm run lint)",
      "Bash(npm run test:*)",
      "Read(~/.zshrc)"
    ],
    "deny": [
      "Bash(curl:*)",
      "Read(./.env)",
      "Read(./secrets/**)",
      "WebFetch"
    ],
    "ask": [
      "Bash(git push:*)",
      "Write(./production/**)"
    ]
  }
}

规则语法

权限规则遵循模式:ToolName(pattern)
  • Bash 规则:使用前缀匹配(非正则表达式)。示例:Bash(npm:*) 匹配任何以 “npm” 开头的命令
  • 文件规则:支持 glob 模式。示例:Read(./src/**/*.ts) 匹配 src 中的 TypeScript 文件
  • 仅工具规则:省略括号以控制整个工具。示例:WebFetch 阻止所有 web 获取

与 SDK 一起使用

虽然规则还不能在 SDK 中以编程方式设置,但它们将从加载 SDK 的路径中的 settings.json 文件中读取。

权限评估顺序

  1. 首先检查拒绝规则 - 如果匹配,工具使用被阻止
  2. 接下来检查允许规则 - 如果匹配,工具使用被允许
  3. 检查询问规则 - 如果匹配,提示用户
  4. 对任何剩余情况调用 canUseTool 回调

Bash 命令解析

SDK 包含一个集成的 bash 解析器,理解命令结构:
  • 处理管道、重定向和命令替换
  • 识别危险模式如 rm -rfcurl | sh
  • 支持通配符和前缀匹配
bash 模式工作方式示例:
  • Bash(git:*) - 匹配任何 git 命令
  • Bash(npm run test) - 匹配确切命令
  • Bash(npm run test:*) - 匹配 npm run test:unit、test:integration 等

最佳实践

  1. 从默认模式开始 进行标准权限检查
  2. 使用权限规则 进行静态策略,特别是 bash 命令(参见 权限设置
  3. 使用钩子 记录、审计或转换所有工具使用(参见 钩子类型
  4. 使用 canUseTool 对未涵盖情况进行动态决策(参见 CanUseTool 类型
  5. 通过组合模式、规则、钩子和回调为关键应用程序分层防御