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

@ferrousapps/listr

v0.2.0

Published

Run Claude Code on your own machine against tasks you assign in Listr. Connect with a pairing code, allow-list the repos it may touch, and it implements tasks and opens PRs for you to review.

Readme

@ferrousapps/listr

Run Claude Code on your own machine against tasks you assign in Listr. Hand a task to Claude from the app; the agent on your machine implements it on a branch, opens a pull request, runs a review pass, and reports status back to the task. You merge.

You, anywhere ───(Listr / Firestore)───▶  your machine: listr-agent start
  "Hand off to Claude" on a task              claim → branch
  (repo comes from the list)                  → claude (code) → gh pr create
                                              → claude (review) → PR comment
                              ◀── status: Queued · Coding · PR Open · Reviewed
  • Browser sign-in — no passwords. listr-agent login approves the machine in a tab; a one-time pairing code covers headless boxes.
  • Repo allowlist is the hard security boundary — the agent only ever touches repos you added on this machine.
  • Shared pools — everyone on a collaborative list can connect machines, and a teammate can hand a task to any online machine in the pool.
  • The agent never merges. Every change lands as a PR for you to review.

The command this package installs is listr-agent.


Requirements

  • Node ≥ 20
  • Claude Code CLI (claude), signed in (claude once interactively, or an API key configured).
  • For GitHub repos: the GitHub CLI (gh), authenticated with push + PR rights: gh auth login.
  • For Bitbucket repos: an app password (BITBUCKET_USERNAME + BITBUCKET_APP_PASSWORD) or an access token (BITBUCKET_TOKEN) — Bitbucket has no gh-style CLI, so the agent uses git-over-HTTPS + the REST API.
  • A Listr Pro/Elite account (Coding Agents is a paid capability).

Install

npm install -g @ferrousapps/listr

This puts the listr-agent command on your PATH. (Prefer not to install globally? Use npx @ferrousapps/listr <command> anywhere below.)

Update later with npm update -g @ferrousapps/listr.


Quick start

The fastest path is the guided wizard — it asks for each value (Enter skips any, add it later), then offers to allow-list a repo and sign the machine in:

listr-agent setup

It writes your answers to ~/.listr-agent/.env; re-run it any time to change or fill in skipped values. Prefer to do it by hand? The individual steps:

# 1. Sign this machine in (opens a browser tab you approve).
listr-agent login
#   …no browser on this machine? Use a code from Listr → Agents → "Connect a machine":
#   listr-agent connect ABCD-1234

# 2. Allow-list the repo(s) this machine may touch (the security boundary).
listr-agent repos add --slug your-org/your-app
#   …or an existing local checkout:
listr-agent repos add --path ~/code/your-app --alias app

# 3. Sanity-check everything (tools, sign-in, visible tasks).
listr-agent doctor

# 4. Run it.
listr-agent start

Then in Listr:

  1. Open a list, edit its details, and set the GitHub repository (owner/repo) — every task you hand off inherits it.
  2. On any task, choose Handoff to Claude → pick a machine (or Any available agent) → Hand off.

The task advances Queued → Claimed → Coding → Committing → PR Open → Reviewing → Reviewed, with the PR link attached. Manage running jobs (cancel / rerun / remove, and view logs) from the Agents tab.

You stay signed in across restarts — you only sign in once per machine.

Per-task options: tag a task Urgent to have agents pick it up first (it even preempts a running non-urgent job). Add a custom field named "Branch" to name the working branch the agent creates; otherwise it auto-generates listr-agent/<id>-<slug>.


Commands

listr-agent start                 Watch for tasks and run them (default)
listr-agent once                  Process whatever's eligible now, then exit
listr-agent doctor                Check config, tools, sign-in, and visible work
listr-agent login                 Sign in via your browser (recommended)
listr-agent connect <code>        Pair with a code — for machines with no browser
listr-agent disconnect            Sign out and remove this machine's session
listr-agent mcp                   Run as an MCP server so Claude Code can create tasks
listr-agent repos list            Show this machine's repo allowlist
listr-agent repos add --slug owner/repo [--alias name]
listr-agent repos add --path /abs/path  [--alias name]
listr-agent repos remove <slug|path|alias>
listr-agent machines              List machines registered to your account

Add --verbose (or -v) to any command for detailed logging.

listr-agent doctor is the safe pre-flight: it lists exactly which tasks it can see and whether each one's repo is allow-listed.


How repos work

A task's repo is untrusted cloud input — the agent never clones or runs it directly. Instead:

  1. You set a repository on the Listr list (or override per task) — GitHub or Bitbucket.
  2. The agent resolves that value against this machine's local allowlist (listr-agent repos add). If it isn't allow-listed, the task is skipped on this machine — another machine that has allow-listed it can run it.

So the cloud can only ever pick from the repos you explicitly approved on a given machine. Provider is inferred from the form:

listr-agent repos add --slug owner/repo                       # GitHub
listr-agent repos add --slug bitbucket.org/workspace/repo     # Bitbucket
listr-agent repos add --slug workspace/repo --provider bitbucket
listr-agent repos add --path ~/code/your-app --alias app      # local checkout

On the Listr list, write owner/repo for GitHub or bitbucket.org/workspace/repo for Bitbucket. GitHub clones via gh; Bitbucket clones via git-over-HTTPS using your configured credentials and opens PRs through the Bitbucket REST API.


Sources & the shared pool

Control which tasks a machine watches with LISTR_AGENT_SOURCE:

| Source | Watches | Default | |---|---|---| | own | your personal lists only | ✅ | | collab | collab lists you own or are shared on | | | both | personal + collab | |

collab/both run task text authored by collaborators, so they require an explicit opt-in: set LISTR_AGENT_ALLOW_COLLAB=1.

When you run with collab/both, your machine joins that list's shared pool: every collaborator can see it online and hand it a task. If several machines watch the same list, an atomic claim guarantees only one runs a given task, and you can target a specific machine when handing off.

# Join collab pools (in addition to your own tasks):
LISTR_AGENT_SOURCE=both LISTR_AGENT_ALLOW_COLLAB=1 listr-agent start

Create tasks from Claude Code, Cursor, or any MCP client

The same pairing also lets any MCP client — Claude Code, Cursor, Windsurf, VS Code (Copilot agent mode), Cline, Codex CLI, Gemini CLI, … — create tasks in your Listr projects — the reverse direction from handing tasks off. Because the session acts as you, it writes your own projects directly; no bot account, no extra login. It's a standard stdio MCP server, so every client launches it the same way: npx -y @ferrousapps/listr mcp.

Sign in once first (if you haven't already):

listr-agent login                      # opens your browser — nothing to copy

Your browser is normally already signed in to Listr, so login just asks you to approve this machine and hands the session back over loopback. On a machine with no browser — SSH, a container, CI — use a pairing code instead:

listr-agent connect ABCD-1234          # code from Listr → Agents → "Connect a machine"

Either way the machine stays signed in across restarts.

Claude Code

claude mcp add listr -- npx -y @ferrousapps/listr mcp

Cursor — one click: Add Listr to Cursor

Or add it by hand to ~/.cursor/mcp.json (all projects) or .cursor/mcp.json (one project), or via Settings → MCP → Add new global MCP server:

{
  "mcpServers": {
    "listr": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@ferrousapps/listr", "mcp"]
    }
  }
}

On Windows, npx is a batch script and Cursor won't run it directly — wrap it in the command interpreter:

{
  "mcpServers": {
    "listr": {
      "type": "stdio",
      "command": "cmd",
      "args": ["/c", "npx", "-y", "@ferrousapps/listr", "mcp"]
    }
  }
}

Cursor starts the server on demand; the tools appear under Settings → MCP. If you haven't paired yet, the server still connects — the first tool call replies with the connect command to run rather than dying silently.

Windsurf — same mcpServers block in ~/.codeium/windsurf/mcp_config.json.

Cline / Roo Code — same mcpServers block via MCP Servers → Configure.

VS Code (Copilot agent mode) — .vscode/mcp.json uses a servers key:

{
  "servers": {
    "listr": { "type": "stdio", "command": "npx", "args": ["-y", "@ferrousapps/listr", "mcp"] }
  }
}

Codex CLI — in ~/.codex/config.toml:

[mcp_servers.listr]
command = "npx"
args = ["-y", "@ferrousapps/listr", "mcp"]

Gemini CLI — the mcpServers block in ~/.gemini/settings.json.

The client then has these tools:

| Tool | What it does | |---|---| | list_projects | Lists your projects (personal + shared) with their ids. Hidden/PIN lists are excluded. | | list_tasks | Lists tasks in a project; pass a parent task to see its sub-tasks. Each row carries status, priority, due date, assignees and tags, plus counts of the task's notes, comments, bugs, context entries and attachments. | | get_task | Reads one task in full — everything the task-detail view shows: description, the Notes, Bugs and Context tabs, the comments thread, attachments, status, priority, tags, due/start dates, reminder, recurrence, assignees, milestone, cycle, dependencies, estimate and time spent, number/currency, custom-field values, agent state, and sub-tasks (subtaskDepth, 0–5). | | create_task | Creates a task. Supports nesting (subtasks for a whole tree, or parentTaskId to add under an existing task) and the same fields update_task takes. | | update_task | Updates any field on a task by id: complete/incomplete, rename, description, status, priority, tags, due/start dates, reminder, repeat rule, assignees, milestone, cycle, dependencies, estimate, time spent, number/currency, custom-field values, and attachments (add or remove). | | add_note / update_note / delete_note | Sticky notes on the task-detail Notes tab. | | add_comment / delete_comment | The task's discussion thread. Posted as your account; @mentions notify teammates. The app has no comment editing, so neither does the MCP. | | add_bug / update_bug / delete_bug | Bugs logged against a task (Bugs tab). Bugs take the same fields as a task but never nest. | | list_context | Reads a task's working-context notes (the task-detail Context tab) — load this before working a task. Only that tab; use get_task for the rest. | | add_context | Appends a context note to a task (findings, decisions, repo layout). Tagged as written by the agent. | | update_context | Edits an existing context note by its entry id. | | delete_context | Removes a context note by its entry id. |

Writes go through the same rules as the app, not just the same fields. Completing a task stamps completedAt and cascades to its sub-tasks; ticking a repeating task rolls its due date forward instead of closing it; a terminal status keeps the checkbox in agreement; renaming a task with sub-tasks renames its sub-list. On shared lists every write stamps the editor and the per-task unread marker, so collaborators see the agent's changes exactly as they'd see a teammate's. Statuses, priorities, tags, milestones, cycles and custom fields accept either the stored id or the label you see in the app, and an unknown value is refused with the list of valid ones rather than written through.

Deleting whole tasks is deliberately not exposed — the agent can close, edit and annotate them, but removing them stays a decision you make in the app.

Examples of what you can ask your agent:

  • "Add a task 'Ship v2 release' to my Roadmap project with sub-tasks for QA, docs, and changelog."
  • "Create a bug ticket under the 'Auth' task and attach ./crash.log."
  • "Read the context on the 'Auth' task, then note what you changed when you're done."
  • "Open the 'Auth' task and summarise its notes, comments and logged bugs."
  • "Move the 'Auth' task to In Review, assign it to [email protected], and comment that the PR is up."
  • "Log a bug on the 'Checkout' task for the crash I just hit, priority Urgent."

Identify a project by title (case-insensitive) or id — run list_projects first if a title is ambiguous. Attachments are capped at 10 MB and reject executables, matching the app. Files on a shared list can only be uploaded by that list's owner; collaborators can still attach links.

The MCP server speaks JSON-RPC over stdio (status goes to stderr). It's a local process your MCP client starts on demand — nothing is exposed to the network. Tool schemas avoid $ref/$defs and never emit a property-less object, so they work with strict clients (Cursor with non-Claude models, Gemini CLI) too. Those clients sometimes send structured arguments as JSON strings; the server parses them, so subtasks, attachments and assignedTo work either way.

If Cursor shows the server as red / "Client closed"

  • Sign-in is not the cause — since v0.1.9 an unpaired machine still connects and reports the fix in the tool result. Run listr-agent login and retry the call; no restart needed.
  • npx must be on the PATH of the GUI app, which does not read your shell rc files. which npx in a terminal, then put that absolute path in command.
  • On Windows, use the cmd /c form above.
  • Cursor hides server output: Help → Toggle Developer Tools → Console, or the Output panel's MCP channel, shows the real error.

Configuration

Everything has a sensible default. To override, set environment variables or copy .env.example to .env next to the package (or in the directory you run from). Common knobs:

| Variable | Default | Purpose | |---|---|---| | LISTR_AGENT_AUTH | pairing | pairing (code) or password (bot user) | | LISTR_AGENT_SOURCE | own | own · collab · both | | LISTR_AGENT_ALLOW_COLLAB | 0 | required 1 for collab/both | | LISTR_AGENT_NAME | hostname | display name for this machine | | LISTR_AGENT_HOME | ~/.listr-agent | config/state directory | | CLAUDE_MODEL | opus | e.g. claude-opus-4-8 | | CLAUDE_PERMISSION_MODE | acceptEdits | Claude permission mode | | CLAUDE_ALLOWED_TOOLS | Bash Edit Write … | tools Claude may use | | CLAUDE_DANGEROUS | 0 | 1 → run Claude with --dangerously-skip-permissions | | CLAUDE_TIMEOUT_MS | 1800000 | per-run timeout (30 min) | | WORKDIR | ~/.listr-agent/repos | where remote repos are cloned | | BITBUCKET_USERNAME + BITBUCKET_APP_PASSWORD | — | Bitbucket app-password auth | | BITBUCKET_TOKEN | — | Bitbucket access token (alternative to app password) |

The Listr project's public Firebase web config is baked in, so you don't need to supply it. Forking Listr? Point the agent elsewhere with FIREBASE_* and LISTR_PAIRING_ENDPOINT — see .env.example.


State on disk

All under ~/.listr-agent (override with LISTR_AGENT_HOME):

  • machine-id — stable id for this machine
  • auth/ — the persisted Firebase session (refresh token; mode 0600)
  • credentials.json — connection marker (email/uid; mode 0600)
  • repos.json — your repo allowlist
  • repos/ — cached GitHub clones

listr-agent disconnect removes the session and signs this machine out.


Security model (please read)

  • Repo allowlist is the boundary — untrusted cloud repo values are only ever resolved against what you added locally; everything else is refused.
  • Own tasks by default. Running collaborators' tasks (collab/both) is a deliberate opt-in (LISTR_AGENT_ALLOW_COLLAB=1).
  • Per-machine session. disconnect cuts a machine off.
  • No auto-merge. Output is always a PR you review.
  • CLAUDE_DANGEROUS=1 removes Claude's permission prompts for fully unattended runs — only use it on repos/machines where that's acceptable.

Troubleshooting

  • gh not authenticated → gh auth login (needs push/PR rights on the repo).
  • Task is skipped: "not in this machine's repo allowlist" → listr-agent repos add --slug owner/repo on the machine that should run it.
  • Nothing happens after handoff → run listr-agent doctor to confirm the machine is signed in, the source includes the task's list, and its repo is allow-listed. Add --verbose to start to watch each step live.
  • Saved session expired → listr-agent login once more.
  • Claude seems stuck → it streams progress; a long pause usually means a slow step, not a hang. Raise CLAUDE_TIMEOUT_MS for big tasks.

Part of Listr. Source: ferrousdesigner/listr-ce under tools/listr-agent.