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

cc-loopkit

v0.1.1

Published

A self-correcting harness around Claude Code — guardrails, post-edit hygiene, and loops that won't let a task finish until it's actually done. Installs into any project.

Downloads

19

Readme

Claude Code Loopkit

  ____ ____      _     ___   ___  ____  _  _____ _____
 / ___/ ___|    | |   / _ \ / _ \|  _ \| |/ /_ _|_   _|
| |  | |   _____| |  | | | | | | | |_) | ' / | |  | |
| |__| |__|_____| |__| |_| | |_| |  __/| . \ | |  | |
 \____\____|    |_____\___/ \___/|_|   |_|\_\___| |_|

A self-correcting harness around Claude Code: guardrails that stop bad actions before they happen, hygiene that runs after every edit, and a loop that won't let a task "finish" until it's actually done.

Quickstart

Prerequisites: jq (the guardrails parse Claude Code's JSON with it) and the claude CLI. npx needs Node, which you almost certainly already have. On macOS: brew install jq. Elsewhere: sudo apt install jq / sudo dnf install jq / sudo pacman -S jq — the installer prints the right command for your system if it's missing.

# Fastest — from inside the project you want to work in (no clone needed):
cd ~/code/my-project
npx cc-loopkit init          # installs the harness + scaffolds a loop

# From source — to hack on the harness itself:
git clone https://github.com/ksed8/cc-loopkit.git && cd cc-loopkit
./install.sh --init ~/code/my-project

init (equivalently --init) also drops a PROMPT.md + .claude/IMPLEMENTATION_PLAN.md into the project so you can fill them in and go. Both entry points are the same installer and take the same flags (--link, --force, --no-mcp, --strict) — npx cc-loopkit … just runs the bundled install.sh for you. --strict makes a missing prerequisite a hard error (handy in CI).

Usage

First, tailor .claude/CLAUDE.md (installed as CLAUDE.md.example if the project already had memory) to your stack, commands, and "Never" rules — the guardrails enforce those rules. From then on the per-tool guardrails and post-edit format/lint run automatically in every session. The two loops below are opt-in, armed per task.

Inner loop — drive one session to "done"

  1. Fill in PROMPT.md (scaffolded at the project root by init): the task, a checkable Definition of done, and any constraints.
  2. Start Claude Code in the project and hand it the task as usual — session-start.sh feeds it PROMPT.md automatically.
  3. Claude can't end a turn while typecheck/tests are red: the Stop gate feeds the failures back and makes it keep going until green.
  4. To confirm it did the right thing (not just that it compiles), ask: "Use the verifier subagent to check the diff against PROMPT.md."
  5. When it's shipped, delete PROMPT.md to disarm the loop and go back to normal interactive use.

Outer loop — run it autonomously to "done"

  1. Fill in PROMPT.md and .claude/IMPLEMENTATION_PLAN.md (both scaffolded by init) — break the Definition of done into concrete, checkable steps.
  2. Run ./run.sh (cap iterations with e.g. ./run.sh 10; default 20). Each iteration is a fresh claude -p that does the next unchecked step, commits on green, verifies, and appends a note to .claude/MEMORY.md.
  3. It stops on its own: STATUS: done (all steps pass the mechanical + semantic checks), blocked (same failure 3+ times — it surfaces the Verify log for you), or the iteration cap.
  4. Watch progress in .claude/IMPLEMENTATION_PLAN.md (Verify log) and .claude/MEMORY.md. Delete both plus PROMPT.md when the task ships.

The rest of this README explains how each gate works under the hood.

Two loops, two shapes of statelessness

There are two independent ways to drive a task to done. Pick based on how much you trust one long session vs. how much you want a hard reset between steps.

Inner loop — one continuous session

Armed by putting a PROMPT.md (goal spec) at the project root — copy PROMPT.template.md. While it exists:

  1. Mechanical gatehooks/stop.sh (a Stop hook). When Claude tries to end a turn, it runs typecheck + tests (via scripts/run-checks.sh). If they're red, it returns {"decision":"block","reason":…}, which feeds the failures back and forces another iteration. Green (or nothing to run) → the turn is allowed to end. Guarded against infinite loops by stop_hook_active.
  2. Semantic gate — the verifier subagent. Mechanical checks prove the code runs; the verifier reads the diff against PROMPT.md and judges whether it does the right thing. Invoke it after a change: Use the verifier subagent to check the diff against PROMPT.md.

No PROMPT.md → this loop is dormant and Claude stops normally.

Outer loop — fresh context every iteration

../run.sh drives this. Instead of one session iterating on itself, every step is a brand-new claude -p process with zero memory of prior turns. Use this when you want a hard boundary between steps — no context creep, no accumulated confusion from a long session talking itself in circles.

State lives on disk, split across two locations by who owns it:

  • PROMPT.md (project root) — same goal spec as the inner loop. The one file in this whole system a human actually authors, so it stays at the root, maximally visible — every "is a loop armed" check throughout the harness keys off this file's presence.
  • .claude/IMPLEMENTATION_PLAN.md — copy IMPLEMENTATION_PLAN.template.md. Holds the step checklist, a STATUS: line (not_started / in_progress / blocked / done), and a Verify log. run.sh greps STATUS: to decide when to stop — get that line's exact text right.
  • .claude/MEMORY.md — free-form, append-only, dated entries. The only continuity a fresh-context iteration has with what previous iterations learned or decided. Append at the end (chronological); never rewrite past entries.

IMPLEMENTATION_PLAN.md and MEMORY.md live under .claude/ rather than the root because nothing ever hand-authors them beyond the initial template copy — they're pure machine state, written and read only by run.sh and /loop-verify. Keeping them there also keeps two fairly generic filenames out of collision range with a project's own files (a project can easily have its own reasons to want a root-level MEMORY.md or PLAN.md unrelated to this harness).

Each iteration of run.sh is two claude -p calls:

  1. Implement — reads PROMPT.md + .claude/IMPLEMENTATION_PLAN.md + .claude/MEMORY.md, does the next unchecked step, commits on green, appends a note to .claude/MEMORY.md.
  2. /loop-verify (skill, run with CLAUDE_VERIFY_MODE=1) — a read-only reporter, never a fixer. Runs the same mechanical checks as the inner loop's Stop gate, invokes the verifier subagent for the semantic check, and records the combined verdict: it updates .claude/IMPLEMENTATION_PLAN.md's Verify log and, only on a full pass, flips STATUS: to done. Two hooks enforce "reporter, not fixer" — pre-tool-use.sh hard-denies Edit/Write on anything except .claude/IMPLEMENTATION_PLAN.md/ .claude/MEMORY.md (full-path match, not just filename) while CLAUDE_VERIFY_MODE=1, and stop.sh exempts that same mode from the fix-it pressure the inner loop normally applies.

run.sh reads STATUS: after each iteration — done exits clean, blocked stops and surfaces the Verify log to a human (the plan itself is wrong, not just unfinished), and it caps at ./run.sh [max-iterations] (default 20) so a stuck loop can't run unattended forever.

/loop-verify is deliberately not named /verify — this environment already ships a general-purpose verify skill with different behavior (run the app, observe it) and the same name would silently shadow one or the other depending on scope resolution.

Either way: sessions see loop state automatically

hooks/session-start.sh injects whatever's armed into context at the start of every session — the PROMPT.md goal spec, .claude/IMPLEMENTATION_PLAN.md, and the tail of .claude/MEMORY.md (each capped so a bloated file can't flood the context window). This matters most for the outer loop, where it's the only reason a fresh, memory-less claude -p process learns any of this without the invoking prompt having to spell it out. Nothing armed → the hook prints nothing and costs nothing.

The guardrails (per-tool)

| Hook | Fires on | Does | | --- | --- | --- | | hooks/pre-tool-use.sh | Edit, Write, Bash | Denies actions that break the CLAUDE.md "Never" rules (editing merged db/migrations/*) and blocks destructive shell commands (bare --force, reset --hard, unbounded DELETE, curl \| sh, …). Also hard-restricts Edit/Write to .claude/IMPLEMENTATION_PLAN.md/.claude/MEMORY.md when CLAUDE_VERIFY_MODE=1. | | hooks/post-tool-use.sh | Edit, Write | Formats the edited file (prettier) and lints it (eslint); surfaces lint errors back to Claude immediately. Fast, file-local only. | | hooks/stop.sh | Stop | The inner-loop gate described above. Exempts CLAUDE_VERIFY_MODE=1 sessions. | | hooks/session-start.sh | Session start | Injects whatever loop state exists (PROMPT.md, .claude/IMPLEMENTATION_PLAN.md, .claude/MEMORY.md tail) into context; silent (zero cost) when nothing's armed. |

All hooks fail open: any internal error allows the action rather than wedging the session. They need jq; the guardrails no-op with a warning if it's missing.

Division of labor: per-edit hooks stay fast (format/lint one file); the expensive whole-project checks (typecheck/tests) run once, at the Stop gate.

Config

  • settings.json — wires the four hooks and sets the permission allow/deny list. The deny list + pre-tool-use.sh are belt-and-suspenders: static denials for the obvious cases, the script for the context-dependent ones.
  • scripts/run-checks.sh — the mechanical check runner (typecheck + tests). Single source of truth used by both hooks/stop.sh (inner loop) and the /loop-verify skill (outer loop) so the two can't silently disagree about what "green" means.
  • mcp.json — MCP servers (github, context7). The installer places this at the project root as .mcp.json — the location Claude Code actually reads.
  • CLAUDE.md — project facts and the "Never" rules the guardrails enforce.
  • ../run.sh — the outer-loop runner (see above). Lives at the project root, not under .claude/, since it's an executable entry point, not config.

Tuning knobs

  • CLAUDE_VERIFY_CMD — override what scripts/run-checks.sh runs (e.g. export CLAUDE_VERIFY_CMD="pnpm typecheck && pnpm test --run"). Otherwise it autodetects pnpm typecheck / tsc --noEmit and pnpm test from package.json.
  • CLAUDE_CHECK_TIMEOUT_SECS — per-check kill timer (default 240). A hung check is killed and reported red rather than letting the Stop hook itself time out — a killed hook would silently fail open. Enforced by a built-in bash watchdog; no GNU timeout needed (stock macOS doesn't have it).
  • Bump the verifier's model: from haiku to sonnet for stricter semantic review.
  • ./run.sh [max-iterations] (default 20) / LOOP_SLEEP_SECS — outer-loop bounds.

Skills

skills/ holds task playbooks Claude loads on demand: agent-llm, debug, security, testing, data, git-ops, loop-verify (outer-loop internal — not for ad hoc use), plus docs, frontend, refactor. Each is a SKILL.md with a description: whose trigger phrases decide when it loads.