← ClaudeAtlas

agent-command-approval-gatelisted

This skill should be used when building or reviewing an approval gate that decides whether a self-hosted agent's shell command needs human approval — OpenClaw/Olu, Hermes/Chuka, or any agent whose exec tool needs a human in the loop for privileged or outbound actions. Covers the three command-matching designs and why only one is safe (substring over-gates, anchored regex under-gates, command-position tokenizer is correct by construction), the full wrapper-bypass catalogue, the heredoc/backtick false positive the tokenizer introduces and its provable fix, block-vs-gate as originating-vs-continuing, the refactor regression a unit harness structurally cannot catch, OpenClaw's 512-char approval cap, the three-case live-fire protocol, and drift detection for a gate living where no playbook deploys it. Built across `dfw` (OpenClaw `admin-changes-gate`) and `hermes` (Hermes `outbound-email-approval`) 2026-09-01 to 2026-09-05. Trigger phrases include "approval gate", "pre_tool_call hook", "before_tool_call", "gate ag
jackson2w/claude-code-skills · ★ 1 · AI & Automation · score 64
Install: claude install-skill jackson2w/claude-code-skills
# Agent command approval gates How to decide that a command an agent is about to run needs a human. Built and re-built across two hosts over five days; every failure mode below is one that actually shipped. The config-and-hook side of gating lives in `openclaw-deployment` (Gotcha 2, `tools.exec.security` vs `ask`) and `hermes-agent-deployment` (`DANGEROUS_PATTERNS`, `approvals.mode`). **This skill is about the part those don't cover: matching.** Getting the hook to fire is easy. Deciding *which* commands it fires on is where every real bug was. ## Why matching is the hard part An approval gate has exactly two ways to fail: - **Under-gate** — a privileged command runs with no prompt. Silent. Presents as "no prompt fired", indistinguishable from the gate not being installed. This is the failure that matters. - **Over-gate** — a harmless command prompts. Noisy, fail-safe, and *not* free: an approval the human clicks through without reading is worth less than no approval at all. Both implementations here carry that reasoning in their own headers. So the target is not "match aggressively." It is **match exactly the invocations, and nothing that merely mentions them.** That turns out to be a parsing problem, not a pattern problem. ## The three designs, in the order they get invented Every implementation walks this path. Skip to design 3. ### 1. Substring — over-gates ```ts re: /\bhey\s+compose\b/ ``` `grep hey compose`, `cat` of a script containing the string, `ls