
dcg 统一 Robot Mode API 设计解析为 AI Agent 打造稳定、可解析的命令行接口【免费下载链接】destructive_command_guardThe Destructive Command Guard (dcg) is for blocking dangerous git and shell commands from being executed by agents.项目地址: https://gitcode.com/GitHub_Trending/de/destructive_command_guarddcgDestructive Command Guard以 hook 形式嵌入 Claude Code、Gemini CLI 等 AI 编码代理拦截危险的 git 与 shell 命令。本文基于仓库 docs/adr-002-robot-mode-api.md 展开剖析其提出的统一Robot Mode机器人模式API设计全局--robot标志、标准化退出码、统一OutputFormat枚举与纯 JSON 输出契约。读完你将掌握 dcg 为机器消费设计的完整接口约定、各子命令在 robot 模式下的行为差异以及如何在自己的脚本或 Agent 工作流中可靠地消费 dcg 的输出。背景Agent 集成为何需要统一接口dcg 作为 hook 被 AI 编码代理调用时代理需要以编程方式解析 dcg 的输出。但在 ADR-002 提出之前CLI 存在一系列不一致使集成变得复杂格式标志不统一不同命令混用-f、-F、-o或--json布尔标志默认值不统一部分命令默认pretty部分默认json或text缺少统一机器人模式每条命令都要单独配置机器输出退出码不统一各命令没有文档化的标准退出码stderr 行为混杂即使在 CI 环境某些命令也会输出装饰性内容JSON 字段命名不一致hook 输出使用 camelCase协议要求其他输出使用 snake_case。Agent 的核心需求AI 代理需要的是stdout 上是纯 JSON无 ANSI 码、无装饰文本stderr保持静默至少不干扰 stdout 解析可预测的退出码用于决策稳定的 JSON schema版本升级不破坏单一标志即可在所有命令上启用“机器模式”。ADR-002 的决策正是围绕这六点展开并已在仓库中落地实现。全局--robot标志一份配置、处处生效ADR-002 设计了一个全局--robot布尔标志并支持通过环境变量DCG_ROBOT启用。在 src/cli.rs 中可以看到它的实际定义/// Enable robot/machine mode for AI agent integration /// /// When enabled: /// - All output is JSON on stdout /// - stderr is completely silent (no rich output, no human messages) /// - Exit codes follow standardized values (see docs/adr-002-robot-mode-api.md) /// - Human-friendly decorations are suppressed #[arg(long, global true)] pub robot: bool,注意实现细节ADR 草案中曾设计env DCG_ROBOT直接挂在 clap 参数上而落地实现将其移到了输出层统一处理。在 src/output/mod.rs 的robot_mode_enabled中pub fn robot_mode_enabled(explicit_robot_flag: bool) - bool { explicit_robot_flag || env_flag_enabled(DCG_ROBOT) }关键语义显式--robot始终优先DCG_ROBOT环境变量遵循与其他输出标志一致的布尔解析——0、false、no、n、off及空值都视为未启用而非“只要设置了就算启用”。env_flag_value_enabled的实现验证了这一点src/output/mod.rs 中test_env_flag_value_enabled_boolean_semantics测试覆盖了这些取值。在 src/main.rs 中robot 模式被纳入“强制纯文本输出”的判定let robot_mode destructive_command_guard::output::robot_mode_enabled(cli.robot); let force_plain_output cli.legacy_output || cli.no_color || robot_mode;即 robot 模式下自动禁用颜色渲染并同时禁用建议suggestion输出init_suggestions(!cli.no_suggestions !robot_mode)。启用方式# 方式一命令行标志 dcg --robot test rm -rf / # 方式二环境变量支持 true/false 语义 DCG_ROBOT1 dcg test rm -rf /行为对照表维度普通模式Robot 模式stdoutJSON 或 pretty始终 JSONstderrRich 彩色输出静默退出码各命令各异标准化ANSI 码视 TTY从不输出进度指示显示隐藏建议suggestions显示仅在 JSON 中警告输出到 stderr编码进 JSON标准化退出码让$?直接可决策ADR-002 提议创建独立的退出码模块。仓库中 src/exit_codes.rs 已完整落地且比 ADR 草案增加了两个实战常量码常量含义0EXIT_SUCCESS成功 / 放行allowed、passed、healthy1EXIT_DENIED命令被安全规则拒绝/拦截2EXIT_WARNING警告配合--fail-on warn3EXIT_CONFIG_ERROR配置错误配置文件无效、缺少必需配置4EXIT_PARSE_ERROR解析/输入错误无效 JSON、畸形命令5EXIT_IO_ERRORIO 错误文件未找到、权限拒绝、网络错误141EXIT_BROKEN_PIPEstdout/stderr 读取方提前离开EPIPE是干净退出而非信号死亡2EXIT_HOOK_BLOCK仅 hook 模式deny/ask/indeterminate 裁决无法写入 stdout 时以退出码承载拦截EXIT_BROKEN_PIPE141的由来EXIT_BROKEN_PIPE对应128 SIGPIPE(13)让dcg … | head -1在set -o pipefail下与cat … | head -1表现完全一致。dcg 通过 broken-pipe panic 兜底issue #389走干净的process::exit到达该码——永远不会因信号死亡因此无 core dump、无SIGABRT且SIGPIPE本身保持忽略详见output::emit的注释hook 二进制不能在 stderr 写入时死亡因为其 stdout 上的裁决可能仍有读者。EXIT_HOOK_BLOCK2与EXIT_WARNING2的共存两个常量数值相同都是 2但永远不会出现在同一进程中EXIT_WARNING属于 robot 模式子命令如dcg --robot test --fail-on warnEXIT_HOOK_BLOCK属于 hook 模式无子命令。当 stdout 写入本身失败EPIPE宿主在裁决写入前关闭了管道时退出 0 且无 JSON 会被宿主解读为“放行”从而把 deny 变成 allow——这是不可接受的因此拦截结果改由退出码 2 承载理由写到 stderr。每个 hook 协议的“裁决无法送达时的退出码”映射表定义在HookProtocol::undeliverable_block_exit_code上。各协议对“退出 2 空 stdout”的解读来自 docs/agents.md协议效果Claude Code 及兼容宿主Posit Assistant、Augment拦截stderr 作为理由反馈给模型Gemini CLI拦截退出 2 即其阻断错误Copilot CLI拦截preToolUse钩子退出 2 拒绝调用Crush拦截stderr 即理由Grok拦截退出 2 是文档化的显式拒绝Codex CLI、Hermes、Antigravityagy记为 hook 失败后 fail-open——与退出 0 无 JSON 效果相同但可见hook 模式绝不会因其他原因退出 2也从不退出 141hook 模式的每次写入都容忍关闭的管道。辅助 APIexit_codes模块还提供to_exit_code(i32) - ExitCode供main()返回、exit_with(code) - !便捷退出包装以及ToExitCodetrait将求值结果转换为退出码。模块内测试exit_codes_are_distinct、exit_codes_are_valid_range、success_is_zero等保证这些常量互不冲突且落在 0–255 合法区间。统一OutputFormat枚举消灭各自为政的格式类型ADR-002 设计了跨命令共享的OutputFormat枚举落地实现位于 src/cli.rs#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, clap::ValueEnum, serde::Serialize)] #[serde(rename_all lowercase)] pub enum OutputFormat { /// Human-readable colored output (default for interactive use) #[default] #[value(alias text, alias human)] Pretty, /// Structured JSON output (for agents and scripting) #[value(alias sarif, alias structured)] Json, /// JSON Lines format (one JSON object per line, for streaming) #[value(name jsonl)] Jsonl, /// Compact single-line output (for specific commands) Compact, }该枚举提供两个实用谓词is_json()Json或Jsonl均为真——用于判断输出是否可被 JSON 解析器消费is_human_readable()Pretty或Compact均为真。Robot 模式下的格式默认值当--robot启用时格式强制默认Json无论命令自身的默认值是什么。因此下面两条命令等价dcg --robot test cmd dcg --robot --format json test cmd可用的格式别名pretty/text/human—— 人类可读无--robot时的默认json/sarif/structured—— JSON 输出--robot时的默认jsonl—— JSON Lines每行一个对象适合流式处理compact—— 紧凑单行输出用于explain等特定命令。从源码结构看除统一枚举外各子命令仍保留了自己的强类型格式枚举TestFormat、CorpusFormat、StatsFormat、ClassifyFormat、ConfigFormat、PacksFormat、DoctorFormat等它们大多以Pretty/Json二元结构为主并通过DCG_FORMAT环境变量统一驱动默认值——这印证了 ADR 中“先加统一枚举、逐步淘汰零散类型”的迁移思路。Robot 模式 JSON 输出稳定、可解析的响应契约ADR-002 设想的响应信封包含dcg_version、schema_version、command_name、success、data、metadata等字段。实际落地为每个子命令输出稳定的 JSON例如dcg test的 deny 结果tests/golden/robot/deny_filesystem.json{ schema_version: 1, dcg_version: DYNAMIC_VERSION, robot_mode: true, command: rm -rf /, decision: deny, mode: deny, rule_id: core.filesystem:rm-rf-root-home, pack_id: core.filesystem, pattern_name: rm-rf-root-home, reason: rm -rf on root or home paths is EXTREMELY DANGEROUS. ..., explanation: This command would recursively delete files starting from the root filesystem (/) ..., source: pack, matched_span: [3, 6], severity: critical, agent: { detected: unknown, trust_level: medium, detection_method: none } }allow 结果的字段更精简tests/golden/robot/allow_git_status.json{ schema_version: 1, dcg_version: 0.4.1, robot_mode: true, command: git status, decision: allow, agent: { detected: unknown, trust_level: medium, detection_method: none } }Agent 元数据字段输出中的agent对象承载代理检测信息detected代理标识如claude-code、trust_levelhigh/medium/low默认medium、detection_method如environment_variable。检测优先级为显式--agent标志 环境变量 父进程检查 unknown详见 docs/agents.md。trust_level是建议性标签本身不改变规则触发行为差异全部来自disabled_packs、extra_packs、additional_allowlist、disabled_allowlist等配置项。Golden 文件测试保障 schema 稳定仓库用 golden 文件锁定 robot 模式 JSON路径 tests/golden/robot/ 下含allow_git_status.json、allow_simple.json、deny_filesystem.json、deny_git_force_push.json、deny_git_reset.json五个快照。配合dcg_version字段支持版本占位符如DYNAMIC_VERSION测试可在版本更新时动态替换从而验证“schema 不因版本而破坏”这一 ADR 目标。Hook 模式 vs Robot 模式两条契约的分工这是理解 dcg 接口的关键——hook 模式与 robot 模式是两套不同的退出码/输出契约docs/agents.mdHook 模式无子命令时默认裁决写在 stdout JSON 上allow 时为空 stdout进程退出 0无论命令是允许、警告、送审还是拒绝。仅当阻断裁决无法送达时退出 2EXIT_HOOK_BLOCK。Codex CLI 使用严格 hook 解析dcg 输出最小化的hookSpecificOutput拒绝负载并退出 0。Robot 模式带子命令如dcg --robot testdeny 时退出 1便于脚本直接判断$?stdout 纯 JSONstderr 静默。stdout / stderr 分离原则dcg 将面向 Agent 的输出与面向人类的输出放在不同流上这是 rich 格式化兼容性的根基流用途Hook 模式内容Robot 模式内容stdoutAgent 与脚本解析拒绝时为协议 JSON放行为空仅 JSONstderr人类可见诊断Rich 或纯文本警告框静默Rich 输出纯属展示用途绝不允许被 Agent 解析也绝不允许写入 stdout。Unicode 边框、颜色、高亮命令、建议面板全部归属 stderr。实战在 Agent 工作流中消费 robot 模式场景一脚本按退出码决策#!/bin/bash # Script for AI agent to check commands before execution check_command() { local cmd$1 local result # Use robot mode for predictable output result$(dcg --robot test $cmd 2/dev/null) local exit_code$? if [ $exit_code -eq 0 ]; then echo Command allowed: $cmd return 0 elif [ $exit_code -eq 1 ]; then echo Command BLOCKED: $cmd echo Reason: $(echo $result | jq -r .reason) return 1 else echo Error checking command (exit code: $exit_code) return $exit_code fi } # Usage check_command git status # Allowed check_command rm -rf / # Blocked场景二包装器同时保留两条流# Hook integration: preserve both streams. dcg hook-input.json hook-stdout.json 2human-warning.txt # Scripting integration: use robot mode and parse stdout only. dcg --robot test rm -rf / decision.json 2/dev/null对于 Codex 和 Claude 兼容的 hook 集成stdout 非空时解析 stdoutstdout 为空且退出 0 视为 allow。Codex 的拒绝负载是最小化的且有意省略 dcg 专属元数据。场景三作为其他工具的底层调用从源码结构看dcg 自身的集成组件也依赖 robot 模式OMP 扩展通过dcg --robot test --stdin --agent omp --format json做每命令预检见 docs/agents.md并以--dialect posix指定 shell 方言。这说明 robot 模式是 dcg 生态内部组件的通用机器接口而不仅是外部脚本的便利开关。Rich 输出降级控制机器人环境的兜底保障除--robot外以下任一条件都会让 dcg 回退到纯文本/静默输出src/output/mod.rs 的should_use_rich_output_with_env控制项效果DCG_NO_RICH1禁用 rich 格式化保持正常命令行为--legacy-output/DCG_LEGACY_OUTPUT1强制 legacy/纯文本渲染路径NO_COLOR1/DCG_NO_COLOR1禁用彩色输出TERMdumb使用 dumb 终端安全输出CI1CI 下抑制 rich 交互格式化stdout 非 TTY偏好纯文本利于管道--robot/DCG_ROBOT1机器可读 stdout stderr 静默判定的完整顺序是显式强制纯文本 →DCG_NO_RICH/NO_COLOR/DCG_NO_COLOR→CI环境变量 → stdout 是否为 TTY →TERMdumb。这些开关共同保证无论 Agent 宿主环境如何CI、管道、无 TTY 子进程stdout 始终可安全解析。迁移策略与影响评估ADR-002 规划的迁移分三个阶段推进Phase 1非破坏新增--robot标志与DCG_ROBOT环境变量、新增exit_codes模块、新增OutputFormat枚举、在 AGENTS.md 中记录 robot 模式——均已落地Phase 2弃用期弃用命令各自的--json布尔标志与不一致的格式枚举旧标志继续工作并发出弃用警告Phase 3未来在下一个大版本移除已弃用标志考虑 gRPC/MCP 原生协议注仓库已提供dcg mcp-server子命令以 stdio 方式暴露check_command、scan_file、explain_pattern工具是这一方向的先行实现。影响总结正面单一--robot标志即可配置一切Agent 集成更简单行为可预测JSON schema 版本化防止破坏性变更golden 文件测试可验证 robot 输出Agent 开发者有集中、清晰的文档。负面CLI 新增一个全局标志现有使用--json的脚本最终需要更新需要同时维护人类与机器两条输出路径。中性完全向后兼容所有既有行为继续工作robot 模式是 opt-in默认仍是人类友好的 pretty 输出。最佳实践清单脚本集成一律使用 robot 模式需要稳定可解析输出时用--robot而非命令各自的--format json简单判定只看退出码allow/deny 直接读$?0/1无需解析 JSON需要理由再jq -r .reason永远丢弃 stderrrobot 模式下 stderr 应为空脚本中建议2/dev/null防御性隔离不要解析 rich 输出人类可读的装饰内容属于 stderr只用于展示CI 中审计 Agent 行为用--format json审计哪些 Agent 在访问代码库配合agent元数据字段检查schema_version消费方应对输出中的schema_version做校验防止 schema 变更时静默破坏hook 集成遵循协议语义hook 模式退出 0 携带裁决 JSON空 stdout 0 allow阻断裁决无法送达时退出 2切勿把退出 2 误读为“警告”。延伸阅读设计原文docs/adr-002-robot-mode-api.mdAgent 配置与集成指南docs/agents.md退出码常量实现src/exit_codes.rs--robot标志与OutputFormat枚举src/cli.rsrobot 模式启用判定src/output/mod.rsRobot 模式 golden 输出快照tests/golden/robot/相关测试tests/robot_mode.rs、tests/golden_json_tests.rs相邻设计MCP 服务器集成见 docs/pi-integration.md 与dcg mcp-server子命令【免费下载链接】destructive_command_guardThe Destructive Command Guard (dcg) is for blocking dangerous git and shell commands from being executed by agents.项目地址: https://gitcode.com/GitHub_Trending/de/destructive_command_guard创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考