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

cached-run

v0.0.1

Published

Cache expensive verification commands so coding agents do not rerun them for the same source state.

Downloads

259

Readme

cached-run

Cache expensive verification commands so coding agents can't run the same check twice for the same source state.

Install

npm install -D cached-run

Works with any package manager (pnpm, yarn, bun); the examples below use npm.

Usage

cached-run run -- npm run typecheck
cached-run run --shell "npm run typecheck"
cached-run explain --shell "npm run typecheck"
# or one quoted argument (argv often contains flags the CLI would misread)
cached-run explain "npm run typecheck"
cached-run clean --older-than 7d

Claude Code hook

Add to .claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "npx cached-run hook claude"
          }
        ]
      }
    ]
  }
}

Matching Bash commands are rewritten to node <absolute-path-to-this-cli> run -- … using the same binary that ran the hook (no PATH or extra config required). Optional binary in config overrides that invocation.

Guarantee

  • Same command + same source state → cached result (original exit code)
  • Changed source state → fresh run
  • Cache entry older than ttl (default 5m) → fresh run
  • Full logs kept on disk under .cache/cached-run (or CACHED_RUN_CACHE_DIR)
  • --force or CACHED_RUN_FORCE=1 bypasses cache

How it works

On each run, cached-run derives a key from two things: the command and the state of your source tree.

The command — the parsed argv, your config (cache dir and command patterns), and cached-run's own version. Upgrading the tool or editing config invalidates earlier entries.

The source state, read from git:

  • the current HEAD commit
  • a diff of every tracked file against HEAD, so uncommitted edits count
  • a content hash of every untracked file that isn't gitignored

These are folded into a SHA-256 digest (truncated to a short hex key). Two runs share a key only when the command and every byte of relevant source match.

From there:

  • Miss — the command runs. Combined stdout and stderr are captured to a log under cacheDir, with metadata (exit code, duration, error count, timestamp). The command's real exit code is returned.
  • Hit — the key matches an entry within ttl, so the command is skipped entirely; cached-run prints a summary and returns the original exit code.

Only commands matching a configured pattern are cached; the cache is just files on disk under cacheDir, with no daemon or global state.

Through the Claude Code hook

The hook is a PreToolUse rewriter, not a wrapper — it never runs your command or touches the cache itself. On each Bash tool call, Claude Code pipes the pending command to cached-run hook claude, which:

  1. Parses the command and matches it against your configured patterns.
  2. If it doesn't match — or can't be parsed safely (see Safety) — exits silently, and Claude runs the original command untouched.
  3. If it matches, emits a PreToolUse decision that rewrites the command to <cli> run -- <command>, reusing the exact binary that ran the hook (so there's no PATH dependency; binary in config can override it).

Claude then runs that rewritten command, and the caching above takes over.

Config

Create cached-run.config.json (or .mjs / .js / .ts):

{
  "cacheDir": ".cache/cached-run",
  "ttl": "5m",
  "commands": [
    "pnpm -r typecheck",
    "pnpm --filter * typecheck"
  ]
}

Each command is a shell string. * matches exactly one whitespace-separated segment (e.g. a package name); a pattern must match the whole command.

Safety

Conservative by design: redirects, &&, env prefixes, subshells, and already-wrapped commands pass through unchanged. Simple matching commands rewrite to cached-run run -- …. If the agent adds a single output pipe (| tail, | head, | grep), the hook prefixes cached-run and keeps the pipe: cached-run run -- npm test | tail -100. Exit codes through pipes are best-effort.

Caveats

  • cached-run captures stdout and stderr together into one combined log file.
  • On a cache hit, cached-run returns the original exit code and prints a short summary. It does not replay the cached command output to stdout.
  • Because cache hits print the summary instead of the original output, a trailing pipe such as | tail -50 sees the cached-run summary on cache hits, not the command log.
  • Use the LOG: path from the summary to inspect the full cached output.