Skip to content
源码分析手册

default-and-acceptedits-modes:Default 与 AcceptEdits 模式的运行时行为

在 Claude Code 中,权限模式(Permission Mode)直接决定了 Agent 的“手脚”被束缚到什么程度。其中最常用的两种——defaultacceptEdits——在源码层面上有着截然不同的判定路径。

一句话讲清楚

本质上,这是 执行策略的全局开关

  • Default:保守派。默认所有涉及系统变更的操作(写文件、运行命令)都必须经过人类确认。
  • AcceptEdits:效率派。它假定模型修改代码是安全的(或可撤销的),因此自动放行所有文件写入,但依然拦截 Bash 命令。

从源码看实现

模式的枚举和基本属性定义在 claude-code-opensource/src/utils/permissions/PermissionMode.ts。但真正的行为分水岭在于各工具的 checkPermissions 实现。

1. Default 模式:全员拦截

default 模式下,toolPermissionContext.modedefault。 当 FileEditTool 被调用时:

  1. 进入 src/utils/permissions/filesystem.tscheckWritePermissionForTool
  2. 代码会检查是否存在显式的 allow 规则。由于是 default 模式,通常没有。
  3. 逻辑落入最后的兜底逻辑:return { behavior: 'ask' }
  4. 这会导致 UI 层弹出 (y/n) 确认框。

2. AcceptEdits 模式:针对性放行

这是 AcceptEdits 模式最精彩的部分。在 src/utils/permissions/filesystem.ts 的第 1366 行左右:

typescript
if (toolPermissionContext.mode === 'acceptEdits' && isInWorkingDir) {
  return {
    behavior: 'allow',
    // ...
  }
}
  • 它的边界:仅当 isInWorkingDir(在当前项目目录下)且是“编辑”操作时,它才会返回 allow
  • 它不放行什么:虽然它放行了文件修改,但它 完全不放行 bash 工具(除非是只读命令)。在 src/tools/BashTool 的相关检查中,如果是 acceptEdits 模式,它依然会要求用户确认除了 lspwd 等安全命令之外的所有操作。

边界条件

  1. AcceptEdits 不是 Bypass:它只对 FileEditToolFileWriteTool 宽容。如果你让 Claude 运行 npm install,在 acceptEdits 模式下你依然得敲 y
  2. 符号的含义:在 UI 状态栏,acceptEdits 对应的是双箭头 ⏵⏵。这在 PermissionMode.ts 中被定义,代表“快进”编辑过程。
  3. 安全性隔离:即便在 acceptEdits 模式下,修改 .git 目录或 .claude.json 依然会被 safetyCheck 拦截,并强行降级为 ask。这在 filesystem.tsDANGEROUS_FILES 检查中体现。

继续探索

  • 想看危险文件名单?查看 claude-code-opensource/src/utils/permissions/filesystem.tsDANGEROUS_FILES 常量。
  • 想看自动模式(Auto Mode)与它们的区别?查看 claude-code-opensource/src/utils/permissions/classifierDecision.ts

源码锚点

📄 src/utils/permissions/PermissionMode.ts — `acceptEdits` 的 UI 配置定义。L49-69 of 142
typescript
    color: 'text',
    external: 'default',
  },
  plan: {
    title: 'Plan Mode',
    shortTitle: 'Plan',
    symbol: PAUSE_ICON,
    color: 'planMode',
    external: 'plan',
  },
  acceptEdits: {
    title: 'Accept edits',
    shortTitle: 'Accept',
    symbol: '⏵⏵',
    color: 'autoAccept',
    external: 'acceptEdits',
  },
  bypassPermissions: {
    title: 'Bypass Permissions',
    shortTitle: 'Bypass',
    symbol: '⏵⏵',
📄 src/utils/permissions/filesystem.ts — `acceptEdits` 自动放行逻辑的硬编码位置。L1356-1376 of 1778
typescript
      }
    }
  }

  // 3. If in acceptEdits or sandboxBashMode mode, allow all writes in original cwd
  const isInWorkingDir = pathInAllowedWorkingPath(
    path,
    toolPermissionContext,
    pathsToCheck,
  )
  if (toolPermissionContext.mode === 'acceptEdits' && isInWorkingDir) {
    return {
      behavior: 'allow',
      updatedInput: input,
      decisionReason: {
        type: 'mode',
        mode: toolPermissionContext.mode,
      },
    }
  }
📄 src/tools/FileEditTool/FileEditTool.ts — 文件编辑工具如何调用权限检查引擎。L115-135 of 626
typescript
  backfillObservableInput(input) {
    // hooks.mdx documents file_path as absolute; expand so hook allowlists
    // can't be bypassed via ~ or relative paths.
    if (typeof input.file_path === 'string') {
      input.file_path = expandPath(input.file_path)
    }
  },
  async preparePermissionMatcher({ file_path }) {
    return pattern => matchWildcardPattern(pattern, file_path)
  },
  async checkPermissions(input, context): Promise<PermissionDecision> {
    const appState = context.getAppState()
    return checkWritePermissionForTool(
      FileEditTool,
      input,
      appState.toolPermissionContext,
    )
  },
  renderToolUseMessage,
  renderToolResultMessage,
  renderToolUseRejectedMessage,

基于 Claude Code v2.1.88 开源快照的深度分析