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

@kevinzhangnothing/loop-context

v1.0.0

Published

Stateful memory manager for agent loops — summarize, prune, and inject context, with a circuit breaker that escalates stagnant or no-progress runs instead of burning tokens.

Readme

loop-context

Stateful memory manager for agent loops. Keeps the context window clean and stops runaway loops before they burn tokens.

Long-running agent loops fail in two classic ways the agent-loops docs warn about:

  • Context overflow & rot — conversation history and error logs grow until the model loses the original goal or drowns in stale stack traces.
  • Stagnant / no-progress loops — the agent retries the same failing action forever, quietly blowing the token budget.

loop-context sits between the agent and its durable memory (STATE.md, run logs) and, before each iteration, does three things:

  1. Summarize what has been tried and what failed.
  2. Prune verbose stack traces, collapse repeated errors, and drop stale attempts outside a recent window.
  3. Inject only the essentials into the next prompt.

A circuit breaker watches iteration count, token spend, stagnation (same error N× in a row), and no-progress (too many consecutive failures) — and escalates to a human instead of looping in vain.

Everything is deterministic and dependency-free: no LLM call is needed to summarize or prune, so it is cheap enough to run on every iteration.

Install / run

npx @kevinzhangnothing/loop-context --help
# or from this repo:
cd tools/loop-context && npm install && npm test

The ledger

The tool reads a run ledger — a JSON record of the loop's goal and its attempts:

{
  "goal": "Get the failing migration test to pass",
  "attempts": [
    { "iteration": 1, "action": "run migration", "outcome": "failure",
      "error": "Error: connect ECONNREFUSED 127.0.0.1:5432", "tokensUsed": 1500 },
    { "iteration": 2, "action": "run migration again", "outcome": "failure",
      "error": "Error: connect ECONNREFUSED 127.0.0.1:5432", "tokensUsed": 1400 }
  ]
}

outcome is success | failure | noop. error and tokensUsed are optional.

Usage

# Circuit breaker — exit 0 = continue, 2 = escalate (wire into a loop's control flow)
loop-context --check --ledger run.json

# Compact context block for the next prompt
loop-context --inject --ledger run.json

# Factual rollup of the run
loop-context --summary --ledger run.json --json

# Pruned ledger (recent window, trimmed traces, collapsed repeats)
loop-context --prune --ledger run.json

# Pipe on stdin
cat run.json | loop-context --check

Options

| Flag | Default | Meaning | |------|---------|---------| | --max-iterations <n> | 10 | Hard iteration cap | | --stagnation <n> | 3 | Escalate when the same error repeats N× in a row | | --no-progress <n> | 5 | Escalate after N consecutive failures | | --token-budget <n> | none | Escalate when cumulative tokens reach the cap | | --window <n> | 5 | Attempts kept when pruning | | --max-trace-lines <n> | 8 | Stack-trace lines kept when pruning |

Exit codes: 0 continue · 2 escalate · 1 error.

Populating the ledger

Your loop control script appends one object per iteration to run.json (or pipes the same shape on stdin):

# after each agent iteration — append attempt, then gate the next one
node -e "
const fs = require('fs');
const ledger = JSON.parse(fs.readFileSync('run.json', 'utf8'));
ledger.attempts.push({
  iteration: ledger.attempts.length + 1,
  action: 'run migration tests',
  outcome: 'failure',
  error: process.argv[1],
  tokensUsed: Number(process.argv[2] || 0),
});
fs.writeFileSync('run.json', JSON.stringify(ledger, null, 2));
" \"\$ERROR_MSG\" \"\$TOKENS\"
loop-context --check --ledger run.json || { loop-context --inject --ledger run.json; exit 2; }

Initialize once at loop start: { \"goal\": \"Get CI green on main\", \"attempts\": [] }.

In a loop

# inside your loop's control script, before each iteration:
if ! loop-context --check --ledger run.json; then
  loop-context --inject --ledger run.json > escalation.md   # hand a clean summary to the human
  exit 0                                                     # stop instead of retrying
fi

Library API

import {
  checkCircuitBreaker,
  pruneLedger,
  summarizeAttempts,
  buildContextInjection,
} from '@kevinzhangnothing/loop-context';

const decision = checkCircuitBreaker(ledger);
if (decision.escalate) escalateToHuman(decision.reason);
else runNextIteration(buildContextInjection(ledger));

Where it fits

This is the Memory / State primitive of agent loops made dynamic: STATE.md stores state statically; loop-context manages it across iterations. See docs/primitives.md and the operating & safety guides.

MIT · part of agent-loops by Kevin Zhang.