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

@eleboucher/pi-memini

v0.7.2

Published

Shared cross-session memory for the Pi coding agent, backed by a memini service.

Readme

memini + Pi

Pi is an open-source coding agent with a first-class extension API. Pi has no built-in MCP — capabilities are added through extensions — so memini ships a native extension in plugin/ that makes memory both automatic and tool-callable, with no MCP layer required.

Recommended: the memory extension

What it wires:

  • before_agent_start — searches memini for the user's prompt and injects the matches as a persistent context message before the agent runs. It excludes this session's own captured turns (already in live context), so they aren't echoed back a turn behind; past sessions still recall.
  • agent_end — once the agent finishes a prompt, stores the completed user/assistant turn back into memini (episodic, tagged pi, with the session id) so it can be recalled later.
  • Explicit tools — modeled on the tool set Claude Code gets from memini's MCP server, registered natively via pi.registerTool: memory_recall, memory_list, memory_remember, memory_forget. The model can call them on demand even though the automatic loop already runs.

Install

The extension is published to npm as @eleboucher/pi-memini. Pi has no init/scaffold command — extensions are just discovered from known locations or declared in config. Pick one:

Project / global settings — add the package to settings.json (.pi/settings.json for one project, or ~/.pi/agent/settings.json globally):

{
  "packages": ["npm:@eleboucher/pi-memini"]
}

Discovery folder — Pi auto-discovers and hot-reloads extensions in ~/.pi/agent/extensions/ (global) or .pi/extensions/ (project-local). Drop the built dist/index.js (or the src/index.ts source) there.

Quick test — point Pi at a local checkout for one run:

pi -e ./integrations/pi/plugin/dist/index.js

Configure

All config is via environment variables in the shell that launches Pi (secrets stay out of any file):

| Env var | Default | Purpose | | -------------------------------- | -------------------------------- | ----------------------------------------------------------------------------------------- | | MEMINI_BASE_URL | http://localhost:8080 | memini REST base URL | | MEMINI_NAMESPACE | unset (server handshake decides) | machine-local namespace override; the offline escape hatch when the server is unreachable | | MEMINI_HOME | unset | caller's personal namespace, sent as X-Memini-Home; unset = no home leg | | MEMINI_RECALL | on | 0/false disables recall-before-turn | | MEMINI_CAPTURE | on | 0/false disables capture-after-turn | | MEMINI_RECALL_LIMIT | 3 | max memories injected per turn | | MEMINI_INJECT_RECALL_MAX_TOK | 0 | hard ceiling on recall-block tokens (0 = unbounded); the tail is dropped with a footer | | MEMINI_INJECT_RECALL_MIN_SCORE | 0 | fused-score floor (>=) sent as min_score to /v1/search | | MEMINI_INJECT_LABELS | — | comma-separated bullet labels: tier, confidence, age | | MEMINI_TIMEOUT_MS | 30000 | per-request timeout | | MEMINI_FALLBACK | on | 0/false surfaces errors instead of degrading silently | | MEMINI_API_KEY | — | bearer token, if memini needs auth (sent as Authorization: Bearer …) | | MEMINI_REQUIRE_HTTPS | — | 1 refuses to send the token over plaintext HTTP |

The namespace itself is resolved by the memini server, not this extension: at the first turn the extension performs the config handshake (POST /v1/handshake), sending the project's facts (git remote, toplevel, cwd basename) and using whatever the server resolves — a pin recorded for this project, MEMINI_NAMESPACE if exported, or derivation from the facts (repo name, then toplevel basename, then cwd basename). The result is memoized in memory for ten minutes. When the server is unreachable, the extension degrades to the same chain locally: MEMINI_NAMESPACE, else git/cwd derivation — which is why the env var is best thought of as the offline escape hatch, not the primary lever.

Commands

| Command | What it does | | ------------------ | ------------------------------------------------------------------------------- | | memini:status | Effective settings, the resolved namespace and where it came from, warnings | | memini:namespace | Show, set, or clear the server-side namespace pin for this project |

memini:status exists because a list of values is not enough to debug a namespace problem. It shows provenance (<- env vs <- server vs (default)), so a MEMINI_NAMESPACE exported once from a shell profile — which pins every repo on the machine to one namespace — shows up as a warning rather than as a mystery. Secrets are redacted.

The namespace pin

memini:namespace              # show the namespace and where it came from
memini:namespace acme/api     # pin this project to acme/api
memini:namespace --clear      # back to automatic resolution

The pin lives on the memini server (PUT/DELETE /v1/pins), keyed by the project's git remote and/or toplevel path — so it follows you across machines, and every client that handshakes for this project (Claude Code, this extension, memini doctor) resolves the same value.

A pin beats MEMINI_NAMESPACE at handshake time, deliberately: a globally exported MEMINI_NAMESPACE is exactly the problem a pin exists to solve, so if the environment won, the command would silently do nothing on the machines that need it. Setting or clearing a pin takes effect on the next turn — the write drops the extension's in-memory handshake memo, so there is no restart or ten-minute wait.

Because pins are server-side, setting one needs the server reachable. For an offline, machine-local override, export MEMINI_NAMESPACE instead.

Build & test

cd integrations/pi/plugin
npm install
npm run build      # esbuild bundle -> dist/index.js
npm test           # bundle test (node --test) + pure-helper unit tests (tsx --test)

Alternative: MCP wire

Pi can also reach memini's memory_* tools over MCP, but — unlike Claude Code or Codex — Pi has no native MCP client, so you first need an MCP extension for Pi (e.g. the one prewired in the my-pi distribution), then point it at memini's server: http://<host>:8080/mcp (remote) or memini mcp (stdio). The native extension above is simpler and adds the automatic recall/capture loop on top of the tools, so prefer it.