Claude

Claude Code 跑长任务总停在 YES/NO:权限配置与无人值守方案

编辑部阅读约 7 分钟

让 Claude Code 执行写好的分步任务,人离开一会儿回来发现它仍卡在命令确认提示上。文章分析「选过不再询问却没生效」的常见原因,给出收紧权限白名单、无人值守模式、会话保活与远程查看进度的具体做法,并说明各自的风险和适用场景。

写好一段分点、分步、事无巨细的提示词,交给 Claude Code 自己跑,然后去处理别的事——回来一看,它并没有跑完,而是停在某条命令的确认提示上,等着你敲一个 yes。这种体验几乎是所有把 agent 当「后台任务」用的人都会遇到的第一个坑。

问题的本质不是模型能力不够,而是执行链路里仍然有一个必须由人参与的环节:工具调用的授权。只要这个环节还在,任务的实际耗时就不取决于机器跑多快,而取决于你多久回来看一眼。下面把原因拆开,再给几种从「收紧」到「放开」的解法,以及各自的代价。

为什么「选过不再询问」还是会弹

多数人第一次遇到时都会疑惑:刚才明明批准过同类命令了。常见原因有这几类:

  • 批准的范围比你以为的窄。 会话内的「不再询问」通常只对相同工具、相同命令前缀或相同匹配模式生效。你批准的是 npm run test,下一条变成 npm run test -- --watch=false 或 cd packages/api && npm test,在匹配规则看来就是另一条命令。
  • 命令组合会拆开判断。 带管道、&&、重定向、sudo 的命令往往被逐段评估,只要其中一段没被批准过,整个调用就要重新确认。
  • 会话级授权不跨会话。 换目录、重启终端、切分支重开,之前点的「不再询问」通常不保留。只有写进配置文件的规则才是持久的。
  • 不只是 Bash 会拦。 写文件、改配置、访问工作目录之外的路径,同样可能触发确认,只是提示文案不同,容易被当成「又要按一次」。
  • 插件和 CLI 的授权状态不共享。 在编辑器插件里点过的选项,未必同步到终端里的会话,反之亦然。

所以「它是不是卡住了」的判断标准很简单:看最后一行是不是在等你输入。如果是,模型没出问题,是授权策略和你的任务粒度不匹配。

方案一:把常用命令写进权限白名单(推荐默认做法)

最稳妥的方向不是「全部放开」,而是把这条任务真正需要的那几条命令提前放行,其余保持人工确认。这类规则写在项目的配置文件里,跨会话持久生效,也便于随仓库一起评审。

一个示意性的配置结构:

{
  "permissions": {
    "allow": [
      "Read",
      "Bash(git status)",
      "Bash(git diff:*)",
      "Bash(npm run lint)",
      "Bash(npm run test:*)"
    ],
    "deny": [
      "Bash(rm -rf:*)",
      "Bash(git push:*)"
    ]
  }
}

几点经验:

  1. 先跑一遍再收口。 第一次让任务正常跑,把你实际点过「同意」的命令记下来,再回头写进 allow 列表,比凭想象列清单准确得多。
  2. 用前缀通配而不是全量放开。 Bash(npm run test:*) 覆盖参数变化,但仍然拒绝任意 shell 命令。
  3. deny 比 allow 优先级更高。 把推送、删除、发布、动数据库这类不可逆操作显式禁掉,比事后检查更省心。
  4. 字段名与匹配语法以官方文档为准。 不同版本的匹配规则、是否支持工作目录级配置、是否区分项目与用户级,都可能变化,配置前先核对一遍当前文档。

方案二:无人值守模式,以及它真正的风险

Claude Code 提供了跳过全部权限确认的启动参数,社区里也常有人直接建议用它:

claude --dangerously-skip-permissions

名字里的「dangerously」不是修辞。它意味着模型生成的任意命令都会立刻执行,包括删除文件、改写配置、发起网络请求、安装依赖。参数本身是官方提供的,风险由使用者承担。

如果确实要跑长时间无人值守的任务,建议把风险限制在可回滚的范围内:

  • 放在一次性环境里跑:容器、临时虚拟机、可随时重建的工作区,跑完即销毁。
  • 不要在有生产凭据的机器上开:包括云厂商密钥、数据库口令、CI token、SSH 私钥。
  • 先提交或打快照:让任何破坏性改动都能用一条命令回退。
  • 网络出口收敛:无人值守时被诱导执行外发数据的命令,是这类模式最典型的损失方式。
  • 注意运行身份限制:某些环境下该参数会受到额外限制,具体以官方最新说明为准。

另一个折中选项是只自动接受文件编辑、命令仍需确认的模式(例如 --permission-mode acceptEdits 这类更细粒度的权限模式)。它能解决「改十几个文件要按十几次」的痛点,但解决不了「命令确认卡住」的问题,适合改动多、命令少的任务。

方案三:让会话活过你离开的那段时间

即使权限问题解决了,还有一个容易忽略的点:终端会话本身。笔记本合盖休眠、SSH 断线、Wi-Fi 切换,都会让前台进程中断。

最轻量的做法是把会话放进 tmux 或 screen:

# 新建会话并启动任务
tmux new -s work
claude

# 暂时离开:Ctrl-b 然后按 d
# 回来重新接入
tmux attach -t work

这样即使本地终端断了,进程仍在服务器或本机上继续跑。配合手机的 SSH 客户端,可以在外面看进度。

如果瓶颈在本地设备——比如编译时机器卡死、需要合盖带走、或者希望任务在你关机后继续跑——可以把工作区放到一台长期在线的机器上,通过远程连接操作,本机只作为显示终端。整台机器放在机房、按月租用、远程连接的 Mac 就是这类做法的一种,适合需要长时间挂着 Claude Code 跑任务、又不想让本地机器一直开着的场景;权限配置本身还是要按上面的方式处理,换机器并不能替代白名单。

方案四:用通知代替盯屏

比「反复查看」更省事的是让任务主动叫你。Claude Code 的 hooks 机制可以在特定事件(例如需要确认、任务结束)触发时执行一条自定义命令,常见用法是:

  • 调用系统通知或终端 bell,本地即时提醒;
  • 通过 webhook / 消息机器人推送一条消息到手机;
  • 写入一个日志文件,配合 tail -f 或状态栏查看。

配置思路是在设置的 hooks 字段里挂上对应事件的命令,具体事件名、传参格式和超时限制随版本变化,建议照官方文档抄一份最小示例再改。需要注意:hook 命令本身也是在本机执行的,别在里面塞需要交互输入的东西,否则会把「等回车」的问题原样搬到 hook 里。

市面上也有一些第三方工具,提供进度面板、手机端查看和完成通知,思路与上面的 tmux + hook 组合类似。用不用取决于你是否愿意把会话交给第三方封装,涉及代码和凭据的场景建议先看清楚它把数据发到哪里。

把任务拆小,比任何开关都管用

权限配置解决的是「不被拦」,但长任务真正容易失败的地方在别处:上下文变长、方向跑偏、改到一半没人纠偏。实践下来更可靠的做法是:

  • 把一次性的大任务拆成 3~5 个可独立验收的小阶段,每阶段结束提交一次;
  • 每阶段结束让 agent 输出一份「改了什么、跑了什么、还剩什么」的摘要,你回来只读摘要;
  • 只在阶段之间需要人判断的地方停下来,而不是在每条命令上停下来。

一份可执行的检查清单

离开前花两分钟过一遍:

  • 常用命令已写入 allow 列表,破坏性命令已写入 deny 列表;
  • 任务被拆成有明确验收标准的阶段;
  • 工作区已提交或已打快照,可一键回滚;
  • 会话跑在 tmux / screen / 远程机器里,不依赖当前终端窗口;
  • 已配置完成或待确认的通知方式;
  • 若开启了跳过确认模式,确认环境隔离、无生产凭据、可随时重建;
  • 知道回来之后第一件事是看最后一行输出和 git status。

小结

「回来发现它还在等一个 yes」不是偶发故障,而是默认授权模型与长任务用法之间的错配。取舍上:日常开发优先用白名单收紧权限,可预期、可评审、风险可控;批量重构或跑测试这类低风险重复劳动可以放宽到自动接受编辑;跳过全部确认只在一次性隔离环境里作为最后手段。至于会话保活和通知,属于花十分钟配置、长期省心的基础设施,值得先做。

最后提醒一句:权限相关的参数名、配置字段、可用模式在持续迭代,动手前请以官方最新文档为准,别照抄几个月前的博客。

Claude Code长任务权限配置tmux无人值守