1. 项目概述:当 CLI 不再只是本地命令行,而成为你云端的“数字分身”
“Claude Code Routines:将 CLI 工具变成云端自动化引擎”——这个标题乍看像一句技术营销话术,但拆开来看,它精准击中了当前开发者工作流里一个真实、普遍且长期被忽视的痛点:我们每天在终端里敲下的那些git commit、npm run build、python scripts/check_docs.py,本质上都是高度结构化、可重复、有明确输入输出的“小任务”,却始终被困在本地机器上,一关机就停摆,一换环境就得重配,一要跨团队协作就得写文档、开会议、建共享账号。而 Routines 的核心价值,就是把这种“人肉 CLI 操作”升维成一种可托管、可编排、可触发、可审计的云端服务。它不是让你放弃终端,而是让终端成为你指挥云端引擎的控制台。关键词里的 “Claude Code” 是执行主体,“Routines” 是封装单元,“CLI” 是交互入口,“云端自动化” 是最终形态,“Webhook” 则是它与外部世界握手的关键协议。这背后没有魔法,只有三件东西:一个清晰定义的 Prompt(即“指令说明书”),一套受控的权限环境(即“工作间”),以及一个或多个触发条件(即“开关”)。我第一次用 Routines 实现“每日凌晨自动扫描所有 PR 中的 API 变更,并生成一份 Markdown 格式的兼容性报告推送到内部 Wiki”时,真正体会到什么叫“下班后代码还在替你打工”。它适合三类人:一是被重复性运维任务压得喘不过气的 DevOps 工程师;二是想把团队最佳实践固化为自动检查点的技术负责人;三是希望把个人知识沉淀(比如“每次发版前必须做的 7 项检查”)变成可复用资产的资深开发者。这不是一个替代 GitHub Actions 或 Cron 的工具,而是一个更高维度的“AI 驱动的自动化编排层”,它负责理解“意图”,而把“执行细节”交给已有的生态。
2. 核心设计逻辑:为什么是“云端”而非“本地”?为什么是“Routines”而非“脚本”?
2.1 云端执行:不是为了炫技,而是解决根本性约束
很多人第一反应是:“我的脚本在本地跑得好好的,为什么要搬到云端?” 这个问题问到了根子上。Routines 选择云端执行,绝非为了堆砌“云原生”的概念,而是直面 CLI 工具在本地运行时无法规避的硬性瓶颈。
首先是环境一致性。你在 Ubuntu 20.04 上调试通过的codex cli脚本,换到同事的 macOS 或 CI 服务器的 Alpine Linux 上,可能因为 OpenSSL 版本差异直接报错error:0308010c:digital envelope routines::unsupported。这个错误在 Node.js 17+ 环境中尤为常见,根源是底层 crypto 模块对旧版加密算法的支持策略变更。本地 CLI 的每一次npm install都是一次环境赌博。而 Routines 的云端环境由 Anthropic 统一维护和打补丁,你配置的environment variables和setup script会在一个干净、隔离、版本可控的容器中执行,彻底消除了“在我机器上能跑”的幻觉。我曾为一个需要调用playwright cli进行前端截图的 Routine 配置过环境变量PLAYWRIGHT_BROWSERS_PATH=/usr/local/browsers,这个路径在本地开发机上是/Users/me/.cache/ms-playwright,但在云端环境里,它被标准化为一个只读的、预装了 Chromium 和 Firefox 的路径。这种一致性,是任何.bashrc或Dockerfile都难以在团队层面 100% 保证的。
其次是资源与生命周期。一个需要遍历整个 Git 仓库历史、分析数千个提交的“技术债扫描” Routine,可能需要 15 分钟才能完成。如果你把它写成一个本地 Cron 任务,你的笔记本电脑就必须整晚不休眠、不锁屏、不关机。一旦网络中断,任务就失败。而云端 Routine 的执行完全脱离你的物理设备,它运行在 Anthropic 的弹性计算集群上,有独立的 CPU、内存配额和超时保护(默认 30 分钟,可申请延长)。更重要的是,它的“状态”是持久化的。你可以随时在 Web UI 里看到某次运行的完整日志、输入参数、输出结果,甚至可以点击“Re-run”按钮,用完全相同的上下文重新执行一次。这种可观测性和可重入性,是本地脚本日志文件永远无法提供的。
最后是安全边界的天然隔离。当你在本地终端运行claude cli --repo my-org/my-app --action update-deps时,这个命令拥有你当前 shell 的全部权限:它可以读取你的~/.ssh/id_rsa,可以访问你的~/.aws/credentials,甚至可以执行rm -rf /(虽然你不会这么干)。而 Routines 的权限模型是声明式的、最小化的。你只能在创建时,从一个白名单里勾选它能访问的 GitHub 仓库、能使用的 Slack 频道、能连接的数据库。它没有“家目录”的概念,没有sudo权限,它的网络访问也受到严格限制(默认仅允许出站 HTTPS,如需访问内网服务,必须显式配置 VPC 连接器)。这就像给一个外包工程师发了一张门禁卡,他只能进你指定的那间办公室,使用你指定的那台电脑,处理你指定的那份文件。这种“零信任”的权限设计,是保障自动化不变成“自动化灾难”的基石。
2.2 Routines 封装:从“命令”到“可交付产品”的范式跃迁
如果说“云端”解决了运行环境的问题,那么“Routines”这个概念,则解决了 CLI 工具的“可交付性”和“可协作性”问题。一个传统的 CLI 脚本,比如./check-pr.sh,它本质上是一个黑盒:它的输入(参数)、输出(stdout/stderr)、副作用(修改文件、发消息)、依赖(需要什么二进制、什么环境变量)都散落在代码的各个角落,只有作者自己心里有数。而一个 Routine,是一个自包含的、可描述的、可版本化的“自动化产品”。
一个 Routine 的五个核心组成部分,构成了它的 DNA:
Prompt(指令说明书):这是 Routine 的灵魂,不是一句简单的
# Review this PR,而是一份详尽的“运行手册”。它必须明确回答:输入数据从哪里来(例如,“从 GitHub Event Payload 中提取pull_request.head.sha和pull_request.base.repo.full_name”)?要执行什么逻辑(例如,“克隆仓库,检出该 SHA,运行npm test,并解析jest的 JSON 报告”)?成功的标准是什么(例如,“jest报告中的numFailedTests必须为 0,且numTotalTests大于 100”)?失败时该如何降级(例如,“如果npm test超时,不要报错,而是向 Slack 发送一条警告消息,并创建一个 draft PR,将本次失败的测试用例列表作为 PR 描述”)?输出到哪里(例如,“将完整的测试报告上传到 S3 存储桶my-org-reports的pr-checks/2024/06/15/PR-1234/路径下”)?我见过最优秀的 Prompt,写得像一份 RFC 文档,里面甚至包含了错误码定义和重试策略。Repositories(目标仓库):这是 Routine 的“工作对象”。它不是一个字符串,而是一个受控的引用。你不能在 Prompt 里写
git clone https://github.com/my-org/my-app.git,而是必须在 UI 或 CLI 中,从你已授权的 GitHub 仓库列表里选择my-org/my-app。这确保了 Routine 只能操作你明确授予它权限的代码,杜绝了脚本里硬编码的 URL 可能带来的越权风险。Cloud Environment(云端环境):这是 Routine 的“工作间”。它不是一个模糊的“Linux 服务器”,而是一个精确配置的沙箱。你可以指定基础镜像(如
ubuntu:22.04)、预装的工具链(如nodejs@18,python@3.11,playwright@1.39)、环境变量(如API_KEY=xxx,DEBUG=true)、以及一个setup script(一段在每次运行前都会执行的 Bash 脚本,用于安装特定的 Python 包或下载私有证书)。这个环境是 Routine 的“操作系统”,它决定了你能做什么,不能做什么。Connectors(连接器):这是 Routine 的“手脚”。它定义了 Routine 如何与外部世界交互。
GitHub Connector让它能读写 PR;Slack Connector让它能发消息;Linear Connector让它能创建 Issue。每个 Connector 都有精细的权限粒度。例如,GitHub Connector 不是简单地给你“读写权限”,而是让你选择“只读 Issues”、“可写 Comments”、“可创建 Draft PRs”,但不能“强制推送(force push)”。这种权限的“乐高化”拼装,是实现最小权限原则的关键。Triggers(触发器):这是 Routine 的“开关”。它定义了 Routine 在什么条件下启动。Schedule 触发器是“时间开关”,API 触发器是“HTTP 开关”,GitHub Events 触发器是“事件开关”。一个 Routine 可以同时拥有多个开关,比如一个“每日健康检查”Routine,既可以被
0 2 * * *的 Cron 定时触发,也可以被一个来自飞书机器人(Feishu Bot)的 Webhook 手动触发,用于在紧急故障时立刻拉起检查。这种多触发源的设计,让 Routine 成为了一个真正的“事件响应中心”。
把这五样东西打包在一起,你就得到了一个可以被命名(如pr-auto-review-v2)、被描述(如 “基于团队代码规范的 PR 初筛”)、被分享(通过链接或 YAML 导出)、被版本化(每次修改都生成新版本号)、被审计(所有运行记录都留存)的“自动化产品”。它不再是一个需要别人chmod +x并祈祷它能跑起来的脚本,而是一个可以直接部署、监控和管理的服务。
3. 实操核心环节:从零开始创建一个“飞书 Webhook 触发的 PR 自动审查” Routine
3.1 前期准备:CLI 工具链与身份认证
在动手创建之前,你必须确保本地 CLI 工具链是完备且可信的。这里要特别注意网络热词里反复出现的claude code安装、claude cli安装、windows安装claude code等问题。官方推荐的方式是通过npm安装@anthropic-ai/cli包,但这恰恰是问题的高发区。很多用户在 Windows 或某些 Linux 发行版上执行npm install -g @anthropic-ai/cli后,会遇到error: claude cli not found in path的错误。这通常不是 CLI 本身的问题,而是 npm 的全局 bin 目录没有被正确添加到系统的PATH环境变量中。
实操心得:我建议绕过全局安装,采用更可控的“局部安装 + 显式调用”方式。首先,在你的项目根目录下,初始化一个package.json(如果还没有的话):
npm init -y然后,将 CLI 作为项目的开发依赖安装:
npm install --save-dev @anthropic-ai/cli这样,CLI 的可执行文件会被安装到./node_modules/.bin/claude。接下来,你可以通过npx claude来调用它,npx会自动在node_modules/.bin中查找并执行。这种方式彻底规避了PATH配置问题,而且不同项目可以使用不同版本的 CLI,互不干扰。对于claude code desktop和cli版本的区别,我的经验是:桌面版是 GUI 入口,适合快速上手和调试;而 CLI 版本是生产环境的“真相之源”,所有 Web UI 的操作,最终都会转化为 CLI 命令。因此,掌握 CLI 是深入理解 Routines 的必经之路。
身份认证是另一个关键点。CLI 需要一个有效的 API Key 才能与 Anthropic 的云端服务通信。这个 Key 不是你在官网注册时的密码,而是在 Claude Code 官网 的Settings > API Keys页面里生成的。生成后,请务必将其保存在一个安全的地方(如密码管理器),并绝对不要将其硬编码在你的 Prompt 或脚本中。CLI 会从环境变量CLAUDE_API_KEY中读取它。所以,最安全的做法是,在你的终端会话中,临时设置这个变量:
export CLAUDE_API_KEY="sk-ant-api03-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"或者,更进一步,将其写入一个.env文件(并确保.env在.gitignore中),然后使用dotenv工具加载。记住,这个 Key 的泄露,等同于你的 GitHub 账号被他人掌控,因为它可以代表你执行所有你有权限的操作。
3.2 创建 Routine:Web UI 与 CLI 的双轨并行
创建一个 Routine 有两种主流方式:Web UI 和 CLI。Web UI 对新手友好,所见即所得;CLI 则更强大、更可编程、更适合 CI/CD 集成。我会以创建一个“飞书 Webhook 触发的 PR 自动审查”Routine 为例,展示两种方式的协同。
第一步:在 Web UI 中定义骨架
打开 Claude Code 的 Web 控制台,导航到Routines页面,点击Create new routine。你会看到一个表单,它对应着 Routine 的五大要素。
Name & Prompt: 给它起个名字,比如
feishu-pr-review。在 Prompt 编辑框里,粘贴一份精心编写的指令。下面是我实际使用的一个简化版 Prompt,它展示了如何将“飞书”和“GitHub”两个世界打通:# Role: Senior Code Reviewer for MyOrg Backend Team ## Task: Perform an automated, high-signal review of a GitHub Pull Request. ## Input: This routine is triggered by a Feishu Webhook. The webhook payload contains: # - `github_repo`: the full name of the GitHub repository (e.g., "my-org/backend") # - `github_pr_number`: the number of the pull request (e.g., 123) # - `feishu_chat_id`: the ID of the Feishu chat where the report should be sent. ## Steps: 1. Use the GitHub Connector to fetch the PR details for `github_repo` and `github_pr_number`. 2. Analyze the PR's title and description for common anti-patterns (e.g., "WIP", "DO NOT MERGE", missing Jira ticket). 3. Fetch the list of changed files. For each file that ends with `.py`, run a static analysis using `pylint` (pre-installed in the environment) and flag any `E` (error) or `F` (fatal) level issues. 4. If any critical issue is found, post a detailed comment on the PR using the GitHub Connector. 5. Compile a summary report and send it as a rich text message to the Feishu chat identified by `feishu_chat_id` using the Feishu Connector. ## Output: A Feishu message containing a summary table of findings and a link to the full PR review comment.Repositories: 在下拉菜单中,选择
my-org/backend。这是你授权给这个 Routine 访问的唯一仓库。Environment: 选择一个预设的
Python 3.11 + Pylint环境,或者创建一个新的。在Environment variables中,添加FEISHU_BOT_TOKEN=your_feishu_bot_token_here。这个 Token 是你在飞书开放平台创建机器人时获得的,它赋予了 Routine 向指定群聊发消息的能力。Connectors: 勾选
GitHub和Feishu。对于 GitHub,只授予Read Pull Requests和Write Pull Request Comments权限。对于 Feishu,只授予Send Messages to Chat权限。切记,不要勾选Write to GitHub Repositories,除非你真的需要它直接修改代码。Triggers: 这是关键。选择
API (Webhook)触发器。系统会为你生成一个唯一的 Webhook URL 和一个 Bearer Token。这个 URL 就是你要在飞书里配置的地址。Bearer Token 必须被当作最高机密来保管,它相当于这个 Routine 的“密码”。
完成表单后,点击Create。此时,一个名为feishu-pr-review的 Routine 就诞生了,但它还处于“未激活”状态,因为你还没有配置飞书端。
第二步:在飞书端配置 Webhook
登录飞书开放平台,进入你的应用管理后台。找到机器人->自定义机器人,创建一个新的机器人。在配置页面,找到Webhook 地址字段,将你在 Claude Code Web UI 中生成的 Webhook URL 粘贴进去。飞书会要求你设置一个Secret,这是一个额外的安全层,用于验证 Webhook 请求确实来自飞书。你需要在 Claude Code 的 Routine 设置中,找到Webhook Security部分,将这个Secret填入。这一步至关重要,它防止了恶意第三方伪造飞书请求来触发你的 Routine。
第三步:用 CLI 进行精细化配置与测试
现在,Routine 的骨架已经搭好,但 Web UI 的配置是“静态”的。为了让它真正“活”起来,你需要用 CLI 来注入动态参数。假设你想让飞书里的某个用户在群里发送/review pr 123,就能触发这个 Routine。这需要一个中间的飞书机器人服务来解析命令,并构造正确的 HTTP POST 请求。
首先,用 CLI 获取这个 Routine 的详细信息,确认其 ID:
npx claude routines list --json | jq '.routines[] | select(.name == "feishu-pr-review") | .id'假设返回rt-abc123。
然后,你可以用 CLI 来手动触发一次测试运行,验证整个链路是否通畅:
curl -X POST \ -H "Authorization: Bearer <your-bearer-token>" \ -H "Content-Type: application/json" \ -d '{ "github_repo": "my-org/backend", "github_pr_number": 123, "feishu_chat_id": "oc_abcdef1234567890" }' \ https://api.anthropic.com/v1/routines/rt-abc123/fire这个curl命令模拟了飞书机器人发来的请求。如果一切顺利,你将在 Web UI 的Runs页面看到一次新的运行记录,状态为Succeeded,并且你指定的飞书群聊里会收到一条格式精美的审查报告。如果失败了,日志会清晰地告诉你是在哪一步卡住了:是 GitHub Token 权限不足?是 Feishu Bot Token 过期?还是pylint分析时找不到某个 Python 包?这种端到端的可观测性,是本地脚本调试梦寐以求的能力。
3.3 关键配置详解:Prompt、环境变量与连接器的协同艺术
一个 Routine 的成败,90% 取决于 Prompt 的质量,而剩下的 10%,则取决于环境变量和连接器的精准配置。这三者不是孤立的,而是一个精密咬合的齿轮组。
Prompt 的编写哲学:从“需求”到“可执行 Runbook”
很多新手的 Prompt 写得像一句需求:“帮我看看这个 PR 有没有问题。” 这在人类对话中没问题,但在 AI 自动化中,它是灾难的开始。AI 不会“帮你”,它只会“执行”。因此,Prompt 必须是一份无歧义、有边界、可验证的 Runbook。
无歧义:避免使用“好”、“坏”、“合理”等主观词汇。要把它们翻译成可量化的规则。例如,“好”的代码风格,应该定义为“符合 PEP8 规范,且
pylint得分大于 9.0”。有边界:明确告诉 AI 它的“能力范围”。例如,“你只能使用
pylint进行静态分析,禁止使用bandit或safety,因为这些工具不在当前环境中。” 这句话看似多余,但能有效防止 AI 在“思考”时产生幻觉,去调用一个根本不存在的命令。可验证:每一个步骤的输出,都必须有明确的成功/失败判定标准。例如,“步骤 3 的成功标准是:
pylint命令的退出码(exit code)为 0,且 stdout 中不包含E[0-9]{3}或F[0-9]{3}的匹配项。”
我在编写一个“依赖安全扫描”Routine 的 Prompt 时,就加入了这样的验证逻辑:
# Step 2: Run `pip-audit` to scan for vulnerable dependencies. # Expected Success: Command exits with code 0 AND stdout contains "No known vulnerabilities found". # Expected Failure: Command exits with code 1 AND stdout contains "Found X known vulnerabilities". # If command fails with code 2 (network error), retry once with `--timeout 60`.这种写法,让 Routine 的行为变得完全可预测和可测试。
环境变量:不只是“配置”,更是“契约”
环境变量在 Routine 中扮演着双重角色:一是传递敏感信息(如FEISHU_BOT_TOKEN),二是定义运行时的“契约”。例如,你可以定义一个MAX_FILE_SIZE_MB=5的环境变量,然后在 Prompt 中写:“如果任何一个被修改的 Python 文件大小超过MAX_FILE_SIZE_MBMB,则跳过对该文件的pylint分析,并在报告中注明原因。” 这样,你就可以通过修改环境变量,来动态调整 Routine 的行为,而无需每次都去重写 Prompt。这是一种非常强大的“配置即代码(Configuration as Code)”实践。
连接器:权限的“最小化”与“组合化”
连接器的配置,是安全性的最后一道防线。我有一个血泪教训:早期我为了图省事,在一个 Routine 中勾选了GitHub: Full Access,结果在一次 Prompt 的误写中,AI 错误地理解了指令,执行了git push --force origin main,导致主分支的历史被重写。从此,我给自己立下铁律:永远只授予连接器完成其单一任务所必需的、最窄的权限。对于“PR 审查”,只需要Read PRs和Write Comments;对于“文档同步”,只需要Read Files和Write Files(且限定在docs/目录下);对于“告警通知”,只需要Send Messages。这种“组合化”的权限授予,让你可以像搭积木一样,构建出功能复杂但权限清晰的自动化流程。
4. 常见问题与实战排查:从error:0308010c到 Webhook 超时的全链路诊断
4.1 环境与依赖问题:error:0308010c的根源与解法
error:0308010c:digital envelope routines::unsupported这个错误,是网络热词中出现频率最高的报错之一,也是新手最容易陷入的“坑”。它几乎总是出现在使用codex cli或其他基于 Node.js 的 CLI 工具时。它的字面意思是“数字信封例程不支持”,但其背后的真实含义是:你正在使用的 Node.js 版本,其内置的 OpenSSL 库,拒绝加载或使用一个它认为不安全或已废弃的加密算法。
这个错误的典型触发场景是:你的本地 Node.js 版本是 18.x 或 20.x,而你试图运行一个为 Node.js 16.x 编写的、依赖了旧版crypto模块 API 的脚本。Node.js 17+ 为了提升安全性,移除了对md4、md5、sha1等弱哈希算法的默认支持,并改变了createCipher/createDecipher等函数的行为。
排查与解决路径如下:
确认 Node.js 版本:首先,在终端中运行
node --version。如果显示v18.17.0或更高,那么问题极大概率在此。检查 CLI 工具的兼容性:查阅
@anthropic-ai/cli的官方文档或 GitHub Issues,确认其最新版本是否已适配 Node.js 18+。如果尚未适配,官方通常会提供一个临时的环境变量解决方案。终极解决方案:使用兼容模式。在运行 CLI 命令前,设置以下环境变量:
export NODE_OPTIONS=--openssl-legacy-provider npx claude routines list这个
--openssl-legacy-provider标志,会强制 Node.js 加载一个兼容旧版算法的 OpenSSL 提供者。这是目前最广泛、最可靠的解决方案。注意,这个环境变量只应在运行claudeCLI 时设置,而不应永久添加到你的~/.bashrc中,因为它会降低整个 Node.js 环境的安全性。预防胜于治疗:在你的 Routine 的
Cloud Environment配置中,明确指定一个经过充分测试的 Node.js 版本,例如nodejs@16.20.2。这样,无论你的本地开发环境如何变化,云端的执行环境始终是稳定和可预测的。这正是 Routines “环境一致性”优势的直接体现。
4.2 Webhook 问题:从飞书配置到 Claude 接收的全链路追踪
Webhook 是 Routines 与外部世界沟通的桥梁,但这座桥也最容易出现“信号不良”。最常见的问题是:飞书那边显示“消息已发送”,但 Claude Code 的 Web UI 里却没有任何运行记录。这通常不是单点故障,而是一个涉及三方(飞书、网络、Claude)的链路问题。
系统化的排查清单:
| 步骤 | 检查项 | 如何验证 | 说明 |
|---|---|---|---|
| 1. 飞书端 | Webhook URL 是否正确? | 在飞书机器人配置页,复制 URL,粘贴到浏览器地址栏,看是否返回405 Method Not Allowed(正常)或404 Not Found(URL 错误)。 | 405表示 URL 正确,但浏览器用了 GET 方法;404表示 URL 根本不存在,可能是你在 Claude UI 中创建后又删除了,或者复制时漏掉了字符。 |
| 2. 飞书端 | Secret 是否匹配? | 在飞书配置页的Security Settings中,找到Verification Token和App Secret。在 Claude UI 的 Routine 设置中,找到Webhook Security,确认Secret字段的值与飞书的Verification Token完全一致(区分大小写)。 | 这是最常见的配置错误。飞书会用这个Secret对请求体进行签名,Claude 会用它来验签。不匹配,请求会被直接拒绝。 |
| 3. 网络层 | 请求是否到达 Claude? | 在 Claude UI 的Runs页面,切换到All Runs标签页,查看是否有Failed状态的记录。如果有,点开详情,看错误类型是Webhook Signature Invalid(验签失败)还是Webhook Payload Malformed(JSON 格式错误)。 | 如果连Failed记录都没有,说明请求根本没到达 Claude 服务器,问题出在飞书或网络防火墙。 |
| 4. Claude 端 | Bearer Token 是否有效? | 在 CLI 中,尝试用curl命令,不带飞书的签名,直接用 Bearer Token 调用fire端点。如果成功,说明 Claude 端服务正常;如果失败,检查 Token 是否过期或被撤销。 | 这一步可以快速隔离问题:如果curl成功,说明问题一定在飞书的签名或 payload 构造上。 |
一个真实的 payload 构造案例:
飞书发送的 Webhook 请求体(payload)必须是一个合法的 JSON 对象。很多飞书开发者会错误地将整个飞书事件对象原封不动地转发给 Claude。这是不对的。Claude 的 Webhook 端点期望的,是一个精简的、只包含 Routine 所需字段的 JSON。
错误的 payload(包含了飞书的所有元数据):
{ "schema": "2.0", "header": { ... }, "event": { "type": "message", "sender": { ... }, "message": { "text": "/review pr 123" } } }正确的 payload(由飞书机器人服务解析后构造):
{ "github_repo": "my-org/backend", "github_pr_number": 123, "feishu_chat_id": "oc_abcdef1234567890" }这个转换过程,必须由你自己的飞书机器人后端服务来完成。它需要解析飞书的原始事件,提取出用户指令中的关键参数,然后构造一个符合 Claude API 规范的、轻量级的 JSON。
4.3 权限与连接器问题:“GitHub commits 以你的账号出现”的深层含义
官方文档中有一句非常重要的话:“Routine 做出的动作会使用你的账号身份。比如:GitHub commits 和 PR 以你的 GitHub 用户出现。” 这句话初看是功能描述,细想却是安全警示。它意味着,Routine 不是一个匿名的、无主的机器人,而是一个完全代表你本人的“数字分身”。你在 GitHub 上拥有的所有权限,它都拥有;你在 Slack 上能发消息的频道,它都能发。
这带来了一个关键的排查思路:当一个 Routine 的 GitHub 操作失败时,首要怀疑的不是 Routine 本身,而是你自己的 GitHub 账号权限。
检查 GitHub Personal Access Token (PAT):Claude Code 是通过你授权的 GitHub PAT 来访问仓库的。请登录 GitHub,进入
Settings > Developer settings > Personal access tokens > Tokens (classic),找到你授权给 Claude Code 的那个 Token。检查它的过期时间,以及它所拥有的 scopes(权限范围)。对于 PR 审查,至少需要public_repo(如果是私有仓库,则是repo)和workflow(如果需要触发 Actions)。检查仓库的 Branch Protection Rules:即使你的 PAT 权限足够,GitHub 的分支保护规则也可能拦截 Routine 的操作。例如,如果
main分支启用了“Require pull request reviews before merging”,那么 Routine 创建的 Draft PR 是可以的,但如果你想让它直接git push到main,就会被拒绝。你需要在 GitHub 仓库的Settings > Branches > Branch protection rules中,为 Routine 使用的账号(即你的账号)添加一个Bypass pull request requirements的例外。检查连接器的权限粒度:回到 Claude UI 的 Routine 设置,在
Connectors部分,再次确认你为 GitHub Connector 勾选的权限。如果你只勾选了Read Pull Requests,那么它就不可能执行Write Pull Request Comments。这个权限列表是实时生效的,修改后无需重启,下次运行即生效。
提示:在 Routine 的开发和测试阶段,我强烈建议开启
Draft PR模式。即在 Prompt 中,所有写操作(如创建 PR、提交代码)都明确指定为draft: true。这样,即使 Prompt 出了错,它创建的也是一个草稿 PR,不会对主分支造成任何影响。等你确认逻辑完全正确后,再将draft: false。
4.4 运行时问题:日志、超时与幂等性设计
当 Routine 运行起来后,你面对的将是另一类问题:它运行了,但结果不对;它运行了,但耗时太久;它运行了,但重复执行了两次。
日志是唯一的真相:Claude UI 的
Runs页面提供了完整的、按时间戳排序的执行日志。它不仅包含你console.log的输出,还包含系统级别的日志,如“Starting setup script...”、“Cloning repository my-org/backend...”、“Running pylint on file api/handler.py...”。当结果异常时,不要猜测,直接滚动日志,找到第一个ERROR或WARNING标记,那里就是问题的源头。我曾遇到一个 Routine 总是报告“找不到文件”,日志显示它克隆仓库后,cd进入的目录是my-org-backend,而不是预期的backend。原因是 Prompt 里写的git clone命令没有指定--depth 1,导致它克隆了整个组织的仓库,而backend只是其中一个子目录。修复方法很简单:在setup script中,添加cd backend。超时是隐形的杀手:Routines 默认超时时间为 30 分钟。对于一个需要分析大型单体应用的 Routine 来说,这可能不够。你可以在创建 Routine 时,在
Environment配置中,找到Timeout (seconds)字段,将其修改为3600(1 小时)。但更优雅的方案是,在 Prompt 中加入超时控制逻辑。例如,使用timeout命令来包装一个可能很慢的命令:# Step 3: Run the heavy linting job. If it takes more than 5 minutes, abort and report. timeout 300 pylint --output-format=json api/ || echo "Pylint timed out after 5 minutes."幂等性是可靠性的基石:Webhook 机制本身是“尽力而为”的,网络抖动可能导致同一个事件被飞书重复发送多次。如果你的 Routine 没有幂等性设计,就可能出现“同一份 PR 被审查了三次,发了三条重复的飞书消息”。实现幂等性的最简单方法,是在 Prompt 的开头,加入一个“防重”检查:
# Step 0: Check for idempotency. Look for a comment from this routine on the PR. # If found, exit immediately with success. GITHUB_COMMENT_ID=$(