首页 › tutorials › 斜杠命令工厂:把提示词压成指令

概述

如果你发现自己每天都要把同一段"请按团队规范 review 这段代码"的提示词手动敲进 Claude Code,那本教程就是写给你的。本教程聚焦 自定义斜杠命令(custom commands) 这一支自动化主线:从一个 .md 文件起步,逐步加上参数、动态注入、工具预授权、子代理隔离,最后用无头 -p 模式把同一条指令批量喂给成百上千个文件或 PR。学完后你能把任意重复提示词"压"成一条 /命令,并在 CI 里无人值守地跑起来。适合中高级开发者、工程效能团队与 CI 维护者。

前置条件

正文

步骤 1:先划清四件事的边界

写命令之前,先分清四个"会改 Claude 行为"的配置,免得用错工具:

特性 作用方式 什么时候用
斜杠命令(本教程主角) 显式 /name 触发,单次注入提示词 重复的多步流程:评审、提 PR、发版说明
Skill(自动触发) description 命中时由 Claude 自动加载 需要上下文判断才该跑的知识型流程
CLAUDE.md 每轮都在上下文里的项目事实 编码规范、目录约定、固定事实
Output style 改系统提示词,影响每轮的"语气/格式" 永远先画图、永远输出 JSON

一句话记法:CLAUDE.md 是"常识",Skill 是"能力",斜杠命令是"动作",Output style 是"口吻"。动作型流程(带副作用、有明确触发点)就该做成斜杠命令,并关掉自动触发,避免 Claude 自作主张。

步骤 2:第一个命令——从 5 行 Markdown 开始

在你的项目根目录建一个命令文件:

mkdir -p .claude/commands

写入 .claude/commands/explain.md:

Explain the following file for a new team member. Focus on:
1. What this module is responsible for
2. Its public entry points
3. Any non-obvious side effects

File: $ARGUMENTS

操作:保存后无需重启——Claude Code 会监听命令目录,当前会话内即生效。在交互界面输入:

/explain src/auth/login.ts

预期结果:$ARGUMENTS 被替换成 src/auth/login.ts,Claude 实际收到"File: src/auth/login.ts",并按三点结构产出说明。若忘了写 $ARGUMENTS,你输入的参数会以 ARGUMENTS: src/auth/login.ts 追加到末尾,仍可见。

常见问题: - 输入 / 看不到我的命令:确认文件在 .claude/commands/(项目级)或 ~/.claude/commands/(用户级),且扩展名是 .md。 - 中文文件名/含空格路径:用引号包裹,如 /explain "src/用户 模块/auth.ts"。

步骤 3:用 frontmatter 给命令"加装备"

裸 Markdown 只是个提示词模板。真正的威力来自顶部 YAML frontmatter。把 explain.md 升级成 lint-review.md:

---
description: Review uncommitted changes against team lint rules. Use when the user asks to review their diff or before committing.
argument-hint: [optional: file or directory]
disable-model-invocation: true
allowed-tools: Read Grep Bash(git diff *) Bash(git status *)
model: inherit
---
## Current diff
!`git diff HEAD -- $ARGUMENTS`

## Your task
Review the diff above. For each finding, output:
- **Severity**: blocker | major | minor | nit
- **Location**: file:line
- **Issue**: one sentence
- **Fix**: concrete suggestion

Do not comment on style already enforced by our linter.

逐字段解读:

预期结果:/lint-review 后 Claude 直接读 diff 并按四级严重度输出表格,期间不再弹 git diff 的权限确认框。

常见问题: - allowed-tools 没生效:项目级命令需先通过工作区信任(workspace trust)对话框;审阅陌生仓库的 .claude/commands/ 再决定是否信任,因为命令能给自己授予较宽的工具权限。 - YAML 写错:Claude Code 会用空元数据加载命令体,/lint-review 仍可手动跑,但 description 为空导致无法自动触发。加 --debug 启动可看到解析错误。

步骤 4:位置参数与命名参数

$ARGUMENTS 是"全部参数原样"。要按位取值,用 $0 $1 $2(0 起)或 $ARGUMENTS[0]:

---
description: Migrate a component between frameworks
argument-hint: [component] [from] [to]
---
Migrate the $0 component from $1 to $2. Preserve all behavior and tests.

调用 /migrate SearchBar React Vue → $0=SearchBar $1=React $2=Vue。含空格的值用引号:/migrate "User Card" React Vue。

更可读的方式是命名参数,在 frontmatter 声明:

---
description: Scaffold a new endpoint
arguments: [resource, version]
---
Create a $version endpoint for the "$resource" resource…

调用 /scaffold-order v2 → $resource=order $version=v2。命名参数让模板自文档化,团队协作时更不易传错。

步骤 5:动态注入——把实时数据塞进提示词

!反引号`` 语法会在命令内容发给 Claude 之前先执行 shell,把输出原地替换进去。这是命令"活起来"的关键。看一个 PR 摘要命令:

---
description: Summarize the current pull request
context: fork
agent: Explore
allowed-tools: Bash(gh *)
---
## PR context
- Diff: !`gh pr diff`
- Comments: !`gh pr view --comments`
- Changed files: !`gh pr diff --name-only`

## Task
Summarize this PR in 3 bullets, then list 2 risks.

执行顺序:①每条 !cmd 立即跑;②输出替换占位符;③Claude 只看到最终渲染好的文本。多行命令用 ```! 围栏块。

安全开关:在 settings 里设 "disableSkillShellExecution": true 可全局禁用注入,命令里的 !cmd 会被替换成 [shell command execution disabled by policy]。给不可信仓库配这个。

常见问题: - !cmd 没执行:! 必须在行首或空白之后。KEY=!cmd 这种紧跟字符的写法会被当字面量。 - 输出爆上下文:大 diff 全量注入会吃掉 token。用 --name-only 或 head 先裁剪。

步骤 6:放哪儿、叫什么——作用域与命名空间

位置 路径 作用范围 调用名
用户级 ~/.claude/commands/foo.md 你所有项目 /foo
项目级 .claude/commands/foo.md 本项目 /foo
嵌套(monorepo) apps/web/.claude/commands/deploy.md 该子包 /apps/web:deploy

优先级:同名时项目级覆盖用户级。monorepo 里,根目录的 /deploy 与子包的 /apps/web:deploy 可并存,Claude 会按你正编辑的文件所在目录选用合适变体。

实战建议:团队共享的命令(发版、评审规范)提交进项目 .claude/commands/ 并纳入 git;个人习惯(个人快捷生成)放 ~/.claude/commands/,不污染团队仓库。

步骤 7:用 output style 让输出"机器可读"

当命令要进 CI 或被下游脚本消费时,输出必须稳定。与其在命令里反复强调"输出 JSON",不如做一个 output style 一次性约束所有响应。新建 .claude/output-styles/json-strict.md:

---
name: json-strict
description: Always respond with a single valid JSON object, no prose
keep-coding-instructions: false
---
Respond ONLY with one valid JSON object. No markdown fences, no commentary.
If asked to review code, use this schema:
{ "findings": [ { "severity": "...", "file": "...", "line": 0, "issue": "...", "fix": "..." } ] }

要点: - keep-coding-instructions: false 表示完全替换系统提示词——命令不写代码时用这个,省 token 又避免默认编码指令干扰。 - 临时启用:/config → Output style 选 json-strict,或直接在 settings 写 "outputStyle": "json-strict"。 - Output style 在会话开始时读入系统提示词,改完要 /clear 或新开会话才生效。

这样 /lint-review 配 json-strict 后,输出就是干净 JSON,可直接 jq 解析。

步骤 8:无头 -p 模式批量驱动命令

这是把"斜杠命令"升级为"批量引擎"的一步。claude -p "..." 以非交互方式运行、打印结果到 stdout 后退出,天然适合 shell 循环与 CI。

单文件无头调用:

claude -p "$(cat .claude/commands/lint-review.md)" \
  --output-format json \
  --max-turns 4 \
  --permission-mode acceptEdits \
  < src/auth/login.ts > review-login.json

关键标志: - --output-format json:结构化结果,含每轮消息与工具调用,便于解析。 - --max-turns 4:自动化护栏,限定轮次,防 runaway。 - --permission-mode acceptEdits:自动接受文件编辑(CI 场景)。只读场景用 default 或配 --allowedTools 收紧。

说明:无头模式里最稳的复用方式是把命令文件内容当 prompt 传入(如上 $(cat ...)),这样不依赖交互式 / 解析,行为可复现。交互场景则直接 /lint-review。

对一批文件批量跑:见下一节实战。

常见问题: - 输出里混了工具调用日志:用 --output-format json 后只取 .result 字段,或 --output-format text 只要最终文本。 - 跑着跑着卡住烧钱:务必设 --max-turns,并在 CI 里加 timeout。 - 想接着上次继续:claude -p -c "继续" 用 --continue/-c 续接最近会话,--resume <id> 指定会话。

实战案例:团队评审命令库 + 批量无头引擎

目标:建三条命令 + 一个批量脚本,对本次改动涉及的所有文件自动跑评审并汇总。

1) 三个命令(放入项目 .claude/commands/):

/lint-review(见步骤 3)

/explain(见步骤 2)

/release-notes:

---
description: Draft release notes from commits since last tag
disable-model-invocation: true
allowed-tools: Bash(git *)
---
## Commits since last tag
!`git log $(git describe --tags --abbrev=0)..HEAD --pretty=format:'- %s'`

## Task
Group the commits into: Features / Fixes / Chores. Output markdown.

2) 批量脚本 batch-review.sh:对所有改动的 .ts/.py 文件无头跑 /lint-review,合并成报告。

#!/usr/bin/env bash
set -euo pipefail

PROMPT="$(cat .claude/commands/lint-review.md)"
REPORT="lint-report.md"
echo "# 批量评审报告" > "$REPORT"

# 列出本次改动文件
mapfile -t FILES < <(git diff --name-only HEAD | grep -E '\.(ts|py)$' || true)

for f in "${FILES[@]}"; do
  echo "→ 评审 $f"
  echo -e "\n## $f\n" >> "$REPORT"
  claude -p "$PROMPT" \
    --output-format json \
    --max-turns 3 \
    --permission-mode default \
    <<< "$f" \
    | jq -r '.result // "(无输出)"' >> "$REPORT"
done

echo "完成:$REPORT(共 ${#FILES[@]} 个文件)"
chmod +x batch-review.sh
./batch-review.sh

预期结果:lint-report.md 按文件分节,每节是该文件的 JSON 评审结果。脚本可在本地一键跑,也可塞进 CI 的 PR 检查 job。

进阶:把 --permission-mode 换成 bypassPermissions 并配 --allowedTools 白名单,可在受控 CI runner 上完全无人值守;用 xargs -P 4 并行多个文件以提速。

工作流程图

flowchart TD
    A[作者: 写 .claude/commands/foo.md] --> B{frontmatter 配置}
    B -->|参数| C[$ARGUMENTS / $0 $1 / 命名参数]
    B -->|权限| D[allowed-tools 预授权]
    B -->|隔离| E[context: fork 子代理]
    A --> F[动态注入 !cmd 渲染实时数据]
    G[触发方式] --> H[交互 /foo]
    G --> I[无头 -p 批量循环]
    C --> J[渲染后提示词]
    D --> J
    E --> J
    F --> J
    H --> J
    I --> J
    J --> K[output style 约束格式]
    K --> L[Claude 执行]
    L --> M[结构化输出 JSON/MD]
    M --> N[CI 或下游脚本消费]

延伸阅读

训练营适用性评估

参考来源

  1. Extend Claude with skills — Claude Code Docs — 官方对 custom commands 与 skills 合并后的完整说明,含 frontmatter 字段表与 $ARGUMENTS/$N 替换变量。
  2. Output styles — Claude Code Docs — output style 如何改写系统提示词、内置 Proactive/Explanatory/Learning 样式与自定义方法。
  3. Customize your status line — Claude Code Docs — 状态栏脚本接收的会话 JSON 字段全表,可用于监控批量任务。
  4. Agent Skills 开放标准 — 跨 AI 工具通用的 skill 规范与最佳实践。
  5. Claude Code Slash Commands (2026) — Claude Directory — 第三方实战指南,补充文件布局与参数传递细节。 --verbose \

    "$STREAM" &

DOG=$!

预算闸:后台监工,回合超限即熔断

( while kill -0 "$DOG" 2>/dev/null; do t=$(jq -c 'select(.type=="assistant")' "$STREAM" 2>/dev/null | wc -l) [ "$t" -ge "$TURN_CAP" ] && { kill -TERM "$DOG"; echo "熔断@${t}回合"; > "$WORK/killed"; break; } sleep 2 done ) & WATCH=$! wait "$DOG" || true kill "$WATCH" 2>/dev/null || true

解析结算

RES=$(jq -c 'select(.type=="result")' "$STREAM") turns=$(echo "$RES" | jq -r '.num_turns') cost=$(echo "$RES" | jq -r '.cost_usd') err=$(echo "$RES" | jq -r '.is_error')

生成人类可读报告

{ echo "# 夜巡报告 $STAMP" echo "- 回合数:$turns / $TURN_CAP" echo "- 花费:\$$cost / \$$BUDGET_USD" echo "- 出错:$err" echo "## Agent 最终结论" echo "$RES" | jq -r '.result' echo "## 工具调用统计" jq -r 'select(.type=="assistant")|.message.content[]?|select(.type=="tool_use")|.name' \ "$STREAM" | sort | uniq -c | sort -rn } > "$REPORT"

预算闸:超支则禁用次日

echo "$cost" >> reports/dog.cost.log echo "报告已生成:$REPORT"

### 预期结果

- 正常夜:约 8–15 回合,花费 \$0.05–0.30,报告里列出已修复项与残留项
- 跑飞夜:第 25 回合被熔断,报告标"回合数:25 / 25",Agent 的部分结论仍被记录
- 越界尝试:Agent 若想 `git commit`,工具被拒,它在 stream-json 里留下一行 `tool_result is_error=true`,审计可见

### 常见问题

**Q:为什么用 Sonnet 而不是 Opus 跑夜巡?**
夜巡是大量低风险重复活,Sonnet 4.6 性价比远高于 Opus 4.8。把贵的 Opus 留给交互式复杂重构,自主批处理用便宜的——这是预算管理的延伸。

**Q:报告里 Agent 结论是自由文本,怎么结构化?**
在 prompt 末尾加"最终请用如下 JSON 输出:`{fixed:[...],remaining:[...]}`",然后 `echo "$RES" | jq -r '.result' | jq .` 二次解析。

**Q:多个仓库同时巡怎么办?**
每个仓库一个 `night-dog.sh` 进程,各自独立 stream 日志;在它们之上加一层 `fleet-budget.sh`(见第四步)做累计金额闸。这正是社区里 agent-orchestrator 这类"生产控制平面"要解决的:cron 调度 + 并发与回合上限 + 预算统筹。

---

## 三闸一管架构总览

```mermaid
flowchart TB
    subgraph 触发["触发层"]
        CRON[cron / CI / 编排器]
    end

    subgraph 三闸["三道护栏 (约束)"]
        T1["① 轮次闸<br/>--max-turns"]
        T2["② 权限闸<br/>permission-mode + allowedTools"]
        T3["③ 预算闸<br/>result.cost_usd + 外部看门狗"]
    end

    subgraph 引擎["自主引擎"]
        LOOP["claude -p agent loop<br/>思考↔工具调用"]
    end

    subgraph 管道["可观测管道 (眼睛)"]
        SJ["--output-format stream-json --verbose"]
        JQ["jq 实时提取<br/>工具/回合/报错"]
        LOG[(".jsonl 审计日志")]
        DASH["报告 / Dashboard"]
    end

    CRON --> T1 --> T2 --> T3 --> LOOP
    LOOP -- 每个事件 --> SJ --> JQ --> LOG --> DASH
    JQ -- 回合超限 --> KILL(["熔断 SIGTERM"])
    JQ -- 累计超支 --> STOP(["停止派发新任务"])
    LOOP -- 结束 --> RES[("result 消息<br/>cost/turns/error")]
    RES --> T3
    RES -- 出错/撞顶 --> RESUME[("--resume 续接")]

读懂这张图就懂了本篇:左侧三闸把 Agent 圈住,右侧管道把 Agent 照亮,中间的 --resume 提供续命能力。三者缺一,自主 Agent 都进不了生产。


进阶组合:Agent SDK 把三闸程序化

当你需要比 shell 更精细的控制时,绕过 CLI,直接用 Agent SDK(Python / TypeScript / CLI 三种形态)。它把 agent loop、工具、上下文管理暴露成可编程对象,三闸变成函数参数:

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

const result = query({
  prompt: "修复所有 lint 错误",
  options: {
    maxTurns: 25,                 // 轮次闸
    permissionMode: "acceptEdits",// 权限闸
    allowedTools: ["Read","Edit","Bash(npm run lint:*)"],
    model: "claude-sonnet-4-6",
  }
});

let spent = 0;
for await (const msg of result) {
  if (msg.type === "assistant") console.log("回合推进");
  if (msg.type === "result") {            // 预算闸传感器
    spent += msg.total_cost_usd;
    if (spent > BUDGET) break;            // 程序化熔断,比 kill 更优雅
    console.log(`本次 ${msg.num_turns} 回合,$${msg.cost_usd}`);
  }
}

SDK 的优势:预算闸可以从"事后 kill"升级为"事前判断 + 循环控制",并能把多个 query 串成一个有状态的编排。这正是把"夜间看门狗"演进为"白天作战舰队"的路径。


训练营适用性评估

延伸阅读

参考来源

  1. Run Claude Code programmatically — Claude Code Docs — headless 模式与 Agent SDK 官方文档,stream-json / input-format / 结构化输出的权威来源
  2. What is --max-turns in Claude Code — ClaudeLog — 轮次闸的作用机制与非交互会话防失控说明
  3. How Do I Use Claude Code Safely in CI/CD Pipelines with Budget Controls — BSWen — CI/CD 中预算控制与防无限推理循环的工程实践
  4. Output formats: json / text / stream-json — docs.qcode.cc — 三种输出格式对比与管道消费方式
  5. agent-orchestrator — GitHub — 生产级自主 Agent 控制平面:cron、并发与回合上限、预算统筹的参考实现

[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。

51学通信知识星球海报-扫码加入