Approval Gate
SkillFiles & storageApproval gate for dangerous operations. Use internally before executing destructive commands, file deletions, git pushes, or external API calls from the web chat. Do NOT invoke directly.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Approval Gate skill
What this skill tells your AI
The instructions your AI receives, as published by mfielding92/clawedback in .claude/skills/oc-approve/SKILL.md and read by ahel’s review.
Human-in-the-loop safety gate for dangerous operations requested through the web chat.
When to Require Approval
Always require approval before:
- Running shell commands that modify or delete files
- Running
git push,git reset, or destructive git operations - Making external API calls or sending data to third parties
- Installing packages or modifying system state
- Any operation the user didn't explicitly request
How It Works
Step 1: Request Approval
Write an approval request to the outgoing queue:
cd $PROJECT_ROOT/.claude/skills/oc-poll/scripts && python queue_manager.py write '{
"content": "I need your approval to run:\n\n```\nrm -rf old_backups/\n```\n\nThis will permanently delete the old_backups directory. Reply **yes** to approve or **no** to deny.",
"type": "approval_request",
"metadata": {"action_id": "<unique_id>", "action": "bash", "command": "rm -rf old_backups/"}
}'
Step 2: Record Pending Approval
Add the pending approval to the session file (data/sessions/conversation.json):
{
"pending_approvals": [
{
"id": "<unique_id>",
"action": "bash",
"command": "rm -rf old_backups/",
"requested": 1700000000.0,
"description": "Delete old_backups directory"
}
]
}
Step 3: Wait
Do NOT execute the operation. The next poll cycle will pick up the user's response.
Step 4: Resolve (handled by oc-router)
When the router sees a "yes"/"approve" or "no"/"deny" message and there's a pending approval:
- Approved: Execute the operation, remove from pending, confirm completion
- Denied: Remove from pending, acknowledge the denial
- Expired: Approvals older than 1 hour are auto-denied
Pre-Approved Operations (Allowlist)
These operations do NOT require approval:
- Reading files anywhere on the system
- Writing files within
$PROJECT_ROOT/ - Running Python scripts within
$PROJECT_ROOT/ - Web searches and web fetches
- Creating/listing cron jobs within the session
Approval Message Format
Be clear and specific:
- State exactly what will happen
- Show the exact command
- Mention if it's irreversible
- Ask for yes/no
Multi-Step Approval Chains
For tasks that need multiple sequential human approvals (e.g., migrate → test → deploy), use a workflow chain instead of individual gates.
Creating a Chain
Define all steps upfront, persist them to data/sessions/workflows.json, then queue only step 1's approval.
Step 1: Write the workflow to disk
# Read existing workflows (or start fresh)
cat $PROJECT_ROOT/data/sessions/workflows.json 2>/dev/null || echo '{"workflows":{}}'
Add the new workflow:
{
"workflow_id": "<unique-id>",
"workflow_name": "Human-readable name",
"total_steps": 3,
"current_step": 1,
"status": "in_progress",
"steps": [
{"step": 1, "description": "What step 1 does", "action": "bash", "command": "the command", "status": "pending", "approved_at": null, "executed_at": null},
{"step": 2, "description": "What step 2 does", "action": "bash", "command": "the command", "status": "waiting", "approved_at": null, "executed_at": null},
{"step": 3, "description": "What step 3 does", "action": "bash", "command": "the command", "status": "waiting", "approved_at": null, "executed_at": null}
],
"created": 1700000000.0,
"cancelled_at": null,
"completed_at": null
}
Write to data/sessions/workflows.json. This file survives crashes and restarts.
Step 2: Queue the first step's approval
cd $PROJECT_ROOT/.claude/skills/oc-poll/scripts && python queue_manager.py write '{
"content": "**Workflow: Deploy v2** (Step 1/3)\n\nI need to run database migrations:\n```\npython manage.py migrate\n```\n\nApprove? Reply **yes** to proceed or **no** to cancel the workflow.",
"type": "approval_request",
"metadata": {"workflow_id": "<id>", "step": 1, "total_steps": 3}
}'
Step 3: Record in pending_approvals
Add to session's pending_approvals with the workflow fields:
{
"id": "<id>-step1",
"workflow_id": "<id>",
"workflow_name": "Deploy v2",
"step": 1,
"total_steps": 3,
"action": "bash",
"command": "python manage.py migrate",
"description": "Run database migrations",
"requested": 1700000000.0
}
Chain Resolution (handled by oc-router)
When an approval with workflow_id is resolved:
Approved:
- Execute the action
- Update
workflows.json: current step →status: "executed", setapproved_atandexecuted_at - If there's a next step: set it to
status: "pending", incrementcurrent_step, queue its approval request - If it was the last step: set workflow
status: "completed",completed_attimestamp. Send: "Workflow 'name' complete — all N steps approved and executed."
Denied:
- Do NOT execute
- Update
workflows.json: workflowstatus: "cancelled",cancelled_attimestamp - Send: "Workflow 'name' cancelled at step N/M."
Expired (>1 hour):
- Same as denied — cancel the entire workflow
Approval Message Format for Chains
Always show progress:
**Workflow: Deploy v2** (Step 2/3)
Step 1 ✅ Run database migrations — completed
Step 2 ➡️ Run full test suite — awaiting approval
Step 3 ⏳ Deploy to production — waiting
I need to run:
```pytest```
Approve? Reply **yes** to proceed or **no** to cancel the workflow.
Single Gates vs Chains
- No
workflow_id→ single gate, works exactly as before - Has
workflow_id→ part of a chain, follows the workflow lifecycle above
Both types coexist in pending_approvals. They don't interfere with each other.
Signals
- GitHub stars
- 23
- Last commit
- Aug 2026
Advanced
- Catalog kind
- skill
- Gateway key
oc-approve- Source
- github.com/mfielding92/clawedback