npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@alexcodeplace/slopgate

v0.3.3

Published

Global code-quality / anti-slop gate — engine shared, rules per-project.

Readme

slopgate

A global code-quality / anti-slop gate for Claude Code and git. Engine is shared, rules are per-project.

What it does: Catches code quality violations in two tiers — a fast post-edit scan (regex + AST rules, instant feedback) and a heavy commit-tier scan (static type checkers, dead-code analysis, architecture rules, copy-paste detection). A ratchet baseline lets legacy repos adopt without flooding — only NEW violations block commits; pre-existing ones are baselined and tracked for paydown.


Features

  • Two-tier gate

    • Fast tier (post-edit hook): regex patterns + AST rules, instant feedback as you code
    • Commit tier (pre-commit hook): includes heavy checkers (tsc, knip, jscpd, dependency-cruiser, type-coverage, diff-shape) + AST + regex, blocks commits
  • Ratchet baseline — snapshot violations at adoption time; only NEW violations fail the gate. Track debt paydown over time.

  • Six commit-tier checkers

    • tsc — TypeScript type errors (full-project scope)
    • knip — dead/unused code (exports, files, dependencies)
    • jscpd — copy-paste duplication (token-level)
    • dependency-cruiser — architecture rules (cycles, orphans, layer boundaries)
    • type-coverage — propagation of any type (per-expression tracking)
    • diff-shape — wide commits spanning too many directories (encourages focused changes)
  • Shared regex + AST rule packs — fast-tier and commit-tier both run these

    • Convention: no-stubs, ts-suppress, as-any, no-narration-comments, raw-hex (design tokens), sql-safety
    • Security: live-secrets, eval-ban, pii-logs, weak-hash
    • Cloudflare boundary: kv-ban (plus the opt-in stack = ["cloudflare"] pack)
    • Built-in AST rules: empty-catch, unsafe innerHTML/dangerouslySetInnerHTML, target="_blank" without rel, window access during render
  • Native git pre-commit hook — no daemon, no CI coupling, just git

  • Claude Code integration — hooks into PreToolUse (commit) and PostToolUse (edit) events

  • Suppressions — per-file, per-line, with line-hash stability across edits

  • Self-testslopgate --self-test validates rule engines + baseline checker parsers against bundled fixtures


Install

npm install -g slopgate

The matching prebuilt native engine for your platform (linux / macOS / Windows × x64 / arm64) is pulled in automatically as an optional dependency — no toolchain or build step required.

Then onboard a project:

slopgate init [path-to-repo]

This:

  1. Detects TypeScript roots, file extensions, and package layout
  2. Scaffolds .slopgate/config.toml with detected checkers enabled
  3. Writes .slopgate/suppressions.json and .slopgate/depcruise.cjs (starter)
  4. Creates .slopgate/convention-sources.json (hints for authoring project rules from local skills/agents/docs)
  5. Creates .slopgate/rules/ast/ and .slopgate/fixtures/src/ directories
  6. Installs git pre-commit hook (or appends to existing)
  7. Merges Claude Code hook settings into .claude/settings.json
  8. Prints next steps (including: run slopgate baseline --config .slopgate/config.toml)

Quickstart

Run the gate on staged changes (pre-commit):

slopgate --staged --config .slopgate/config.toml

Run on a single file (post-edit, fast tier):

slopgate --file src/app.ts --config .slopgate/config.toml

Create/update the baseline:

# Create baseline (refuses if it exists)
slopgate baseline --config .slopgate/config.toml

# Update baseline (re-snapshot all current violations)
slopgate baseline --update --config .slopgate/config.toml

# Prune baseline (remove entries no longer occurring)
slopgate baseline --prune --config .slopgate/config.toml

Run self-test (validate the engine against bundled fixtures):

slopgate --self-test --config "$(npm root -g)/slopgate/rules/baseline/selftest.config.toml"

Run immutable full-repository CI gate:

slopgate scan --scope repo --tier commit --format github --config .slopgate/config.toml

Record reviewer defects and enforce rule harvesting:

slopgate defect record --class missing-button-type --file src/app.tsx --line 42 --source code-review --config .slopgate/config.toml
slopgate harvest --check --config .slopgate/config.toml

Second distinct occurrence requires .slopgate/rules/ast/<class>.yml plus .slopgate/fixtures/<class>.invalid.ts[x] and <class>.valid.ts[x]. --self-test proves rule fires on configured fixtures.

Reusable GitHub gate:

jobs:
  slopgate:
    uses: alexcodeplace/slopgate/.github/workflows/slopgate.yml@v1

Self-hosted jobs reject fork pull requests before checkout. Use repository-owned branches or isolated disposable runners for untrusted forks.

Install or reinstall hooks:

slopgate install-hooks --config .slopgate/config.toml

Command Reference

slopgate init [dir]

Onboard a new repository. Detects roots, extensions, installed checkers, and scaffolds project structure.

Args:

  • dir (optional) — target directory; defaults to process.cwd()
  • No --config required; generates config during init

Creates:

  • .slopgate/config.toml — project config (roots, extensions, rule packs, checkers, baseline/suppressions paths)
  • .slopgate/suppressions.json — line-level violation suppressions (empty initially)
  • .slopgate/depcruise.cjs — starter dependency-cruiser rules (if depcruise detected)
  • .slopgate/convention-sources.json — hints for authoring project-specific rule packs
  • .slopgate/rules/ast/ and .slopgate/fixtures/src/ — directories for custom rules and fixtures
  • .git/hooks/pre-commit — native git pre-commit hook (creates new or appends to existing)
  • .claude/settings.json — Claude Code hook entries (idempotent merge)

Next step: Run slopgate baseline --config .slopgate/config.toml to create the initial ratchet baseline


slopgate --staged --config <path>

Run commit-tier gate on staged files. Used by git pre-commit hook and Claude Code PreToolUse hook.

Flags:

  • --config <path> (required) — path to .slopgate/config.toml
  • --tier fast|commit (optional) — override default tier (default: commit for --staged)

Exit codes:

  • 0 — no violations (or all baselined/suppressed)
  • 1 — violations block the commit
  • 2 — config error or missing argument

Output:

  • Violations grouped by source (regex, ast, checker:tsc, etc.)
  • Baselined count footer
  • Skipped checkers (if tool/config missing)

slopgate --file <path> --config <path>

Run fast-tier gate on a single file (post-edit). Used by Claude Code PostToolUse hook.

Flags:

  • --file <path> (required) — repo-relative path to check
  • --config <path> (required) — path to .slopgate/config.toml
  • --tier fast|commit (optional) — override default tier (default: fast for --file)

Exit codes: same as --staged

Output: violations in the touched file only; no baseline filtering


slopgate baseline --config <path> [--update] [--prune]

Manage the ratchet baseline.

Flags:

  • --config <path> (required)
  • --update — re-snapshot all current violations (overwrites baseline)
  • --prune — remove entries whose fingerprint no longer occurs (dry-run only)
  • Both flags can be combined; --prune --update prunes then updates

Behavior:

  • No flags, file missing → create baseline with current violations
  • No flags, file exists → error (refuses overwrite; use --update)
  • --update → snapshot all violations in full commit tier scan
  • --prune → drop resolved fingerprints (non-destructive; just removes old entries)

slopgate install-hooks --config <path>

Install or upgrade the git pre-commit hook.

Flags:

  • --config <path> (required)

Behavior:

  • No hook exists → create new hook with slopgate check
  • Hook exists with slopgate marker → upgrade (idempotent)
  • Foreign hook exists → append slopgate block before final exec (preserves other hooks)

Hook location: <git-dir>/hooks/pre-commit (or respects git config core.hooksPath)


slopgate --self-test --config <path>

Internal: validate regex + AST engines and checker parsers against fixtures.

Flags:

  • --config <path> (required) — typically rules/baseline/selftest.config.toml

Runs in-process tests; exit 0 = all pass, exit 1 = failure. Used by npm run self-test.


How the Two Tiers Work

Fast Tier (Post-Edit)

Runs on every Edit/Write to a .ts, .tsx, or .astro file.

Scope: Single file Engines: Regex patterns + AST rules (baseline packs only) Baseline: Not consulted (all violations shown) Latency: < 1 second Feedback: Instant, in-editor

Rules applied:

  • All regex patterns in enabled baseline packs (no-stubs, ts-suppress, as-any, etc.)
  • All AST rules from enabled baseline packs
  • Project-owned AST rules (from astRules config)

Commit Tier (Pre-Commit)

Runs before git commit or when --staged is called manually.

Scope: All staged files + full repo (for checkers like tsc, knip that need graph context) Engines: Regex patterns + AST rules + six heavy checkers Baseline: Consulted; only NEW violations block commit Latency: 5–30 seconds (tsc + knip dominate) Feedback: Commit blocked or passes

Rules applied:

  • All regex patterns (same as fast tier)
  • All AST rules (same as fast tier)
  • tsc — TypeScript type errors (full-project compile)
  • knip — unused exports/files/dependencies
  • jscpd — copy-paste clones (staged files only are reported)
  • dependency-cruiser — architecture violations
  • type-coverage — NEW uncovered expressions
  • diff-shape — staged files spanning > N top-level dirs

Filtering:

  1. Run all sources (regex, ast, checkers)
  2. Fingerprint violations (sha256 of source, rule, file, normalized message, line text)
  3. Filter by ratchet baseline (drop fingerprints in baseline.json)
  4. Filter by suppressions (line-level, per file + lineHash)
  5. Filter by severity gate (only show critical/high by default, configurable)
  6. Print report; exit 1 if violations remain

Ratchet Baseline

The ratchet prevents violations from blocking adoption of new rules or onboarding legacy repos.

How It Works

  1. At init: slopgate baseline --config ... creates .slopgate/baseline.json with a snapshot of ALL current violations.

  2. On commit: The gate compares the current full-repo commit-tier scan against the baseline. Violations whose fingerprint is in the baseline are ignored (baselined); NEW violations block the commit.

  3. Paydown: As issues are fixed, their fingerprint disappears from the current scan. slopgate baseline --prune removes old entries from the baseline, lowering the bar.

  4. Re-snapshot: slopgate baseline --update does a full re-scan and updates the baseline (use after intentionally widening rules or adding new checkers).

Fingerprint Stability

Fingerprints include:

  • Rule ID
  • File path (repo-relative)
  • Normalized message (digit runs replaced with #, kills line/col churn)
  • First 60 chars of the source line (trimmed)

Fingerprints do NOT include the line number, so they survive unrelated edits shifting lines.

Suppressions vs. Baseline

  • Baseline — temporary allowlist; debt should be paid down over time. Track in version control. Entire project-wide snapshot.
  • Suppressions — permanent per-file exemptions (e.g., "this pattern is correct in this context"). Sparse, line-level. Also tracked.

UX Module (optional)

The UX module provides opinionated static analysis rules for common UX anti-patterns. It is off by default since UX preferences vary across teams and projects. Enable selectively via the ux:{} config namespace.

Why optional? Many teams have different UX preferences, and enabling UX rules on existing projects would flag pre-existing markup. These are good-enough defaults for NEW projects where you want opinionated UX guidance but have no specific opinion yourself.

Configuration

# .slopgate/config.toml
# ... other config

# UX module (optional) — off by default, opt-in per sub-module
[ux]
a11y = "high"        # Accessibility violations (gate commits)
cls = "high"         # Cumulative Layout Shift violations (gate commits)
feedback = "high"    # Silent async / double-submit (gate commits)
taste = "advisory"   # Design taste violations (report only, don't gate)
advisory = "advisory" # Heuristic nudges (report only, higher false-positive)
# taste = "medium"   # equivalent to 'advisory'
# taste = true       # use sub-module default severity
# omit key = that sub-module OFF
# delete whole [ux] table = entire module OFF

Sub-modules

| Key | Catches | Default Severity | Framework § | |-----|---------|------------------|-------------| | a11y | onClick on <div>/<span> without role; <a onClick> without href; <img> without alt; <button> without type; positive tabIndex | high | §11 | | cls | <img>/<video>/<iframe> without width/height | high | §13 | | feedback | async onClick on a <button> with no disabled state (double-submit, silent wait) | high | §3/§12 | | taste | emoji in UI, "trusted by" clichés, Lorem ipsum, robotic microcopy, heavy drop shadows, linear/long (>300ms) motion | medium | §0/§6/§26 | | advisory | modal without onClose; array index as React key; view state (tab/page/filter) in useState instead of the URL | medium | §10/§14 |

Magic hardcoded colors/spacing (#hex, rgb()/hsl(), multi-digit px) are caught by the baseline raw-hex pack (§15), independent of the UX module.

Severity Levels

  • 'critical'/'high': Gates commits (blocks by default, since default gate is ['critical','high'])
  • 'medium'/'advisory': Reports but doesn't block commits (useful for gradual adoption)
  • true: Use the sub-module's default severity
  • Omit key: That sub-module is OFF
  • Delete ux:{} block: Entire UX module is OFF

Opt-out

Symmetric and trivial:

  • Delete a key to disable one sub-module: ux: { a11y: 'high' } (cls and taste OFF)
  • Delete the whole ux:{} block to disable the entire module

Companion Skill

Pair the static UX module with the /slopgate-ux skill for semantic UX directives that static analysis can't enforce (four-states, button hierarchy, focus-trap, optimistic UI, etc.).


Config Reference (.slopgate/config.toml)

# Repository layout
roots = ["src"]                          # source roots to scan
exts = [".ts", ".tsx", ".astro"]         # file extensions
skipDirs = ["node_modules", "dist"]      # dirs to skip

# Rule packs
baseline = ["no-stubs", "ts-suppress", "as-any"]  # built-in baseline packs to enable (opt-in)
rules = []                               # project regex rule packs — must be [] (PHASE-2, not yet supported)
astRules = "./rules/ast"                 # dir of .yml AST rules (optional)
astDisable = []                          # rule ids to disable (escape hatch)

# Custom file paths (relative to repo root)
suppressions = "./suppressions.json"     # line-level exemptions
fixtures = "./fixtures"                  # test fixture canaries
# baselinePath is auto-computed: .slopgate/baseline.json

# Commit-tier checkers (detected at init; absent = off)
# Per-checker options as key = value under each [checkers.<name>] table.
[checkers.tsc]
# e.g. timeout = 60

# UX module (optional) — off by default, opt-in per sub-module
[ux]
a11y = "high"        # accessibility violations
cls = "high"         # cumulative layout shift
taste = "advisory"   # design taste (reports, doesn't gate)

# Severity filtering (which violations show in reports)
[gate]
file = ["critical", "high"]    # fast-tier report threshold
staged = ["critical", "high"]  # commit-tier report threshold

Auto-generated during init:

  • roots — detected from workspace packages and src/ dirs
  • exts — detected from file walk
  • skipDirs — detected from common exclusions (node_modules, dist, tests, .worktrees)
  • checkers — detected from installed binaries and config files (all true initially)

Rule Packs

Baseline Regex Packs (Shipped)

All are opt-in via the baseline array in config. Severity drives the gate threshold (critical/high block by default).

| Pack | Severity | Category | Catches | |------|----------|----------|---------| | no-stubs | critical | convention | Stub / placeholder / "not implemented" / deferred-work markers | | ts-suppress | high | convention | @ts-ignore / @ts-expect-error — suppressing tsc instead of fixing the cause | | as-any | high | convention | as any casts that disable type safety | | no-narration-comments | high | convention | Comments that narrate a diff/history/removal (changed from, used to, no longer needed, track later) instead of explaining a non-obvious constraint | | raw-hex | high | convention | Hardcoded hex / rgb() colors + raw multi-digit px — use design tokens | | sql-safety | critical | convention | SELECT … FOR UPDATE with an aggregate (Postgres rejects this at runtime) | | kv-ban | critical | boundary | Cloudflare KV in read-after-write paths (eventually-consistent) | | live-secrets | critical | security | Hardcoded Stripe / webhook / Google live credentials | | eval-ban | critical | security | eval / dynamic code execution (injection surface) | | pii-logs | high | security | PII fields written to logs / error trackers | | weak-hash | high | security | MD5 / SHA-1 for integrity checks or passwords (cryptographically broken) |

Baseline AST Rules (Shipped, Always Active)

Loaded automatically alongside the regex packs (the resolver always adds rules/baseline/ast); disable any by id via astDisable = [...].

| Rule id | Catches | |---------|---------| | empty-catch (ts + tsx) | Empty catch block silently swallowing an error | | inner-html | Unsafe innerHTML / dangerouslySetInnerHTML assignment | | target-blank-norel | target="_blank" anchor missing rel="noopener" | | window-in-render | window/document access during render (SSR hazard) |

Stack Packs (Shipped)

Opt-in via stack = ["cloudflare"]:

| Pack | Rule ids | |------|----------| | cloudflare | cf-env-spread-secrets, process-env-access, waituntil-bare-method-ref, cf-getCloudflareContext-banned, hono-env-direct-access |

Planned (v2+):

  • Depth rules — pass-through-fn, delegating-wrapper (Ousterhout symptoms)
  • Test-slop rules — test-no-assertion, test-skip-only
  • Custom project regex rule packs (the rules = [...] field — see Project-Owned Rules)

Project-Owned Rules

Add custom rules as AST rules.yml files in ast-grep syntax:

id: my-ast-rule
language: tsx
severity: error          # ast-grep level (error|warning|info)
message: Rule violation
note: '{"severity":"high","category":"convention","resolution":"…"}'  # slopgate metadata
rule:
  pattern: 'someBadCall($$$ARGS)'   # code-snippet matcher; or structural kind/has/inside/all/any/not

Point astRules at the directory holding them:

astRules = "./rules/ast"  # auto-loads all .yml files in this dir

Note: Custom project regex rule packs (the rules = [...] field) are not yet supported by the native engine. rules must currently be []; a non-empty value errors with slopgate: project rule pack "<path>" cannot be loaded by the native TOML resolver (PHASE-2: project rule packs). Project regex packs are planned (PHASE-2). For now, use ast-grep YAML for custom rules, or one of the built-in baseline/stack packs.


How Rules Are Authored

Regex Rules

Note: Authoring custom project regex rule packs is not yet supported by the native engine (PHASE-2 — see Project-Owned Rules). The shape below describes how the built-in regex packs are defined (compiled into the engine); it is reference, not a workflow you can wire in via rules today. Use ast-grep YAML for custom rules.

Patterns are regex strings with flags (i, m, s, etc.). A pattern matches any line containing the regex.

Example:

{
  id: 'no-stubs-placeholder',
  pattern: 'placeholder\\s+(?:for now|impl)',
  flags: 'i',
  canary: '// placeholder for now',
  negativeCanary: ['placeholder={t(\'x\')}'],  // should NOT match
}

Advanced:

  • minFiles: N — pattern must match in ≥ N files to fire (catch widespread slop)
  • excludeGlobs: ['*.test.ts'] — skip matching in these paths
  • includeGlobs: ['src/**'] — only match in these paths
  • Suppressions: per-file, per-line (lineHash = sha256 of line text)

AST Rules

Written in ast-grep YAML syntax; scoped to source roots + extensions from config.

Example (modeled on the shipped rules/baseline/ast/empty-catch-block-tsx.yml):

id: empty-catch
language: tsx
severity: error          # ast-grep level (error|warning|info)
message: Empty catch block swallows error silently
note: '{"severity":"high","category":"convention","resolution":"Handle or rethrow; log with context."}'
rule:
  pattern: 'try { $A } catch ($E) {}'   # code-snippet matcher; or structural kind/has/inside/all/any/not

The top-level severity is ast-grep's own level; slopgate's gating severity/category/resolution live in the JSON note field.

Fixtures: add a source canary that triggers the rule to .slopgate/fixtures/src/ (built-in rules use rules/baseline/fixtures/src/). A .ts/.tsx file containing the violating code is enough:

// .slopgate/fixtures/src/empty-catch.tsx
export function f() { try { risky(); } catch (e) {} }  // should fire empty-catch

slopgate --self-test --config .slopgate/config.toml scans the fixtures and asserts every rule fires at least once.


Hooks Integration

Claude Code Hooks

Init wires slopgate into .claude/settings.json:

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [
        {
          "type": "command",
          "command": "/path/to/slopgate/hooks/commit-hook.sh"
        }
      ]
    }],
    "PostToolUse": [{
      "matcher": "Edit|Write",
      "hooks": [
        {
          "type": "command",
          "command": "/path/to/slopgate/hooks/edit-hook.sh"
        }
      ]
    }]
  }
}
  • PreToolUse (commit-hook.sh) — fires before Bash tool use; checks for git commit in the command and runs slopgate --staged
  • PostToolUse (edit-hook.sh) — fires after Edit/Write; runs slopgate --file on the touched file (fast tier, 5-second timeout)

Git Pre-Commit Hook

init also installs .git/hooks/pre-commit (or appends to existing). This is the native git hook; it catches commits from any tool (terminal, IDE, other agents).

#!/usr/bin/env bash
ROOT=$(git rev-parse --show-toplevel) || exit 0
CONFIG="$ROOT/.slopgate/config.toml"
[ -f "$CONFIG" ] || exit 0
exec slopgate --staged --config "$CONFIG"

The hook can be bypassed with git commit --no-verify, which is intentional (user-initiated escape hatch).


Suppressions

Edit .slopgate/suppressions.json:

{
  "version": 1,
  "entries": [
    {
      "ruleId": "no-stubs-placeholder",
      "file": "src/app.ts",
      "lineHash": "abc123def..."
    }
  ]
}

Line hash is auto-generated: sha256(trimmedLine).slice(0, 16).

To suppress a violation, grab the line hash from the report and add an entry. The line text must match exactly (trimmed); unrelated edits shift line numbers but keep line text stable.


Testing

Run Self-Test

npm run self-test

Validates:

  • Regex engine (patterns match canaries, skip negativeCanaries)
  • AST engine (ast-grep rules parse + match fixtures)
  • Checker parsers (tsc, knip, jscpd, depcruise, type-coverage outputs parse correctly)
  • Ratchet fingerprints (stability under line shifts)
  • Suppressions (line hashing, deduplication)

Examples

Example 1: Block Unsafe Type Casts

Config:

baseline = ["as-any"]
[gate]
staged = ["critical", "high"]

Commit a file with const x = y as any;:

slopgate: 1 violation(s)

regex › as-any-cast
  src/utils.ts:42
  Unsafe `as any` cast
  severity: high
  resolution: Use a precise type or a discriminated narrowing.

exit code: 1 (commit blocked)

Fix it to const x = y as unknown; or a proper type, then commit.

Example 2: Allow Pre-Existing Copy-Paste, Block New Ones

Config:

baseline = []
[checkers.jscpd]
minTokens = 50

Run slopgate baseline --config .slopgate/config.toml to baseline existing clones. Now:

  • Commits pass unless they introduce NEW duplications
  • Track paydown via slopgate baseline --prune (drops resolved entries)

Example 3: Custom Architecture Rules

Create .slopgate/depcruise.cjs:

module.exports = {
  forbidden: [
    {
      name: 'no-ui-to-db',
      severity: 'error',
      from: { path: 'src/ui' },
      to: { path: 'src/db' },
    },
  ],
};

Now commits that import database code from UI layer are blocked.

Example 4: Silence a Built-in Rule in One Project

Config:

baseline = ["no-stubs", "as-any"]
astDisable = ["target-blank-norel"]  # this app links only to vetted internal routes

astDisable lists built-in AST rule ids to turn off for this repo; every other rule stays active.


Architecture

Data Flow (Commit Tier)

git commit
  └─ .git/hooks/pre-commit
       └─ slopgate --staged --config <repo>/.slopgate/config.toml
            ├─ Enumerate staged files
            ├─ Regex engine (patterns → violations)
            ├─ AST engine (ast-grep rules → violations)
            ├─ Checker adapters
            │  ├─ tsc (type errors)
            │  ├─ knip (dead code)
            │  ├─ jscpd (duplication)
            │  ├─ dependency-cruiser (architecture)
            │  ├─ type-coverage (any propagation)
            │  └─ diff-shape (mixed concerns)
            ├─ Ratchet baseline filter (drop pre-existing)
            ├─ Suppressions filter (per-file, per-line)
            ├─ Severity gate (critical/high)
            └─ Report + exit code (0 = pass, 1 = blocked)

Checker Timeout and Errors

Each checker has a per-tool timeout (configurable):

  • tsc: 120s
  • knip: 90s
  • jscpd: 60s
  • depcruise: 60s
  • type-coverage: 120s

Tool crash / timeout → ⚠ skipped: <id> (<reason>) warning, gate continues (fail-open on infra). Violations still block; missing tools don't.


Limitations & Future Work

  • Git-only — no other VCS support
  • No auto-fix — violations are reported, not automatically corrected
  • slopgate audit command — planned for v2 (non-gating architecture-health report: hotspots, module shape, co-change coupling, ratchet progress tracking)
  • Embeddings-based semantic duplicate detection — planned, not in v1
  • API-surface diff gate — track breaking changes to public exports (future)
  • LLM-judge skill — on-demand deep review of architectural debt (separate sub-project)

Contributing

See CONTRIBUTING.md.


License

MIT — See LICENSE for details.