Skip to main content
AI/MLWaterplanAI

ac-tools-dry-run

Runs a delegated command or prompt in dry-run mode by setting session status, preserving read-only behavior, and resetting state after execution. Triggers on keywords: dry run, simulate, preview changes, safe mode

Stars
31
Source
WaterplanAI/agentic-config
Updated
2026-05-25
Slug
WaterplanAI--agentic-config--ac-tools-dry-run
View on GitHubRaw SKILL.md

// install — copy + paste into any project

mkdir -p .claude/skills && curl -fsSL https://raw.githubusercontent.com/WaterplanAI/agentic-config/HEAD/packages/pi-ac-tools/skills/ac-tools-dry-run/SKILL.md -o .claude/skills/ac-tools-dry-run.md

Drops the SKILL.md into .claude/skills/ac-tools-dry-run.md. Works with Claude Code, Cursor, and any agent that loads SKILL.md files from .claude/skills/.

Dry Run

Executes any command or prompt in simulation mode, preventing file modifications except for the session status file.

Compatibility Note

This pi wrapper preserves the original dry-run workflow. Runtime enforcement comes from the package-local dry-run-guard.py registration via @agentic-config/pi-compat; if that guard is unavailable, still follow the same no-write constraints manually.

Usage

/skill:ac-tools-dry-run <any command or prompt>

Examples:

  • /skill:ac-tools-dry-run /skill:ac-workflow-spec IMPLEMENT path/to/spec.md - Preview the implementation flow without writing files
  • /skill:ac-tools-dry-run /skill:ac-workflow-mux-ospec path/to/spec.md - Preview a larger workflow without committing changes
  • /skill:ac-tools-dry-run explain why the current plan uses packaged assets - Normal chat with no file modifications

Workflow

Step 1: Initialize Session Status

Resolve the session status path using the same priority as the dry-run hook:

  1. prefer CLAUDE_SESSION_ID when it is available
  2. otherwise fall back to compat PID tracing
  3. use the shared path only as a legacy last resort
SESSION_ID="${CLAUDE_SESSION_ID:-}"
if [ -z "$SESSION_ID" ]; then
  SESSION_ID=$(python3 - <<'PY'
import os
import subprocess

pid = os.getpid()
for _ in range(10):
    result = subprocess.run(
        ["ps", "-o", "pid=,ppid=,comm=", "-p", str(pid)],
        capture_output=True,
        text=True,
        check=False,
    )
    line = result.stdout.strip()
    if not line:
        break

    parts = line.split()
    if len(parts) >= 3:
        current_pid, ppid, comm = int(parts[0]), int(parts[1]), parts[2]
        if "claude" in comm.lower():
            print(current_pid)
            break
        pid = ppid
    else:
        break
else:
    print("shared")
PY
)
fi

[ -n "$SESSION_ID" ] || SESSION_ID="shared"
STATUS_DIR="outputs/session/${SESSION_ID}"
STATUS_FILE="${STATUS_DIR}/status.yml"
mkdir -p "$STATUS_DIR"

If ${STATUS_FILE} does not exist, create it with:

dry_run: false

Step 2: Set Dry-Run Mode

Update ${STATUS_FILE} to:

dry_run: true

This signals to this session's file operations that writes are prohibited. Other sessions with different session IDs are not affected.

Step 3: Execute Delegated Command

Execute the provided command or prompt exactly as given. All behavior remains normal except:

  • No file modifications are allowed
  • The only write exception is ${STATUS_FILE}
  • If the delegated work requires file writes, describe what would change instead of performing the write
  • For chat-only prompts, respond normally

Step 4: Reset Dry-Run Mode

After execution completes, whether it succeeds or fails, reset ${STATUS_FILE} to:

dry_run: false

Step 5: Report Results

Summarize:

  • what was executed
  • what file changes would have occurred, if any
  • confirmation that dry-run mode was reset

Implementation Notes

The skill acts as a wrapper:

  1. It does not reinterpret the delegated work
  2. It sets the status flag, then lets the normal workflow continue
  3. The dry-run flag is enforced by the package-local pre-tool hook when available
  4. It must always clean up the status flag afterward

State Schema

outputs/session/<session_id>/status.yml:

dry_run: bool