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

l3-simulator

v1.0.1

Published

GitHub issue orchestrator that dispatches AI coding agents ("L3s") over labeled issues: plan, code, and fix in isolated git worktrees, open PRs, and babysit CI and review feedback. Humans merge.

Readme

L3 Simulator

Have you ever wanted a tireless junior engineer who never sleeps or doom-scrolls? L3 Simulator orchestrates AI coding agents over your GitHub issues: label an issue ready and your synthetic L3 claims it, optionally writes up a plan, dispatches a coding agent (Claude Code or Codex) in an isolated git worktree, opens a PR, and babysits it through CI failures, review comments, and merge conflicts. In the meantime you go do something befitting your seniority.

L3 Simulator never merges anything. You are still responsible for code review and merging. The gh wrapper hard-rejects merge commands, agents are denied gh and git push, and CI greps for regressions. Your L3s can open all the PRs they like, but shipping is above their pay grade.

Requirements

  • Node >= 22
  • gh authenticated (gh auth login)
  • claude (Claude Code) and/or codex CLI installed
  • A local clone of the repo you want to orchestrate

Installation

Install the CLI globally from npm:

npm install -g l3-simulator

This puts an l3-simulator command on your PATH. Prefer not to install globally? npx l3-simulator <command> works too. To build from source, see Development.

Then, inside each repo you want to orchestrate:

l3-simulator init

init writes .l3-simulator.json into the repo (gitignore it; it contains a local path) and creates the five workflow labels on GitHub. Any command run from inside that repo picks up its config, so multiple repos each get their own daemon, worktrees, state, and logs.

The label workflow

GitHub labels are the orchestrator's source of truth: the issues UI is the dashboard, and a crash or restart re-derives everything from labels + PRs. Your L3s have no memory of their own. You can interact either via the TUI or via the GitHub issues UI.

| Label | Meaning | Who sets it | | --------------------- | ----------------------------------------------------------------------------- | ------------ | | ready | Start working on this | you | | needs-plan | Plan first; reply #approve to start coding, anything else revises the plan | you | | needs-plan-noreview | Plan first, then code immediately without waiting for approval | you | | in-progress | Claimed; an agent is (or will be) working | orchestrator | | blocked | Needs your input (plan approval, questions, failures) | orchestrator | | in-review | An agent PR is open. Review and merge it yourself | orchestrator | | failure | Added with blocked when an agent actually failed. Urgent, reply to retry | orchestrator |

Lifecycle:

  1. Create issue with ready tag. Optionally add needs-plan or needs-plan-noreview
  2. L3 claims an issue (addsin-progress tag)
  3. (Optional) L3 plans work and posts a comment with the plan, waits for approval
  4. Coding L3 starts in a worktree on l3/issue-<n>-<slug>
  5. Submits a PR (tags in-review)
  6. (Optional) comment on the PR to request updates
  7. You merge, and the labels are removed

Cross-repo prerequisites file themselves. When a coding agent concludes the work is blocked on changes in another repository, it describes the issue(s) to file there, the orchestrator creates them and the original issue automatically resumes once every prerequisite issue is closed. You can run another instance of L3 Simulator on that repo as well.

Plans are approved explicitly. When a plan is posted (needs-plan), the issue blocks until you reply. A reply containing #approve starts coding — anything else in that reply is passed to the coding agent as guidance. Any other reply is treated as plan feedback: the plan agent produces a revised plan and re-posts it for review, as many rounds as you like.

Everything else blocked resumes on a reply. Planning-agent questions, agent failures, and the fix-attempt cap all add blocked plus an explanatory comment. Replying with any comment unblocks the issue and work resumes with your reply as context. Removing the blocked label by hand also works. Human comments are passed to the coding agent and take precedence over the plan.

Multi-stage issues. When a coding agent reports its PR is a first slice (done: false), the issue keeps in-progress alongside in-review, and the next stage starts only after you merge the current PR.

While a PR is open the orchestrator polls its health: failing checks, new review comments, or merge conflicts dispatch a fix agent into the same worktree (capped at maxFixIterationsPerPr per PR; pushing your own commit to the branch resets the counter). Branches that fall behind the base are updated automatically, and merge conflicts are resolved even while an issue is blocked on something else.

Closed issues are tidied automatically: workflow labels are stripped (so the closed list looks clean) and worktrees whose PRs are merged or closed are removed once the issue is no longer active — worktrees with uncommitted changes are left for l3-simulator cleanup --force.

Usage

l3-simulator start                 # TUI dashboard + daemon (q to quit)
l3-simulator start --headless      # plain log lines (cron, background)
l3-simulator start --dry-run       # log every mutation instead of doing it
l3-simulator run-once              # single tick (demos, cron)
l3-simulator status                # one-shot table derived from GitHub
l3-simulator cleanup               # prune worktrees for merged/closed PRs

The dashboard

start opens a live TUI: every workflow issue with its phase (queued, planning, coding, fixing, plan review, blocked, in review, next stage), the running agent's role + elapsed time + live progress line (on the selected row), the open PR with a CI glyph (✓ ✗ ●), the worktree branch, and a "recently completed" section of closed issues the orchestrator shipped. A log pane shows recent events (--verbose adds per-tool agent progress).

Keys: ↑↓/j k select · n file a new issue (title, body, label choice — appears on the next tick) · r force a poll now · o open a new tmux pane cd'd into the selected issue's worktree · open the PR (or issue) in your browser · q/ctrl-C graceful shutdown (kills agents, releases the lock).

Agent transcripts land in ~/.local/share/l3-simulator/logs/<owner--repo>/issue-<n>/.

While a fix agent addresses PR feedback, the issue's in-review label swaps to in-progress (and back after the push) so GitHub also shows work is active.

Configuration

~/.config/l3-simulator/config.json (override with --config or L3_SIMULATOR_CONFIG):

{
  "repo": {"path": "/home/you/myrepo", "slug": "you/myrepo"},
  "maxConcurrentAgents": 2,
  "pollIntervalSeconds": 60,
  "maxFixIterationsPerPr": 3,
  "agents": {
    "plan": {"backend": "claude", "timeoutMinutes": 15},
    "code": {"backend": "claude", "timeoutMinutes": 60, "model": "opus"},
    "fix": {"backend": "codex", "timeoutMinutes": 30},
  },
}

Each role (plan/code/fix) independently chooses claude or codex, plus optional model, permissionMode (Claude), and extraArgs. Use init --global for a single per-user config instead (~/.config/l3-simulator/config.json). Resolution order:

  1. --config flag
  2. L3_SIMULATOR_CONFIG
  3. nearest .l3-simulator.json up the directory tree
  4. user config dir.

Safety model

  • No merging. The only gh pr subcommands in the codebase are create/list/view/checks/comment/update-branch; the single gh choke point (src/github/gh.ts) rejects merge argv outright.
  • Agents don't touch GitHub. Claude runs with gh and git push disallowed; Codex runs sandboxed. The orchestrator pushes branches and opens PRs itself, and only after verifying the agent actually committed.
  • Claude code/fix agents run with bypassPermissions inside their isolated worktree. Headless acceptEdits aborts on any shell command, so autonomous work is impossible without it. The gh/git push deny rules are enforced even in bypass mode; set agents.<role>.permissionMode to tighten this if you prefer explicit allowlists.
  • blocked is inert. Anything the orchestrator can't handle is commented on the issue and handed to you. Your L3s know when to escalate to an adult.
  • Recommended: branch protection on your default branch (require review, no force pushes). One daemon per repo (enforced by a pidfile).

Development

npm install              # install dependencies
npm run dev -- status    # run from source (tsx)
npm run demo             # render the sample dashboard (handy for screenshots)
npm test                 # vitest
npm run typecheck && npm run lint && npm run format:check

To use a source build as the global l3-simulator command: npm run build && npm link.