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

pi-extension-optimizer

v0.2.2

Published

Precompile TypeScript Pi extensions into dist-opt/ .js so jiti skips transpilation at cold start (~13.2s → ~3.0s in the author setup). Auto-scans enabled extensions, backs up package.json before rewriting entries, creates harness junctions, and reports re

Readme

⚡ pi-extension-optimizer

Precompile your TypeScript Pi extensions for dramatically faster startup.

Pi extension License: MIT npm version

| ⏱️ Extensions load | 🚀 Own startup cost | |---|---| | ~13.2s → ~3.0s (baseline → optimized) | 2558ms → 156ms |


✨ What it does

Pi loads every .ts extension through jiti at each cold start — a full TypeScript compile pass per file, per startup, with no disk cache (moduleCache: false). If you run several extensions (web access, MCP, status bars…), that adds up to seconds of dead time.

pi-extension-optimizer precompiles the .ts sources of your installed extensions into plain .js, and rewires their pi.extensions entry to the compiled output. jiti skips .js — zero transpilation at startup.

  • 🔍 Auto-scans every enabled package in settings.json — no hard-coded lists
  • 🛟 Backs up each package.json (.pi-orig) before touching it — one command to roll back
  • 🔗 Shares the running Pi instance — harness imports (@earendil-works/pi-coding-agent etc.) stay bare and dist-opt/ is marked "type": "commonjs", so Pi's loader resolves them to the already-running Pi. No second copy of Pi, no junctions, no Cannot find package
  • 🔁 Transpiles .ts-distributed dependency packages (e.g. @juicesharp/rpiv-config) that Node refuses to type-strip under node_modules
  • 🧪 measure reports the real startup cost (preloads the Pi harness, like the actual main process) — not a cold-subprocess artifact
  • ⚡ Lazy esbuild + zero harness-main-package imports keep the optimizer's own startup cost at ~156ms

🚀 Installation

From npm (recommended)

pi install npm:pi-extension-optimizer

From git

pi install git:github.com/LosLiSang/pi-extension-optimizer

From a local checkout

git clone https://github.com/LosLiSang/pi-extension-optimizer.git
pi install ./pi-extension-optimizer

(dist/ is committed, so no build step is needed — pi install handles dependency installation. If you modify sources, run npm install && npm run build first.)

Then restart Pi (or /reload) and run:

/ext-opt build

🕹️ Usage

| Command | Action | |---|---| | /ext-opt | Interactive menu | | /ext-opt build | Discover .ts extensions → transpile → back up → apply | | /ext-opt status | Show optimized / TypeScript / native JS / broken per package + leftover harness links | | /ext-opt measure | Time the real module-import phase in a clean child process | | /ext-opt repair | Remove harness links left by v0.1.7 and earlier, add missing commonjs markers (also runs automatically on startup) | | /ext-opt rollback | Restore every package.json from its .pi-orig backup | | /ext-opt rollback <name> | Roll back a single package | | /ext-opt lang [auto\|en\|zh] | Switch the UI language (interactive picker without an argument) |

Non-interactive mutation commands accept --yes:

/ext-opt build --yes
/ext-opt rollback --yes

🌐 Language

The UI is available in English and 简体中文. By default (auto) it follows your system locale — Chinese locales get Chinese, everything else gets English. Resolution order:

  1. PI_EXT_OPT_LANG=en|zh|auto environment variable
  2. ~/.pi/agent/ext-opt.json → { "language": "en" | "zh" | "auto" } (written by /ext-opt lang)
  3. System locale: LC_ALL → LC_MESSAGES → LANG → Intl (the only signal on Windows)

/ext-opt lang en switches immediately, no /reload needed.

📊 Performance

Measured on the author's setup (15 enabled extensions, Pi 0.83.0, real startup timing via PI_TIMING=1):

| Phase | Before | After | |---|---|---| | Extensions module import | ~13.2s (all .ts, jiti transpile) | ~3.0s (precompiled .js) | | This package's own load | 2558ms (eager esbuild + harness import) | 156ms (lazy + zero harness imports) |

The remaining ~3s is dominated by native .js dependencies each extension brings (e.g. MCP SDK, pi-tui-kit) — V8 compilation that no transpile step can remove. Precompilation eliminates the .ts transpile cost, which is the part that scales with every file of every extension.

🛠️ How it works

installed extension (node_modules/pkg)
  │  package.json  pi.extensions: ["./src/index.ts"]
  │
  ▼  /ext-opt build
  ├─ esbuild transform: src/*.ts ──────────► dist-opt/*.js   (no bundling, structure preserved)
  ├─ harness imports ("@earendil-works/pi-coding-agent" …) kept bare
  ├─ dist-opt/package.json  ← { "type": "commonjs" }
  ├─ package.json.pi-orig  ← original package.json backup
  └─ pi.extensions: ["./dist-opt/index.js"]

Pi startup:
  ├─ jiti loads dist-opt/*.js  (precompiled; jiti's fs cache makes its pass cheap)  ⚡
  ├─ harness imports → Pi's virtualModules → the running Pi instance ✓
  └─ factory registers tools/commands  (unchanged)

Why the commonjs marker? The published Pi CLI runs from a bundle and resolves @earendil-works/* imports of extensions through in-memory virtualModules — the running Pi instance. But extension packages are usually "type": "module", and jiti hands such plain .js files to Node's native import(). From there the whole subtree, including dynamic import() (e.g. pi-tool-display's config-modal → zellij-modal), is resolved by Node, which only looks in node_modules:

| node_modules/@earendil-works/pi-coding-agent | Result | |---|---| | missing | Cannot find package '@earendil-works/pi-coding-agent' | | junction to Pi (v0.1.7 and earlier created these) | works, but loads a second, unbundled copy of Pi (~+3s startup; instanceof vs. the main process fails) |

Marking dist-opt/ as commonjs makes Node's native load of these ESM files fail fast, so jiti falls back to loading them itself, and every harness import goes through virtualModules. Measured on 9 extensions: 5.4s → 2.2s startup, with /tool-display working and no junction.

Older versions (v0.1.5–0.1.7) also rewrote harness imports to file:///…/pi-coding-agent/dist/index.js, which loaded the unbundled copy as well. v0.1.8 removed the rewrite and the junctions.

🩹 Troubleshooting: Cannot find package '@earendil-works/pi-coding-agent' imported from …

Cause: a dist-opt/ built by v0.1.7 or earlier, without the commonjs marker, and no harness junction.

Fix: /ext-opt repair (or just /reload — the optimizer adds missing markers and removes old junctions on every start), then /reload. /ext-opt build --if-needed also rebuilds unmarked outputs.

WSL + nvm note (fixed in v0.1.7): npm exposes pi as a symlink such as <nvm-prefix>/bin/pi, while the real package lives under <nvm-prefix>/lib/node_modules. The optimizer resolves the CLI symlink and recognizes the Unix global npm layout when locating the Pi install (used by /ext-opt measure).

WSL vs. native Windows: keep the WSL ~/.pi/agent/npm tree separate from Windows %USERPROFILE%.piagent pm and run /ext-opt build --yes in each environment.

🔄 Upgrading

Pi package updates or npm reinstalls replace extension directories, reverting entries to .ts. Just run /ext-opt build again — automatic scanning re-optimizes everything.

↩️ Rollback

/ext-opt rollback restores every currently optimized package from its .pi-orig backup; /ext-opt rollback <name> targets a single package. dist-opt/ files remain on disk but are no longer referenced.

🔒 Safety

  • Minimal startup work — the only automatic actions are adding a missing "type": "commonjs" to existing dist-opt/package.json files and removing harness links left by older versions (idempotent, no-op when clean). Every mutation is an explicit command with a confirmation prompt (--yes to skip)
  • Only packages enabled in settings.json are touched; disabled/unused packages are never modified
  • Per-package backups before the first entry rewrite, refreshed on upgrade
  • Entry applied only when every source file transpiles successfully and the target entry exists
  • Never uploads data or contacts external services

🧰 Development

npm install
npm run build        # compile src/ → dist/
npm run test:core    # fixture tests (transpile, backup/apply/rollback, dependency-chain, commonjs marker, harness-link cleanup, locale resolution)

📄 License

MIT © LosLiSang