
Rulecheck
- 199 installs
- 23.1k repo stars
- Updated August 4, 2026
- coleam00/archon
Audit changes against project rules, conventions, and guardrails before merge so agents do not ship inconsistent or noncompliant code.
About
Runs structured rule and convention checks on agent-generated changes, comparing implementation against repository standards, style guides, and policy constraints so issues are caught during review instead of after release.
- Checks code against project rules
- Flags convention and policy violations
- Supports pre-merge quality gates
- Reduces inconsistent agent output
Rulecheck by the numbers
- 199 all-time installs (skills.sh)
- Ranked #341 of 1,352 Code Review & Quality skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/coleam00/archon --skill rulecheckAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 199 |
|---|---|
| repo stars | ★ 23.1k |
| Last updated | August 4, 2026 |
| Repository | coleam00/archon ↗ |
What it does
Audit changes against project rules, conventions, and guardrails before merge so agents do not ship inconsistent or noncompliant code.
Files
Rulecheck
Launch the rulecheck-agent to autonomously scan and fix CLAUDE.md rule violations.
Your Job (Main Agent)
You are the orchestrator. Your ONLY job is to launch the rulecheck-agent and report its results when it completes. You do NOT do the scanning or fixing yourself.
1. Launch the rulecheck-agent with the focus area (if any): $ARGUMENTS 2. Wait for it to complete — do NOT poll, tail, or check on it. You will be notified automatically when it finishes. 3. Report ONLY what the agent told you — relay its final message verbatim or summarize it. Do NOT search for PRs, read files, or fabricate results. If the agent hit its context limit, say so. If it didn't produce a PR URL in its output, don't go looking for one.
Rules for You
- Do NOT scan the codebase yourself — that's the agent's job
- Do NOT grep, read source files, or run linters — the agent handles all of that
- Do NOT edit any files — you are the orchestrator, not the fixer
- Do NOT try to resume or check on the agent while it's running — just wait
- Do NOT do the agent's work if it fails or hits context limits — report the failure to the user and stop. NEVER pick up where the agent left off. You are not in a worktree and would be editing main directly.
- Do NOT update project memory — the agent maintains its own memory at
.claude/agent-memory/rulecheck-agent/. Do not duplicate run results into your project memory. - Trust the agent. It runs in an isolated worktree and will create a PR when done.
#!/bin/bash
# PreToolUse hook: block dangerous commands from the rulecheck agent.
# Prevents force pushes, hard resets, git clean, and destructive rm operations.
#
# Input: JSON on stdin with tool_input.command
# Output: exit 0 to allow, exit 2 + stderr message to block.
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
# No command found — not a Bash tool call, allow
if [ -z "$COMMAND" ]; then
exit 0
fi
# Block git push --force / -f
if echo "$COMMAND" | grep -qE 'git\s+push\s+.*(-f|--force)'; then
echo "Blocked: force push is not allowed. Push normally or ask the user." >&2
exit 2
fi
# Block git clean -fd (explicit CLAUDE.md rule)
if echo "$COMMAND" | grep -qE 'git\s+clean'; then
echo "Blocked: git clean permanently deletes untracked files. Use 'git checkout .' instead." >&2
exit 2
fi
# Block git reset --hard
if echo "$COMMAND" | grep -qE 'git\s+reset\s+--hard'; then
echo "Blocked: git reset --hard discards all changes. Use a safer alternative." >&2
exit 2
fi
# Block rm -rf outside worktree (allow rm -rf within .claude/ or node_modules)
if echo "$COMMAND" | grep -qE 'rm\s+-rf?\s+/' | grep -vqE '(node_modules|\.claude/)'; then
echo "Blocked: rm -rf with absolute paths is not allowed from this agent." >&2
exit 2
fi
# Block destructive operations targeting main/master
if echo "$COMMAND" | grep -qE 'git\s+(push|branch\s+-[dD]|checkout)\s+.*(main|master)'; then
echo "Blocked: destructive operations on main/master are not allowed." >&2
exit 2
fi
exit 0
#!/bin/bash
# Stop hook: notify Slack with a summary of the rulecheck run.
# Extracts info from the stop event JSON (last_assistant_message) since
# the summary file may not exist yet when this hook fires.
#
# Input: JSON on stdin with stop event context
# Output: exit 0 always (notification failure should not block the agent)
#
# Uses SLACK_WEBHOOK_URL env var if set, otherwise falls back to hardcoded URL.
INPUT=$(cat)
if [ -z "$SLACK_WEBHOOK_URL" ]; then
# No webhook configured — skip notification silently
exit 0
fi
# Extract the last assistant message from the stop event
LAST_MESSAGE=$(echo "$INPUT" | jq -r '.last_assistant_message // empty' 2>/dev/null)
if [ -z "$LAST_MESSAGE" ]; then
LAST_MESSAGE="Rulecheck agent completed (no summary available)"
fi
# Try to extract a PR URL from the message
PR_URL=$(echo "$LAST_MESSAGE" | grep -oE 'https://github\.com/[^ ]+/pull/[0-9]+' | head -1)
if [ -n "$PR_URL" ]; then
PR_LINE="*PR*: <${PR_URL}|View Pull Request>"
else
PR_LINE="*PR*: No PR created"
fi
# Truncate message for Slack (max 3000 chars in a section)
SUMMARY=$(echo "$LAST_MESSAGE" | head -20 | cut -c1-2000)
PAYLOAD=$(jq -n \
--arg pr "$PR_LINE" \
--arg summary "$SUMMARY" \
'{
"blocks": [
{
"type": "header",
"text": { "type": "plain_text", "text": "Rulecheck Agent Run Complete" }
},
{
"type": "section",
"text": { "type": "mrkdwn", "text": $pr }
},
{
"type": "section",
"text": { "type": "mrkdwn", "text": $summary }
}
]
}')
# Send to Slack — don't let curl failure block the agent
curl -s -X POST "$SLACK_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d "$PAYLOAD" > /dev/null 2>&1 || true
exit 0
Rules Guide — Where to Find Project Rules
Reference for the rulecheck agent. Focus on rules that linters can't enforce — architectural principles, patterns, and conventions from CLAUDE.md.
Primary Source: CLAUDE.md (Root)
Read this file thoroughly. Every section contains enforceable rules.
Engineering Principles (each is a concrete rule, not a slogan)
| Principle | What to Look For |
|---|---|
| Fail Fast | Silent fallbacks, swallowed errors, catch blocks that return defaults instead of throwing, silently broadened permissions |
| KISS | Clever meta-programming, hidden dynamic behavior, convoluted control flow, magic that obscures intent |
| YAGNI | Config keys with no caller, speculative abstractions, feature flags for unplanned features, partial fake support |
| DRY + Rule of Three | Same pattern copy-pasted 3+ times without extraction; OR premature abstractions extracted from only 1-2 uses |
| SRP + ISP | God modules mixing policy/transport/storage, fat interfaces with unrelated methods, modules doing too many things |
| Determinism | Flaky tests with timing dependencies, network-dependent tests without guardrails |
| Reversibility | Mixed mega-patches, changes with unclear blast radius |
Logging Rules
| Rule | Violation |
|---|---|
| Use Pino structured logger | console.log, console.error, console.warn in production code |
Event naming: {domain}.{action}_{state} | Events like processing, handling, doing_stuff |
Standard states: _started, _completed, _failed | Unpaired events (a _started without matching _completed/_failed) |
| Never log secrets | Logging variables named token, key, password, secret without masking |
| Include context in logs | log.error("failed") without IDs, durations, or error details |
| Log levels matter | Using log.info for errors, or log.error for non-errors |
Error Handling Rules
| Rule | Violation |
|---|---|
| Log with structured context | catch(e) { throw e } without log.error({ err, contextId }) |
Use classifyIsolationError() | Git operation catch blocks that don't classify the error for users |
| Surface errors to users | Catch blocks that silently swallow without notifying the user |
| Include error type info | log.error({ error: err.message }) instead of log.error({ err, errorType: err.constructor.name, err }) |
| Clear error messages | throw new Error("failed") without saying what failed or why |
Import Rules
| Rule | Violation |
|---|---|
No generic import * from @archon/core | import * as core from '@archon/core' |
Use import type for type-only | import { MyType } from '...' when MyType is only used as a type |
| Namespace imports for submodules only | import * as conversationDb from '@archon/core/db/conversations' is fine |
| Specific named imports for values | import { handleMessage, pool } from '@archon/core' |
Git Safety Rules
| Rule | Violation |
|---|---|
Never git clean -fd | Any use of git clean (use git checkout . instead) |
Use execFileAsync not exec | exec("git ...") instead of execFileAsync("git", [...]) |
Use @archon/git functions | Direct git shell calls when an @archon/git function exists |
Violation Categories by Impact
Tier 1 — Critical (fix first)
- Swallowed errors — catch blocks that silently eat errors without logging or re-throwing
- Silent fallbacks — returning defaults for unexpected states instead of failing fast
- Missing error context — throw/log without IDs, descriptions, or structured data
- God modules — files mixing unrelated concerns (>300 lines doing multiple jobs)
Tier 2 — High (fix next)
- Wrong logger —
console.log/console.errorin production code instead of Pino - Bad log event names — events not following
{domain}.{action}_{state}convention - Missing error classification — git catch blocks without
classifyIsolationError() - *Generic `import
** — from@archon/core` instead of specific named imports
Tier 3 — Medium (fix if time permits)
- Unpaired log events —
_startedwithout corresponding_completed/_failed - DRY violations — same pattern in 3+ places without extraction
- Nested ternaries — should be if/else or switch
- Clever code — meta-programming or hidden dynamic behavior that obscures intent
- YAGNI violations — speculative code with no current caller
Tier 4 — Low (note for backlog)
- Missing `import type` — type-only imports without
typekeyword (often auto-fixable) - Inconsistent naming — doesn't follow project conventions
- Comment quality — obvious comments, outdated descriptions
What NOT to Check
These are already enforced by tooling — don't waste time on them:
- ESLint rules (return types, unused vars, etc.) —
bun run lintcatches these - TypeScript strict mode violations —
bun run type-checkcatches these - Formatting (quotes, commas, indentation) — Prettier handles this
Rulecheck — Workshop Guide
What This Skill Demonstrates
An autonomous code quality agent that combines 17 Claude Code features into one genuinely useful tool: custom agents, safety hooks, all four hook types (command, prompt, http, agent), LLM-as-judge, persistent memory, Slack notifications, and worktree isolation.
Replaces the existing advisory-only code-rulecheck agent with a fully autonomous version that finds violations, fixes them, validates, creates PRs, and learns.
Full demo steps: See part2-guide.md — Feature 8.
Architecture
User invokes /rulecheck [focus area]
│
▼
┌──────────────────────────┐
│ SKILL.md │ agent: rulecheck-agent
│ (orchestrator) │ disable-model-invocation: true
│ │ argument-hint: "[focus area]"
│ Launches agent, │
│ reports results │ NO context: fork
└────────┬─────────────────┘
│ delegates to agent
▼
┌──────────────────────────┐
│ rulecheck-agent.md │ isolation: worktree
│ (.claude/agents/) │ background: true
│ │ memory: project
│ model: sonnet │ permissionMode: acceptEdits
│ maxTurns: 500 │
│ │
│ hooks: │
│ ├─ PreToolUse [Bash] │──→ block-dangerous.sh (safety gate)
│ ├─ PostToolUse [Edit] │──→ bun run lint:fix (auto-fix)
│ └─ Stop │
│ ├─ command │──→ slack-notify.sh (reads summary JSON)
│ ├─ http │──→ POST to Slack webhook URL
│ └─ agent │──→ meta-judge (LLM evaluation)
└────────┬─────────────────┘
│ works in worktree
▼
┌──────────────────────────┐
│ Worktree │
│ 1. Read memory │
│ 2. Read CLAUDE.md rules │
│ 3. Deep scan source │
│ 4. Group violations │
│ 5. Fix one group │
│ 6. bun run validate │
│ 7. Write summary JSON │
│ 8. gh pr create │
│ 9. Update memory │
└──────────────────────────┘
│
▼
Results reported to main conversation
+ PR created + Slack notified + memory updatedFeatures to Walk Through
1. agent: rulecheck-agent — Custom Agent Delegation (no fork)
What is it? The agent: field delegates to a custom agent with its own system prompt, model, hooks, and memory configuration.
In this skill: The skill acts as an orchestrator — it launches the agent and reports results. There is no context: fork. The skill stays active in the main conversation while the agent runs in the background in its own worktree.
Why no fork? The rulecheck agent uses background: true and isolation: worktree, so it already runs in a completely separate context. Forking would add an unnecessary layer. The skill just launches and waits.
2. disable-model-invocation: true — User-Only Trigger
What is it? Prevents Claude from auto-invoking this skill. Since it creates PRs and pushes branches (side effects), only the user should trigger it.
3. argument-hint: "[focus area]" — Usage Hint
What is it? Shows in /help and tab completion to tell users what arguments the skill accepts. Optional — the agent works without arguments too.
4. !command`` — Dynamic Context Injection
What is it? Shell commands that execute at skill load time (before Claude sees the prompt). Stdout replaces the placeholder.
In this skill: Injects current branch, recent git log, and lint status so the agent starts with real context instead of having to fetch it.
5. Supporting Files — On-Demand Loading
What is it? Markdown files linked from the skill body with [name](file.md). Claude loads them only when needed, keeping the initial prompt small.
In this skill: rules-guide.md documents where to find rules and how to rank violations. The agent loads it during the scan phase.
6. isolation: worktree — Git Worktree Isolation
What is it? The agent works in a temporary git worktree — a separate working directory with its own branch. Changes are isolated from the main repo.
In this skill: The agent edits files and creates commits without affecting the user's working directory. If something goes wrong, the worktree is disposable.
7. background: true — Concurrent Execution
What is it? The agent runs in the background. The user can continue working in the main conversation while the agent scans, fixes, and creates a PR.
8. memory: project — Persistent Memory
What is it? The agent has a persistent memory directory at .claude/agent-memory/rulecheck-agent/. It reads from and writes to MEMORY.md across runs.
In this skill: The agent remembers what it fixed last time, what's in the backlog, and meta-judge feedback — so each run builds on the previous one.
9. permissionMode: acceptEdits — Auto-Accept Edits
What is it? File edits (Edit/Write tools) are automatically approved without user confirmation. Other tools still require approval per the normal flow.
In this skill: The agent needs to edit many files to fix violations. Prompting for each edit would defeat the purpose of autonomous execution.
10. maxTurns: 500 — Safety Cap
What is it? Limits the agent to 500 API round-trips. Prevents runaway agents that loop endlessly. Set high here because the agent does a lot of work (scan, fix, validate, commit, push, PR, memory update).
11. hooks: in Agent Frontmatter
What is it? Hooks defined directly in the agent's YAML frontmatter. They activate whenever this agent runs, regardless of which skill invokes it.
This skill demonstrates all four hook types:
11a. type: "command" — Shell Script Hooks
PreToolUse [Bash]: block-dangerous.sh reads the command from stdin, checks against a blocklist (force push, git clean, hard reset, rm -rf), and exits 2 to block dangerous commands.
PostToolUse [Edit|Write]: Runs bun run lint:fix after every file edit to auto-correct formatting issues before they accumulate.
Stop: slack-notify.sh reads the agent's summary file and sends a formatted Slack message with what was fixed, PR link, and remaining opportunities. This demonstrates inter-hook communication — the agent writes a JSON file, the hook reads it.
11b. type: "http" — HTTP Webhook
Stop: POSTs the event directly to a Slack webhook URL. No script needed — just a URL in the frontmatter. This is the simplest way to notify external services. Compare with 11a above: the command hook gives you full control over the message format, while the HTTP hook sends the raw event with zero code.
11c. type: "agent" — LLM Meta-Judge
Stop: A third Stop hook spawns a subagent that evaluates the rulecheck's execution. It reviews what was fixed, assesses prioritization quality, and writes structured feedback to memory for the next run.
12. statusMessage — Hook Progress Indicators
What is it? A string shown in the Claude Code spinner while a hook runs. Gives users visibility into what's happening during hook execution.
In this skill: "Checking command safety...", "Auto-fixing lint issues...", "Notifying Slack...", "Posting run event to Slack...", "Running meta-judge evaluation..."
13. $ARGUMENTS — Skill Arguments
What is it? The text after the skill name (e.g., /rulecheck error handling) is available as $ARGUMENTS in the skill body and passed through to the agent.
14. ${CLAUDE_SESSION_ID} — Session Identifier
What is it? Environment variable with the current session ID. Used in the meta-judge prompt to tag feedback with the session that produced it.
15. Summary File Pattern — Inter-Hook Communication
What is it? The agent writes .claude/archon/rulecheck-last-run.json as a structured summary. The Slack hook reads this file to format its notification.
This is a practical pattern for passing data between the agent and its hooks when the hook needs more than what's in the event JSON.
Live Demo Steps
1. Show the architecture — open all files:
.claude/skills/rulecheck/SKILL.md(skill entry point).claude/agents/rulecheck-agent.md(the autonomous agent).claude/skills/rulecheck/hooks/block-dangerous.sh(safety gate).claude/skills/rulecheck/hooks/slack-notify.sh(Slack notification).claude/skills/rulecheck/rules-guide.md(supporting reference)
2. Trace the delegation chain: skill → agent: rulecheck-agent → isolation: worktree + background: true
3. Show the hooks: PreToolUse safety gate, PostToolUse lint auto-fix, Stop Slack (command + http) + meta-judge (agent)
4. Test the safety hook:
echo '{"tool_input":{"command":"git push --force"}}' | .claude/skills/rulecheck/hooks/block-dangerous.sh
# Should exit 2 with error message
echo '{"tool_input":{"command":"bun run lint"}}' | .claude/skills/rulecheck/hooks/block-dangerous.sh
# Should exit 05. Invoke: /rulecheck type safety
- Show: background execution, user can keep working
- Show: the agent scanning, fixing, validating in the worktree
- Show: PR creation and Slack notification
6. Show the outputs:
- PR on GitHub
- Slack notification
- Memory file (what was learned)
- Meta-judge feedback
Comparison: Before vs After
| Advisory Code-Rulecheck | Autonomous Rulecheck | |
|---|---|---|
| Format | .claude/agents/code-rulecheck.md | Skill + agent + hooks |
| Execution | Inline, blocks conversation | Background, worktree-isolated |
| Output | Advisory report (no changes) | Actual fixes + PR |
| Isolation | None (reads in-place) | Git worktree |
| Safety | None | PreToolUse command blocklist |
| Validation | None | bun run validate |
| Notifications | None | Slack (command hook + HTTP hook) |
| Learning | None | Persistent memory + meta-judge |
| Autonomy | Reports findings only | Finds, fixes, validates, PRs |
Talking Points
- "This is 17 features in one skill. Each one is simple — the power is in composition."
- "The safety hook is a shell script. It reads JSON, checks a blocklist, exits 2 to block. No framework needed."
- "Memory makes the agent better over time. Each run builds on the last — it remembers what's in the backlog."
- "The meta-judge is an LLM evaluating another LLM. It writes structured feedback the agent reads next run."
- "Worktree isolation means the agent can break things safely. Your working directory is untouched."
- "Background execution means you keep working. The agent runs, creates a PR, notifies Slack — you review when ready."
- "The old code-rulecheck was advisory. This one actually fixes things. Same domain, fundamentally different capability."