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

lumbergh

v0.1.0

Published

A micromanager for local coding agents

Readme

Lumbergh

A micromanager for local coding agents.

Yeah, if you could just go ahead and create that feature branch, that'd be great.


The Problem

If you've tried running a local LLM as a coding agent on consumer hardware, you've probably seen this:

Agent: "I will tackle TaskPlanner.php next"
You:   "OK, do that then..."
Agent: "Do you want me to modify that file?"
You:   "Yes!"
Agent: *finally does a bit of coding*

Or this:

Agent: "Actually, I'll try ls -la /."
Agent: "Actually, I'll try ls -la /."
Agent: "Actually, I'll try ls -la /."
Agent: "Actually, I'll try ls -la /."

Local models like Gemma 4 26B are frustratingly close to being useful coding agents. They can read GitHub issues, create feature branches, break tasks into steps, and write decent code. But they have two crippling habits:

  1. They need constant handholding. They narrate what they're about to do, then stop and wait for permission.
  2. They get stuck in loops. Same action, same output, over and over.

Lumbergh is an outer agent that wraps your local coding CLI and manages these quirks automatically. It's a micromanager -- and that's the point.

How It Works

Lumbergh runs your local coding agent through a loop:

                    +------------------+
                    |   Pre-flight     |
                    |  (git, tests,    |
                    |   existing PRs)  |
                    +--------+---------+
                             |
                             v
                    +------------------+
              +---->|   Worker (LLM)   |
              |     |  via hook script |
              |     +--------+---------+
              |              |
              |              v
              |     +------------------+
              |     |   Loop detect    |
              |     | (hash compare)   |
              |     +--------+---------+
              |              |
              |              v
              |     +------------------+
              |     |    Verifier      |
              |     | (git/gh checks)  |
              |     +--------+---------+
              |              |
              |         DONE? -----> exit
              |              |
              |           FOLLOWUP
              |              |
              +--------------+

Each stage except loop detection is a shell script hook that you can swap out for your own workflow.

Pre-flight

Before any LLM inference happens, the default preflight.sh hook checks:

  • On main? Fails if you're on a feature branch.
  • Clean tree? Fails if there are uncommitted changes.
  • Up to date? Pulls latest with --ff-only.
  • Existing PRs? Fails if there's already an open PR for this issue.
  • Tests pass? Runs npm test. Fails if tests are broken.

These checks are instant and save minutes of wasted inference when something is wrong.

Worker

The default worker.sh hook invokes opencode with your local model. Lumbergh sends it a task with a short preamble:

RULES: Act immediately, no confirmation needed. Do not run ls on large dirs.
Do not summarize or ask how to help. Tests already pass -- only rerun after
your changes. Finish by: 1) create feature branch, 2) commit, 3) push,
4) create PR referencing the issue. Do NOT close the issue.

TASK: Solve Github issue 29

Session IDs are tracked so followup turns continue the same conversation.

Loop Detection

After each worker turn, Lumbergh hashes the output (MD5) and compares it to the last N outputs. If 3 consecutive outputs are identical, it interrupts the worker and forces a different approach.

Verifier

This is the key insight: don't use an LLM to verify LLM work.

The default verify.sh hook uses concrete git/GitHub checks:

  1. On a feature branch? git branch --show-current
  2. Changes committed? git status --porcelain -uno
  3. New commits? git rev-list --count main..HEAD
  4. PR created? gh pr list --head <branch>

Each missing step becomes a specific followup instruction sent back to the worker. The verifier is instant, deterministic, and never hallucinates. It must output exactly DONE or FOLLOWUP:<instruction> -- Lumbergh validates the format.

Usage

Run Lumbergh from your project directory:

cd ~/projects/myapp

# First run auto-creates .lumbergh/ with config and hooks
lumbergh "Solve Github issue 42"

# Or initialize first to customize hooks before running
lumbergh init
# edit .lumbergh/hooks/worker.sh to use aider instead of opencode
lumbergh "Solve Github issue 42"

# One-off overrides via CLI flags
lumbergh "Fix bug" --max-turns 5

CLI

lumbergh <prompt> [options]
lumbergh init

Commands:
  init                   Initialize .lumbergh/ in the current directory
  <prompt>               Task description (e.g., "Solve Github issue 42")

Options:
  --max-turns <n>        Maximum turns (default: 20)
  --loop-threshold <n>   Consecutive identical outputs before redirect (default: 3)
  --preamble <text>      Override the default preamble
  --version              Show version
  --help                 Show this help

Per-Project Config

Each project gets a .lumbergh/ directory (auto-created on first run or via lumbergh init):

myapp/
  .lumbergh/
    config.json           # maxTurns, loopThreshold, preamble
    hooks/
      preflight.sh        # Pre-run checks
      worker.sh           # LLM invocation
      verify.sh           # Completion checks

Config precedence: CLI flags > .lumbergh/config.json > hardcoded defaults.

Running lumbergh init on an already-initialized project prints "Already initialized" and does nothing.

Requirements

  • Node.js 18.3+
  • opencode installed and configured (for default worker hook)
  • Ollama running with a model (tested with gemma4:26b-16k)
  • gh CLI authenticated (for default verify/preflight hooks)
  • npm test working in your target project (for default preflight hook)

Custom Hooks

Why shell scripts?

Hooks are the boundary between the agentic worker (your LLM doing the creative coding) and deterministic micromanagement (Lumbergh enforcing the workflow). That boundary is intentionally made of bash scripts because bash is the lingua franca of coding agents -- every LLM-based coding tool can read, write, and modify shell scripts fluently. If your project uses pytest instead of npm test, or deploys to GitLab instead of GitHub, you can ask your coding agent to update the hooks for you. The scripts are short, self-contained, and live in your repo at .lumbergh/hooks/ -- a natural target for agentic modification.

Hook resolution

Lumbergh looks for hooks in this order:

  1. .lumbergh/hooks/ in the current project directory
  2. Built-in defaults shipped with Lumbergh (fallback if a hook file is deleted)

After lumbergh init, all hooks are copied to .lumbergh/hooks/ for you to edit (or have your agent edit):

| Hook | Arguments | Environment | Expected Output | |------|-----------|-------------|-----------------| | preflight.sh | $1 = project dir, $2 = prompt | -- | Exit 0 to pass, non-zero to fail | | worker.sh | $1 = project dir, $2 = message | LUMBERGH_SESSION_ID | LLM response to stdout | | verify.sh | $1 = project dir | LUMBERGH_INITIAL_BRANCH | DONE or FOLLOWUP:<instruction> |

You only need to override the hooks you want to change. For example, to use a different LLM runner like aider or claude-code, just replace worker.sh. To adapt for GitLab instead of GitHub, replace verify.sh and preflight.sh.

Architecture

src/
  index.ts              CLI entry point (thin wiring)
  cli.ts                Argument parsing (init command + run with flags)
  config.ts             Per-project config loading + merge with precedence
  init.ts               Scaffold .lumbergh/ directory
  orchestrator.ts       Main turn loop with dependency injection
  hook-resolver.ts      2-tier hook resolution (project > built-in)
  hook-runner.ts        Safe shell execution (execFile) + verdict validation
  loop-detector.ts      MD5 hashing + consecutive-match detection
  logger.ts             Structured output with configurable stream
  types.ts              Shared interfaces

hooks/
  preflight.sh          Default: git checks, existing PRs, npm test
  worker.sh             Default: opencode invocation with session support
  verify.sh             Default: git/gh state checks

Zero runtime dependencies -- only Node built-ins (node:child_process, node:crypto, node:fs, node:path).

The orchestrator receives hookResolver and hookRunner as injected dependencies, making it fully testable without real hooks or shell execution.

Development

npm install
npm test              # Run all 99 tests
npm run test:watch    # Watch mode
npm run build         # Compile TypeScript to dist/