# 让 Claude 半夜自己干活,只有两条路
**作者**: 老金
**日期**: 2026-07-29T08:38:16.000Z
**来源**: [https://x.com/freeman1266/status/2082385205088944327](https://x.com/freeman1266/status/2082385205088944327)
---

看到两篇文章,发现它们其实是同一道题的两个答案,而且答得完全相反。
一篇是个人博客。作者翻出一台闲置 Mac,抹盘,建一个不登 Apple ID 的干净账号,打开 SSH,配好免密 sudo,把 Claude Code 装上去,所有会话统一带 --dangerously-skip-permissions 跑。他管这台机器叫 the box。
另一篇是国内一个独立开发者的实测,把 Claude 挂进 GitHub Actions 审 PR。他的做法正相反:工具收成白名单,只给 Read,Grep,Glob,连 Edit 都不给;容器 --network none 直接断网;单次预算 --max-budget-usd 0.50 兜底。
一个人在拼命放权,一个人在拼命收权。可他们想干的事一模一样:让 Claude 在自己睡觉的时候干活。
## 门槛从来不是"跑起来"
技术门槛只有一行:
claude -p "分析 src/ 目录的安全漏洞"
-p 是 --print 的短写,跑完直接退出,不进交互式 REPL。到这儿就结束了。
真正的门槛在下一句:你敢去睡吗。
想清楚这件事得先想清楚交互式模式到底在干什么。你每次按下的那个回车都是一次授权判断:它要不要动这个文件、要不要跑这条命令、要不要装这个包,全靠你那一下。这个权限系统长在你手上,所以你从来没意识到它存在。
无人值守就是把回车键拿掉。拿掉之后那个位置不能空着,得有别的东西补上。
补的方式只有两种:换一台机器,或者换一套参数。
## 路线一:换一台没什么可失去的机器
第一篇文章的思路很干脆——不去限制 agent 能干什么,而是让它干什么都不要紧。作者原话是"在一台没什么可失去的机器上运行拥有广泛权限的代理更安全"。

他为此明确拒绝了容器方案,理由有两条,都挺实在:容器仍然跑在你的宿主机上,它发的网络请求还是从你的 IP 出去;而且容器里跑不了只有 macOS 才有的东西——他想让 agent 开 Unity 做游戏开发,想让它点击拖拽真实的 App 界面,容器给不了。
这条路的关键动作按顺序是:抹盘 → 建一个不登 Apple ID 的本地管理员账号 → sudo systemsetup -setremotelogin on 开 SSH → 写 /etc/sudoers.d/ 免密 sudo → ssh-copy-id 配免密登录 → 装 Claude Code。
真正值钱的是里面几个你自己摸绝对要栽的坑:
它会睡过去。macOS 插着电闲置十分钟也照样睡,一睡就断网,你半夜派的活直接停在那儿。三条命令按住:
```
sudo pmset -c sleep 0 # 插电时永不系统睡眠
sudo pmset -c disablesleep 1 # 合盖也不睡(翻盖模式)
sudo pmset -c displaysleep 0 # 显示器保持开启
```
PATH 要写 .zshenv,不是 .zshrc。因为 .zshenv 每个 zsh 都读,包括非交互式的那种——你从源机 ssh 目标机 'claude -p ...' 走的就是非交互式,写在 .zshrc 里它找不到 claude。
被授权的是 tmux,不是 claude。 这条最反直觉。你想让盒子上的 Claude 截屏、点鼠标,macOS 把屏幕录制和辅助功能权限绑在 GUI 登录会话上,SSH 进程摸不到显示器。变通办法是让一个 LaunchAgent 在 GUI 会话内部维持一个固定 socket 的 tmux 服务器,claude 作为它的子进程跑,于是继承了 GUI 会话。而 macOS 把捕获权限归给链条上的"负责进程"——所以你要去系统设置里给 /opt/homebrew/bin/tmux 授权,不是给 claude。授完还得重启 tmux 服务器,因为进程在启动时就缓存了自己的权限状态。
GitHub 用小号。作者建议盒子上 gh auth login 登一个单独的 GitHub 账户,不是主账户。这一条我强烈同意,它是这套方案里最便宜的一道保险。
出口 IP 也顺手分开。他在盒子上跑 Proton VPN,让 agent 的流量不从自己家 IP 出去。
配完之后他有两个我挺眼馋的用法。一个是 clip send / clip get,拿 pbcopy 和 pbpaste 对着 SSH 管道一接,剪贴板就在两台机器之间走,端到端,不过第三方服务,图片也能传。另一个是从手机控制——claude remote-control,路上用 Claude App 就能给盒子派活。
还有个更狠的:因为盒子上所有会话都挂在同一个 tmux socket 上,你主力机上的 Claude 可以直接 send-keys 给盒子上的 Claude 派活、再 capture-pane 读回复。agent 对 agent。
```
ssh <user>@<host> "tmux -S /tmp/cc-tmux.sock send-keys -t <session> '切到 main 拉一下,PR #4 已经合了' Enter"
sleep 2
ssh <user>@<host> "tmux -S /tmp/cc-tmux.sock send-keys -t <session> Enter"
ssh <user>@<host> "tmux -S /tmp/cc-tmux.sock capture-pane -t <session> -p" | tail -30
```
那两个 Enter 不是笔误。长提示里跟文本同批发过去的 Enter 不算提交,得再补一下。
## 路线二:机器动不了,那就收权限
第二篇的处境不一样。他要让 Claude 在 GitHub Actions 里审 PR,那台 runner 上有他的仓库、他的 secrets、他的合并权限——机器换不掉。
所以他反过来做,把交互式里那些"人按回车"的隐式约定全部显式化成参数:
```
# 输出格式
claude -p "审查 PR" --output-format json # 给机器解析
claude -p "分析架构" --output-format stream-json # 一行一事件,长任务实时盯
# 成本护栏
claude -p "审查代码" --max-turns 5 --max-budget-usd 0.50
# 安全边界
claude -p "审查代码变更" --allowedTools "Read,Grep,Glob" # 只读,最安全
claude -p "检查 git 历史" \
--allowedTools "Read,Grep,Glob,Bash(git log *),Bash(git diff *)" # 细粒度白名单
# 执行控制
claude -p "代码审查" --model claude-sonnet-5 --fallback-model claude-haiku-4-5
```

--allowedTools "Read,Grep,Glob" 这一条是整条路线的地基。审查任务本来就不需要写文件,那就一个写权限都别给。这比任何"请不要修改代码"的提示词都硬——提示词它可以不听,工具不给它就是真的没有。
他还有几笔账我觉得值得抄走:
一是 concurrency 必配。同一个 PR 连推三个 commit,不配这段就是三份账单:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
二是分级跑。阶段一用 Haiku 查格式,needs 依赖它过了,阶段二才上 Sonnet 做安全扫描——格式都过不了的 PR 没必要烧贵模型的钱。他报的数是一条 PR 从单一强模型全量审查的 ~0.15 美元压到 ~0.06 美元。单条审查落在 0.03~0.08美元这个区间。
三是 CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1。一个变量关掉自动更新、遥测和错误上报,否则 CI 跑着跑着 Claude 自己开始检查更新,日志里全是噪音。
四是 --fallback-model。主模型 429 的时候自动切便宜的那档,不至于让整条管道挂在过载上。
## 两条路,一把尺子
换机器收权限手段隔离宿主白名单工具权限姿态全开(--dangerously-skip-permissions)最小(连 Edit 都不给)前期成本一台闲置 Mac + 半天配置十几行 YAML边际成本几乎为零(吃订阅额度)按次计费,需要预算护栏适合探索性、要装东西、要点 GUI 的活结论明确、可重复、要卡门禁的活失败长什么样盒子被搞坏,重装报告不准,人工复核
两条路看着不像,其实用的是同一个公式:
> 爆炸半径 = 这台机器上你丢不起的东西 × agent 能碰到它的概率

换机器那条路把第一项清零,所以它敢完全不管第二项。收权限那条路第一项动不了,只能死磕第二项。
于是最危险的那种状态就自己浮出来了:第一项和第二项都拉满——在你自己的主力机上开 --dangerously-skip-permissions。那台机器上有你的 SSH 私钥、云控制台的登录态、生产库连接串、没提交的代码、家人的照片。
这是现在绝大多数人的状态。包括我。
## 拿这把尺子量我自己
第一篇里有一节标题就叫"为什么不使用 OpenClaw 之类的工具",我看到有点被点到,因为我这个仓库的自动化现在就是 OpenClaw 在跑——每天的 translate、ingest、compile 都是它触发的,我没用 launchd 也没写 cron。
作者不用它的理由是三条:想用 Claude Code 的完整最新功能,想从手机控制,想吃订阅额度而不是 API 计费。三条我都认,但这不改变我的选择——因为按上面那把尺子量,我这套东西根本不在同一个风险档位上。
它跑在我主力机上,动的只有这个仓库的 markdown 文件,没有 secrets,没有发布权限。最坏情况是把 wiki 写脏,git checkout . 一把回滚。第一项接近零,所以它天然落在安全那边,我不需要为它做任何额外的事。
真该动的是另一个:我每天手工敲的那些 Claude Code 会话。同一台机器,同一堆私钥,权限还开得更大。我一直觉得"有我盯着"就是安全,可我盯着的方式,就是那个我从来没写下过标准的回车键。
## 无人值守真正的账,记在别处
上周那篇《如何给 Loop 造个验证器》里我钉了一条:验证器的价值全在于它不听 agent 的话。无人值守把这件事从"最好有"变成了"必须有"——你不在场,就没有"中途叫停"这个选项了,只剩事前限权和事后验证两道。
第二篇里那个 Gate 就是在做事后那道:
```
- name: Gate on critical issues
run: |
if echo "$RESULT" | grep -qi "critical"; then
echo "::error::Critical issues found"
exit 1
fi
```
评审结果里出现 critical 就让 CI 挂掉。它能真的拦住 merge,而不只是产一份等人去读的报告,方向完全对。不过 grep -qi critical 这个实现挺脆,Claude 换个措辞写成"严重问题"就漏了。真要用,让它用 --json-schema 输出结构化的 severity 字段,卡枚举值,别卡关键词。
另一笔账记在《AI 编码的认知债》那边。无人值守最贵的代价不是它搞坏什么,是你不知道它干过什么——早上起来只看到一个结论。所以下面这行不是运维洁癖,是在还这笔债:
claude -p "任务" --output-format json | tee -a ~/claude-audit.jsonl
谁、什么时候、跑了多少轮、花了多少钱,全在这一行里。配上 stream-json 实时盯长任务,你至少还留着一条能回去读的轨迹。
## 今天就能动手的几件事
1. 先列单子,再挑教程。打开你现在跑 Claude 那台机器,列出上面所有你丢不起的东西:SSH 私钥、云控制台登录态、生产库连接串、未提交的代码、私人照片。这张单子决定你走哪条路——它长就去收权限,它空就可以放权限。反过来先挑教程,两条路你都会配错。
2. 今晚就能有的最小无人值守,不用买机器。找一件你已经在手工重复做的活,用只读白名单接上去。比如我这个仓库的:
```
claude -p "读 raw/_registry.md 和 me.md,列出所有 status 为 pending 的素材,按我的关注主题排优先级,只输出前三条和理由" \
--output-format json \
--allowedTools "Read,Grep,Glob" \
--max-turns 5 \
--max-budget-usd 0.10 \
| jq -r '.result'
```
跑通了再谈自动化。这条命令里没有一个工具能改你的文件,所以你现在就可以按回车。
1. 把审计打开。任何无人值守的任务,输出一律走 json,一律 tee 落盘。这条现在不做,等你想查的时候已经没东西可查了。
2. 要走放权那条路,记住授权对象是 tmux。屏幕录制和辅助功能都授给 tmux 二进制,授完重启 tmux 服务器。我把这条单独列出来,是因为它是整篇指南里唯一一个你自己摸半天也摸不出来的地方。
那份标准得先写出来:哪些命令我一向直接放过、哪些一定要先看一眼 diff、哪些不管多晚都该停下来等我。我按了几万次回车,依据的规则一条都没落在文件里,全在手上。
机器怎么配、参数怎么给,都是有了这份东西之后的下游活。
## 相关链接
- [@freeman1266](https://x.com/freeman1266)
- [684](https://x.com/freeman1266/status/2082385205088944327/analytics)
- [Upgrade to Premium](https://x.com/i/premium_sign_up)
- [4:38 PM · Jul 29, 2026](https://x.com/freeman1266/status/2082385205088944327)
- [684 Views](https://x.com/freeman1266/status/2082385205088944327/analytics)
- [View quotes](https://x.com/freeman1266/status/2082385205088944327/quotes)
---
*导出时间: 2026/7/30 10:51:49*