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.1.6

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 .jszero 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
  • 🔗 Rewrites harness imports (@earendil-works/pi-coding-agent etc.) to absolute file URLs in the output, so runtime resolution never depends on fragile links — Cannot find package errors are structurally impossible for rebuilt extensions
  • 🔁 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 + harness junction health | | /ext-opt measure | Time the real module-import phase in a clean child process | | /ext-opt repair | Check and fix harness junctions immediately (fallback mechanism only) | /ext-opt rollback | Restore every package.json from its .pi-orig backup | | /ext-opt rollback <name> | Roll back a single package |

Non-interactive mutation commands accept --yes:

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

📊 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)
  ├─ rewrite harness imports: "@earendil-works/pi-coding-agent" ──► "file:///…/pi-coding-agent/dist/index.js"
  ├─ package.json.pi-orig  ← original package.json backup
  └─ pi.extensions: ["./dist-opt/index.js"]

Pi startup:
  ├─ jiti loads dist-opt/index.js  → .js → NO transpile  ⚡
  ├─ native-loaded subtrees (pure JS ESM handed to native import())
  │    └─ harness imports are file URLs → resolve directly, no node_modules lookup ✓
  └─ factory registers tools/commands  (unchanged)

Why the rewrite? Some import() chains end up in jiti's native-loading path: a plain .js module inside a "type": "module" package is handed to Node's native import(), and every bare import beneath it (e.g. @earendil-works/pi-coding-agent in zellij-modal.js) is then resolved by Node's ESM resolver, which only looks in real node_modules dirs — but the harness packages live outside Pi's node_modules. The optimizer rewrites those bare imports to absolute file: URLs of the real harness entries (same resolution pi's loader uses), so the native chain resolves directly — no junction, no fragility. Junctions are still created as a fallback for old builds and subpath imports, and are self-healed on every Pi start.

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

Symptom: an optimized extension's command (e.g. /tool-display) throws Cannot find package '@earendil-works/pi-coding-agent' imported from …\dist-opt\src\zellij-modal.js — typically right after you install/uninstall/update a Pi package.

Root cause (fixed since v0.1.5): pi install … runs npm inside ~/.pi/agent/npm. npm's reify treats the harness junction as extraneous — it's a peerDependency, not present in package-lock.json — and deletes it. Native-loaded subtrees of the extension then fail their bare-import resolution with ERR_MODULE_NOT_FOUND.

The fix: since v0.1.5 the optimizer rewrites harness bare imports to absolute file: URLs at build time, so rebuilt extensions resolve directly to the real harness and never depend on the junction — npm can delete it a thousand times and /tool-display keeps working. Junctions remain only as a fallback for builds made by older optimizer versions and subpath imports.

If you still see the error:

/ext-opt build --yes   # rebuilds all extensions with the file-URL rewrite (v0.1.5+)
/reload

Old builds (v0.1.4 and earlier) rely on the junction, which is auto-healed on every Pi start/reload (/ext-opt repair fixes it immediately in the current session).

🔄 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 (the build also re-creates any missing junctions).

⚠️ Junction permissions (Windows): creating junctions requires administrator rights or Developer Mode. If creation fails, the build itself still succeeds (static imports are handled by jiti aliases), but runtime dynamic import() of harness packages will fail with Cannot find package. Such failures are now surfaced as warnings in the build result — run pi elevated or enable Developer Mode, then rebuild.

↩️ 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

  • Read-only at startup — the only automatic action is verifying the harness junctions and repairing them when missing (idempotent, no-op when healthy). 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, junction behavior)

📄 License

MIT © LosLiSang