agentsclimarketplace

Agent guardrails

Skill Paldom/python-skills/skills/agent-guardrails

Agent Skills and hooks for maintaining high-quality open-source Python packages - an agentic engineering setup covering linting, testing, packaging, releases, and CI quality gates.

Install
npx -y skills add Paldom/python-skills --skill agent-guardrails

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Installs agentic guardrails into a Python repo — Claude Code hooks, a Stop gate that signs off only what pre-commit accepts, vetted public skills — and troubleshoots hooks that don't fire or block. Use for 'add Claude Code hooks', 'write an AGENTS.md', 'make this repo agent-ready', 'agent keeps bypassing checks', 'agent says done but pre-commit fails'. Not for authoring the pre-commit config.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

14.2 KB, as published. Nobody here has run it

agent-guardrails

Install the agent-facing enforcement layer of a Python repo: Claude Code hooks that give a coding agent instant, deterministic feedback (and hard-block the few things it must never do), the settings wiring that ships them, a concise rules file, and vetted public skills. The failure this skill fixes is advisory-only guardrails — rules the model forgets under context pressure, hooks that silently never fire, and exit 1 "blocks" that block nothing.

When NOT to use

  • Git hooks — .pre-commit-config.yaml, commit-msg/pre-push stages. The python-precommit skill, if installed, owns the commit-time layer.
  • CI workflows, required checks, branch rulesets — the python-ci skill. CI is the authoritative gate this skill's layers feed into, not what it installs.
  • Validating LLM output data — Pydantic/Instructor schema validation, retry-with-error-context, SQL safety validators. That is runtime data validation in your application, not repo guardrails; this skill does not cover it.
  • Tuning what the checks themselves do — ruff rules (python-lint), type checker config (python-typing), test infra (python-testing). This skill wires when checks run against agent actions, not their contents.
  • Generic prompt engineering or system-prompt writing.

The layer model (read this first)

Guardrails only work layered; each layer catches what the previous cannot (convention, not an official spec — but it is strong cross-source consensus):

LayerRunsCatchesBypassable?
Rules file (AGENTS.md/CLAUDE.md)read at session startconventions, commandsyes — advice the model can forget
Claude Code hooksat the moment of each agent actionbad writes/commands before or as they happenyes — local, user-controlled
pre-commitat commitwhole-diff issuesyes — --no-verify
CI + rulesetsat mergeeverything, on infra the agent doesn't controlno — the only real gate

Two consequences to state to the user every time: anything that must always happen belongs in a hook, not prose (rules files are wishes; hooks are contracts the harness executes), and hooks are never the security boundary — a determined agent can be dispatched around them (subagents, bash instead of Edit), so CI and server-side rules stay authoritative. Hooks' one unique power: PreToolUse denial happens before the file ever exists on disk — the only layer that can do prevention rather than cleanup.

Workflow

1. Audit what exists

python3 "${CLAUDE_SKILL_DIR}/scripts/check_guardrails.py" --root .

Read-only: reports settings files and scopes, wired hooks and their matchers, rules files and their length, obvious defects (lowercase matchers, exit 1 used as a block, missing script files, unguarded Stop hooks). Also check claude --version — hook behavior has version drift; the current docs are the source of truth: https://code.claude.com/docs/en/hooks

2. Rules file — context, not enforcement

Write (or trim) AGENTS.md at the repo root, with CLAUDE.md containing only @AGENTS.md so every agent reads one canonical file. Start from assets/AGENTS.md.template. Rules that earn their place in a Python repo:

  • exact commands, not prose — uv sync, uv run pytest, uv run ruff check --fix, uv run mypy src/
  • "Use uv, never pip or poetry" (the single most-reported agent failure: defaulting to global pip installs)
  • "Run lint + typecheck + tests before calling a task done"
  • "Never weaken a gate to pass it — no lowering coverage, skipping tests, or || true" (agents under pressure take the cheapest path to green)
  • blast-radius lines: "flag changes to auth, dependencies, or lockfiles for human review"

Keep it under ~200 lines and hand-curated: auto-generated context files have measurably hurt agent success in evaluations — write what is specific to this repo, not a generic overview. Recurring PR-review corrections are the best source of new lines.

3. Hooks — the deterministic layer

Copy the three hook scripts from assets/hooks/ into .claude/hooks/, make them executable, then wire assets/settings.json.template into .claude/settings.json. The architecture is thin JSON, heavy script: the settings file only routes events; logic lives in versioned scripts.

GoalEvent + matcherScript
Block dangerous bash (--no-verify, force-push main, bare pip)PreToolUse on Bashguard-bash.sh
Instant lint/format feedback on the file just editedPostToolUse on Edit|Writelint-edited-file.sh
Sign off only what the commit gate would acceptStopstop-verify.sh

The parity rule. The Stop gate never re-implements checks: when the repo has .pre-commit-config.yaml, stop-verify.sh runs pre-commit itself over the changed + untracked files — the identical gate git commit will run (pre-commit run --files checks the worktree as-is; no stashing). Auto-fixing hooks (prettier, ruff --fix, whitespace fixers) exit non-zero after repairing the tree, so the gate runs twice and a clean second run passes. A hand-rolled subset (ruff check . alone) drifts from the config and produces the classic failure: agent says done, the owner's commit fails on prettier. Repos without pre-commit keep the single fast VERIFY_CMD fallback.

The exit-code contract — the part everyone gets wrong:

  • exit 0 — proceed (stdout may carry JSON decisions).
  • exit 2 — the ONLY blocking exit code. Reason goes to stderr (stdout is discarded on exit 2). What "block" means is event-dependent: PreToolUse prevents the call; PostToolUse cannot undo — stderr is feedback only; Stop prevents stopping and forces the agent to keep working.
  • exit 1 (or any other code) — non-blocking. Logged, ignored, the action proceeds. This single fact breaks a large share of hook setups.

Rules for hooks that survive contact with a team:

  • Scope PostToolUse to the single edited file and keep it sub-second — it runs synchronously on every matching call. Anything slower (mypy, tests) belongs in the Stop hook, pre-commit, or CI.
  • Stop hooks MUST honor stop_hook_active in the stdin JSON — the template re-verifies once, then releases (exit 0) instead of blocking again — or they loop; the harness force-overrides after 8 consecutive blocks.
  • Give the Stop gate a generous explicit timeout (the template wires 300 s) and pre-build hook environments at setup (uv run pre-commit install --install-hooks): a hook that hits its timeout is non-blocking, so a cold first-run env build silently skips verification.
  • Matchers are case-sensitive exact names or regex: bash never matches Bash; Edit.* also catches NotebookEdit — use Edit|Write.
  • Edit|Write misses shell-driven edits (sed -i, heredocs). Cover the gap with the Stop-hook verification pass, which sees the whole worktree.
  • Hard-deny (exit 2) only deterministic, unambiguous violations; prefer non-blocking feedback for style-level issues — an over-eager PreToolUse block can stall the agent entirely instead of guiding it.
  • Roll out observe → warn → enforce: log-only first, then narrow denies for patterns that caused real damage.

Full mechanics (per-event exit-2 semantics, matcher and if-field rules, JSON decision channels, scopes, known version-drift issues): references/hooks-reference.md. Which check belongs at which layer: references/layer-assignment.md.

4. Settings scopes and permissions

  • .claude/settings.json — committed, applies to every contributor. This is the team contract; changes to it deserve PR-level scrutiny (see security below).
  • .claude/settings.local.json — gitignored, personal experiments.
  • ~/.claude/settings.json — user-global. All scopes merge additively; a project file cannot switch off a user hook, only add.
  • Hooks tighten policy but do not replace the permission system: a hook exit 0 does not approve anything, and the if filter is best-effort and fails open on ambiguous commands. Hard allow/deny of tools belongs in permissions rules; hooks add checks the permission grammar cannot express.

5. Install and vet public skills

Recommend established public skills instead of rebuilding them — but treat every third-party skill, plugin, and MCP server as an unreviewed dependency with full user permissions. Minimum vet before install: read the plugin manifest (an mcpServers entry means network access), every hook it ships and the commands they run, and each full SKILL.md body; check requested permissions are proportional to the stated function; pin versions and review updates like dependency bumps. Curated starting points and the full checklist: references/vetting-skills-and-plugins.md.

6. Verify by tripping every wire

A guardrail that has never fired is unverified. Test each one deliberately:

# 1. Scripts standalone, with realistic stdin — check exit code + stderr
echo '{"tool_input":{"command":"git commit --no-verify -m x"}}' \
  | .claude/hooks/guard-bash.sh; echo "exit=$?"        # expect exit=2
echo '{"tool_input":{"command":"git status"}}' \
  | .claude/hooks/guard-bash.sh; echo "exit=$?"        # expect exit=0
# 2. Audit passes
python3 "${CLAUDE_SKILL_DIR}/scripts/check_guardrails.py" --root .

Then, in a live session: ask the agent to do a blocked action (expect a blocked call with the reason), edit a file with a deliberate lint error (expect hook feedback), and end a turn with a failing check (expect the Stop gate to push back). In a repo with pre-commit, also end a turn with an unformatted YAML/Markdown file in the tree — the Stop gate must run the commit gate and auto-fix or block, never sign it off. If a hook doesn't fire: matcher case, settings nesting, jq present on the machine, and script executable bit — in that order.

Output spec

Done means:

  • AGENTS.md (≲200 lines, repo-specific) with CLAUDE.md importing it.
  • .claude/settings.json wiring PreToolUse guard, PostToolUse single-file check, and a Stop gate that runs the repo's own commit gate (pre-commit over the change set) or a single fast verify command; scripts in .claude/hooks/, executable, blocking only via exit 2 + stderr, Stop guarded by stop_hook_active.
  • Every hook demonstrated to fire and to block (step 6 transcript).
  • scripts/check_guardrails.py exits 0.
  • The user told, in one sentence each: hooks are convenience, CI is the gate; and committed hooks execute on every contributor's machine.

Failure modes & gotchas

SymptomCause / fix
Hook "blocks" but the action proceedsexit 1 — only exit 2 blocks; everything else is logged and ignored
Block reason never shown to the agentreason printed to stdout — on exit 2 stdout is discarded; use stderr
Hook never firescase-sensitive matcher (bashBash), wrong settings nesting, missing jq, unexpanded $HOME, or script not executable — all fail silently
Stop hook loops forevermissing stop_hook_active guard; harness caps at 8 blocks but fix the guard
Agent "done" but the owner's git commit fails (prettier reformats, whitespace fixers fire)Stop gate re-implements a subset instead of running the repo's pre-commit — wire stop-verify.sh's parity path (pre-commit run --files over the change set)
First Stop in a fresh clone hangs or times outcold hook-env build; pre-build at setup (pre-commit install --install-hooks) and keep the generous timeout — a timed-out hook is non-blocking, i.e. a silent pass
Agent edits files but the format hook is silentedit made via Bash (sed -i, cat >) — Edit|Write never fires; rely on the Stop-hook worktree pass
Formatter hook fights the agentpost-edit rewrite trips the agent's stale-file check on its next edit; format on save/commit instead, or accept the re-read cost
PreToolUse exit-2 stalls the agent instead of correcting itknown behavior in some versions — keep hard denies rare and actionable; put style feedback in non-blocking channels
Hooks treated as securitythey are local and user-controlled; subagent dispatch and alternate tool paths route around them — CI + rulesets are the boundary
Committed hook = code execution on every clone.claude/ changes are code: CODEOWNERS them, review in the web UI before checking out PR branches (real CVEs exist here)
Plugin/skill turns out maliciousvet before install (step 5), pin versions, prefer official/curated sources
Hook advice from tutorials doesn't match behaviorthe event surface and blocking semantics drift across versions — trust https://code.claude.com/docs/en/hooks over any static list, including this skill's

Files

  • scripts/check_guardrails.py — read-only audit of settings, hooks, matchers and rules files; non-zero exit on defects.
  • assets/settings.json.template — hook wiring for the three-script setup.
  • assets/hooks/guard-bash.sh — PreToolUse deny: --no-verify, SKIP= hook skips, force-push to main, bare pip/python outside uv.
  • assets/hooks/lint-edited-file.sh — PostToolUse single-file ruff check+format.
  • assets/hooks/stop-verify.sh — Stop gate with the stop_hook_active guard: runs the repo's pre-commit over changed + untracked files (twice, so auto-fix hooks converge; uv run fallback for uv-managed installs), or one marked VERIFY_CMD line in repos without pre-commit.
  • assets/AGENTS.md.template — starting rules file.
  • references/hooks-reference.md — full hook mechanics + known issues.
  • references/layer-assignment.md — which check runs at which layer.
  • references/vetting-skills-and-plugins.md — vetting checklist + curated skills.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.