From hackify
Audit an existing or new codebase against its engineering laws — hard caps (function/file/param/nesting), zero-tolerance bans (lint suppressions, non-null `!`, empty catches, bare Error throws, secrets, inline types in scoped modules), plus DRY, naming, layering, single-responsibility, folder-structure, and file-scoping rules. Reads the rule set at audit time from the project's OWN harness (.claude/rules, ban-patterns.txt, CLAUDE.md/AGENTS.md), stricter-wins fallback to global doctrine; runs a deterministic scanner plus semantic subagents; reports every finding with file:line by category/severity, then fixes them one at a time with your approval. Use when the user wants to check, audit, validate, or enforce engineering rules/standards/conventions across a project — e.g. "audit my code against our rules", "does this follow CLAUDE.md", "find all rule violations", "validate the architecture". FULL-CODEBASE sweep — NOT for generating a project's CLAUDE.md/rules, NOT for a single PR diff (use code-review).
How this skill is triggered — by the user, by Claude, or both
Slash command
/hackify:lawkeeperThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Audit a whole project against the engineering laws it is supposed to obey, then fix the
assets/report-template.mdevals/corpus/README.mdevals/corpus/ground-truth.jsonevals/corpus/project/backend/auth/auth.service.tsevals/corpus/project/backend/billing/billing.service.tsevals/corpus/project/backend/config.tsevals/corpus/project/backend/legacy/cleanup.tsevals/corpus/project/backend/legacy/oversized.tsevals/corpus/project/backend/legacy/report.tsevals/corpus/project/backend/migrations/0001_init.tsevals/corpus/project/backend/orders/orders.service.tsevals/corpus/project/backend/package.jsonevals/corpus/project/backend/shared/env.tsevals/corpus/project/backend/shared/flags.tsevals/corpus/project/backend/shared/render.tsevals/corpus/project/backend/shared/transport.tsevals/corpus/project/backend/users/users.controller.tsevals/corpus/project/backend/users/users.repository.tsevals/corpus/project/backend/users/users.service.tsevals/corpus/project/backend/users/users.test.tsAudit a whole project against the engineering laws it is supposed to obey, then fix the violations with the maintainer in the loop. It reads the rules the project already documents (or the global doctrine) and checks the code against them — it does not author the rules, it enforces them.
CLAUDE.md may
add rules (e.g. a folder topology) or tighten a cap; it may not relax a ban. On any
conflict between global and project, apply the stricter rule.references/carve-outs.md.file:line. Judgment calls come from subagents that quote the rule and the code.
Nothing is reported on a hunch; every finding is verifiable.Scripts and references live in this skill's own directory, <skill-dir>. Resolve <skill-dir>
from the Base directory for this skill: line surfaced when the skill loads; if that line is
absent, fall back to find "$HOME/.claude" "$HOME/Code" -type f -path "*/skills/lawkeeper/SKILL.md" | head -1 | xargs dirname. Reference each file when the phase that needs it arrives — do not
preload them.
~ or a non-project
directory, ask which project to audit.Build the rule set the audit will enforce, in this precedence (stricter wins):
.claude/rules/*, .claude/hooks/ban-patterns.txt, root + .claude/ CLAUDE.md, AGENTS.md, plus .cursorrules / .github/copilot-instructions.md if present.~/.claude/CLAUDE.md and any always-on hard-caps hook.Extract:
ban-patterns.txt verbatim if present (grep-ERE format); the
scanner is handed this file so the bans are the project's, not a hardcoded duplicate.template-reference/, FE
react-refresh / typed-route exceptions, do-not-extract floors.Produce a short effective-ruleset summary (caps, ban count, topology source, carve-outs)
and show it before scanning, so the maintainer can confirm you are enforcing the right rules.
references/rule-catalog.md maps every rule_id to its category, severity, detection engine,
and canonical source.
Run the bundled scanner through the shell primitive — do not hand-derive these checks. The
scanner is a Python program, so this is the one phase that assumes a python3 interpreter on
PATH (the only host dependency lawkeeper adds beyond the shell itself; see the host-interpreter
note in skills/hackify/references/runtime-adapters.md). Pass the resolved config:
python3 <skill-dir>/scripts/audit_scan.py <project_root> \
--max-file-lines <cap> \
--ban-patterns <project>/.claude/hooks/ban-patterns.txt # omit if none
It emits one JSON object: {schema_version, root, config, stats, findings[]}. Each finding
carries rule_id, category, severity, confidence, file, line, end_line, message, snippet, fixable. It covers what a regex matches exactly — file line-count and the token bans
(suppressions, empty catch, bare Error, non-null !, inline type in scoped modules, hardcoded
secrets). Secrets are redacted in the snippet. The scanner already applies the path carve-outs.
Most findings are confidence: exact; the two marked confidence: syntactic (ban.bare-error,
ban.inline-type) are matched exactly but need a one-step check before you act — is the throw
in domain code, does the type have 2+ props.
If python3 is absent — rare on a dev machine, possible on a locked-down best-effort
runtime — say so in the report and fall through to the semantic pass: the Phase 3 judgment
rules are interpreter-free and still run. Never drop the deterministic checks silently; an
audit that skips a whole engine without recording it reads as "clean" when it isn't.
The bundled scanner's full check suite is ECMAScript-family only. Pick the path by the project's primary language (from Phase 1 / a quick manifest glance):
--text-only-ext .py --text-only-ext .go (etc.). Those files get ONLY the file-line cap and
the project's ban-patterns.txt; the JS-construct checks are skipped so nothing misfires.references/porting-scanner.md: it
mirrors the bundled scanner's concepts (a language-appropriate comment/string masker, that
language's suppression / empty-catch / bare-throw / inline-type analogs, the universal secret
regexes, the same path carve-outs) and emits the SAME finding JSON schema. Write it under a
fresh temp dir (mktemp -d), run it, parse its JSON exactly like the bundled scanner's, and
delete the temp dir in Phase 6. These are ephemeral, single-session scripts — never written
into the audited project, never left behind.The scanner deliberately stops where precision would require a real parser or understanding.
First reuse what the project already has: if .claude/agents/ holds installed review
agents (security-auditor, performance-auditor, cleanup-scout, code-reviewer), dispatch
THOSE for their concern rather than re-deriving it — they encode the project's exact rules.
Fall back to the built-in concern prompts only where an agent is absent. Then fan out subagents
(one per concern, in a single message), reading references/semantic-pass.md for the per-rule
prompt, severity, and — critically — the exemption floors each must honor:
max-lines-per-function / max-params / max-depth,
Biome equivalents) — it is exact. Otherwise a subagent estimates and flags candidates.references/carve-outs.md).// removed: and
ownerless TODO/FIXME).Each subagent returns structured findings in the same shape as the scanner (rule_id, file, line, severity, evidence) so Phase 4 can merge them uniformly. Scope the pass to the whole tree by default, or to a path/changed-set if the user asked for that.
Merge deterministic + semantic findings, drop duplicates (same file+line+rule), and render
the report from assets/report-template.md: a header with totals per category and severity,
then findings grouped Folder-Structure / Code-Styles / File-Scoping, each with file:line,
the rule, the evidence, and the fix posture. Lead with critical/security findings. Present it
and stop — this is the natural review point (§5.3). Do not start fixing unprompted.
Work findings in severity order. For each finding or tight cluster, follow §5.2: state the
problem with file:line, present 2-3 concrete options (including "do nothing" where
reasonable) with effort/risk/impact, recommend the first, and ask before writing. Batch the
questions — group similar findings into one wizard tool round (≤4 questions), numbered by
issue and lettered by option, recommended option first. Apply only approved fixes, using the
project's existing patterns (a fix must read as if the original author wrote it). After each
batch, re-run the relevant test/lint/typecheck legs to prove the fix is clean.
Reality check on fixability: splitting a 500-line file, extracting a function, removing a !,
or filling an empty catch are real changes that need judgment, not blind rewrites — they all
go through propose-confirm. Only a tiny set (extract a magic literal, drop a dead import,
delete a // removed: comment) is trivially safe, and even those are shown before applying.
When a finding's fix is substantive on its own — splitting a 500-line file, unwinding an N+1, layering surgery — name that it deserves more than an inline propose-confirm: offer the maintainer a compressed clarify → implement → verify pass for it rather than folding a real structural change into the audit. lawkeeper never calls sibling skills, so this is a framing you offer (and a separate task the user opts into), not a handoff you perform.
Re-run the deterministic scanner to confirm fixed findings are gone and none were introduced. Run the project's full verification triad (lint / typecheck / test) on the touched scope. Print a summary table: findings by category before/after, what was fixed, what was deferred (and why), and any rule the maintainer chose to waive. If the project has no edit-time enforcement (a PreToolUse hook that blocks banned tokens as they are written), suggest adding one so new violations are prevented rather than found later.
Clean up. Delete any on-demand scanner temp dir created in Phase 2 (rm -rf the mktemp -d
path). The audit leaves nothing behind in the project or in temp — only the report and the
approved fixes.
<skill-dir> (resolved at the top of this file from the
Base directory for this skill: line) — never hardcode an absolute user path..ts/.tsx/.js/.jsx/.mts/.cts/.mjs/.cjs). For any other extension passed via
--text-only-ext, it runs ONLY the language-agnostic checks — file-line cap and the
project's ban-patterns.txt — because the JS lexer and the built-in token bans would
misfire on other syntax. Deep deterministic coverage of a non-JS stack is done by the
on-demand scanner from Phase 2 (references/porting-scanner.md). The workflow and the
semantic pass are fully language-agnostic.npx claudepluginhub nadyshalaby/hackify --plugin hackify-edgeGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.