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

@aaarc/recursivelearnmcp

v0.1.3

Published

A recoverable recursive-learning tree with MCP, HTTP/SSE, and an embedded web UI.

Readme

@incursion/cli

The incursion command: new, ls, show, focus, rebuild, undo, orphans, serve (embedded web UI + HTTP/SSE), mcp (the complete entrypoint — the same UI and HTTP/SSE surface plus MCP over stdio), and registry (the deployable public-forest HTTP gateway backed by built-in SQLite). Run incursion with no arguments (or --help) for the full usage text.

The release tarball embeds apps/web under dist/web, so users do not need to install, start, or deploy Next.js separately. Both long-running commands print their resolved endpoints on startup. mcp prints them to stderr because stdout is reserved exclusively for JSON-RPC.

The production runtime also opens one Automerge-backed history repository beside the human-readable tree projection. Every real mutation is committed as a complete-forest checkpoint before the projection and SSE notification are published. The embedded UI's 检查点 tab can restore any checkpoint append-only; a stale HEAD or manually modified worktree is rejected instead of being silently overwritten.

Public forest deployment

incursion registry --port=7780 --db=/path/public-forest.sqlite is the self-contained reference deployment. Public reads require no credential. Writes are disabled unless INCURSION_REGISTRY_TOKEN is set, and then require Authorization: Bearer <token>. The registry validates the narrow PublishableNode schema and computes its SHA-256 server-side, so attempts, notes, verification/mastery and caller-supplied hashes cannot cross the publishing boundary. Local serve/mcp processes connect through INCURSION_REMOTE_URL; that replaceable HTTP boundary allows a later PostgreSQL or hosted-database implementation without changing MCP tools or mounted snapshot semantics.

incursion mcp: one owner, any number of Codex instances

@incursion/mcp's own bin.ts is deliberately stdio-only (see that package's README — it exists for its own subprocess tests and for hosts that only want MCP). The task brief's "MCP server 启动时默认同时起 HTTP" behavior lives here instead. incursion mcp reuses or starts one detached owner for the selected forest. The owner alone opens the Automerge writer, embedded UI, HTTP/SSE, and an authenticated local MCP-over-HTTP endpoint. Each Codex process exposes stdio by proxying to that endpoint. Many Codex windows therefore share one Engine; closing the first window does not kill the UI, and no second process can overwrite the projection. A requested port collision falls back to an OS-assigned free port recorded in runtime.json.

Because each proxy's stdout is the MCP JSON-RPC wire protocol, every informational message (including the owner PID and actual HTTP endpoint) goes to stderr, never stdout. Writing anything else to stdout would corrupt the host connection.

Color coding

show colors each rendered line by the node's most specific state: green for verified, blue for asserted, yellow for provisional, gray for pruned; everything else is printed uncolored (src/tree-view.ts). Two independent opt-outs are honored, checked in src/color.ts:

  • NO_COLOR (https://no-color.org) — presence of the variable disables color regardless of its value, even on a real TTY.
  • Non-TTY stdout — anything piped, redirected, or captured by a test's execFile/spawn auto-disables color. This isn't just a nicety: it's what makes test/cli.test.ts's output assertions byte-stable without stripping ANSI codes in every test.

Coloring is layered on top of core's own plain-text render() rather than folding color into @incursion/core itself — core's render() output is also what MCP's tree_render tool hands to a model, where ANSI escape codes would just be extra tokens to parse around for no benefit.

A core gap found while building rebuild

rebuild [tree] is meant to verify that a tree's on-disk archive is recoverable purely from (tree, nodes), by comparing every node's persisted rollup against what core's rebuildAllRollups() recomputes from scratch. In practice this needed one carve-out: recomputeRollup()'s composer always returns a string (defaultComposer("", []) is "", not null), so it can never reproduce rollup: null — the value every node actually starts at (algebra.ts's createTree) and keeps until the first close() anywhere bubbles a value into it. A freshly created, never-closed tree's root would therefore always show up as a false-positive "mismatch" (null on disk vs. "" recomputed) if compared naively. rebuildAllRollups()'s own doc comment scopes its invariant to "for any sequence of closes"; cmdRebuild (src/commands.ts) follows that same scope and skips nodes whose on-disk rollup is still null, rather than silently loosening the comparison or reporting a mismatch that core's own invariant never claimed to cover.

Testing

Every test spawns the actual built dist/bin.js — via execFile for commands that exit (test/cli.test.ts) and via spawn + a line-matching wait for the two long-running commands, serve and mcp (test/long-running.test.ts, which kills the child process in afterEach rather than waiting for it to exit on its own). No command is ever called in-process through run() directly — the point is to exercise the real binary a user would actually invoke, including argv parsing and process exit codes.