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-lens-bridge

v2.2.4

Published

OpenCode V2 plugin that pushes pi-lens findings into agent context after edits, and settles pi-lens turn-end when a session execution finishes

Readme

pi-lens-bridge

OpenCode V2 plugin that pushes pi-lens diagnostics into agent context after an edit, and admits pi-lens turn-end settlement when a session execution finishes. pi-lens stays an untouched black box: the bridge only runs its shipped pi-lens-analyze CLI and registers its MCP server.

Install

Two commands, any platform:

npm i -g pi-lens                 # pi-lens itself is user-installed and user-updated
opencode plugin add pi-lens-bridge

Published packages ship the TUI entry as precompiled JavaScript (dist/tui.js): OpenCode does not apply the Solid TSX transform to files inside node_modules. A local directory install must run npm run build once before it is loaded.

On Windows, the standard npm global install is enough: the bridge probes npm.cmd, the npm global root, and the pi-lens-analyze.cmd shim. No manual path configuration is required.

npm installs of the bridge ship compiled dist/ JavaScript for the MCP launcher, and store installs resolve it automatically; repository installs keep using the TypeScript launcher. An MCP entry the bridge recorded earlier is rewritten to the current command at plugin activation.

The bridge resolves pi-lens from PATH, then from the npm global root, and derives the analyze CLI and the MCP server from that single package through its public bin metadata (pi-lens-analyze, pi-lens-mcp). A pi-lens release that moves internal files without renaming those bins keeps working, and a self-registered MCP entry is updated to the new server path.

@opencode/plugin is a development dependency only. OpenCode provides the plugin runtime; the published package does not install a second OpenCode SDK tree.

What it does

  • After edit, write, or patch completes on a covered file, runs pi-lens-analyze --file=<path> and appends a bounded findings block to the tool result the model reads.
  • One tool call is bounded: at most 3 files, 2 analyses at once, one shared analysis per absolute path, and 6 seconds total. A timed-out inline analysis keeps running; the background registration joins the same analysis instead of spawning a second one.
  • Deferrals and pending files are aggregated into one counted note with a bounded sample. The total text one tool result may gain is capped.
  • When a session execution ends, runs pi-lens-analyze --turn-end against the workspace's warm MCP server. Every non-empty report is admitted as bounded, sanitized, untrusted synthetic context with resume: false; blocking, advisory, and test text are all preserved as data. The bridge does not infer a blocker from marker text in a test dump.
  • Settlement waits up to 2 seconds for pending background registrations. Files still pending are disclosed in the admitted report. A rejected registration marks the path unregistered immediately.
  • The worklist survives a resolver recovery; a stale background failure cannot tear down a replacement runtime.
  • At most once per 24 hours, compares the installed pi-lens version with npm's latest and writes one log line when a newer one exists. Concurrent settlements share one probe.
  • Records every concluded pi-lens run (post-edit injection, turn-end settlement, agent-initiated MCP call) in a bounded per-directory history and surfaces it in the TUI.
  • Never fails the edit: every failure is a one-line note in the result or a log line, and the tool result is otherwise untouched.

Silence means clean. A skipped analysis, a spawn failure, or a missing pi-lens always carries a line saying so.

Run metrics

The package's ./tui export adds a PI-LENS block to the sidebar and a /pilens-runs command. The sidebar shows one row per file per lane, newest first within each lane:

PI-LENS
• ts edit app.ts 2
▪ -- off
✦ ts analyze runs.ts 1
✦ ts health -- 0

| Symbol | Lane | | --- | --- | | • | post-edit injection | | ▪ | turn-end settlement | | ✦ | agent-initiated pi-lens MCP call |

Edit and agent rows are <symbol> <language> <tool> <file> <amount>; turn-end rows keep <symbol> <language> <reason>. Tool names lose the bridge namespace and one leading pilens_ word (pi-lens_pilens_analyze becomes analyze). File names are basenames only — directories are never stored or shown — and a legacy record without one renders --.

Amounts are compact: a findings count counts blocking and warning entries only (advisories are excluded), 0 means the run completed without findings, × means the run failed, and a skipped run keeps its short reason word. 0 on a tool that never reports findings means "the call completed", not "zero issues were checked". Error reasons and capture times live in the panel.

A lane keeps its five newest per-file rows; older files collapse into a muted ✦ … +N more files line. Each lane is capped independently, so a busy agent lane never hides edit or turn-end rows. The panel lists every retained run newest-first with tool, file, amount, bounded error reason, and capture time.

Colors follow the result: findings use the info tone, clean uses success, errors use error, and skips use muted. No duration is shown, and nothing claims language-server activity.

Records are bounded to 20 per directory, redacted at entry, and mirrored to ~/.pi-lens/bridge/runs.json with an atomic write. The TUI reads the plugin RPC channel first and merges the file on a one-second poll, so a channel interruption degrades without restarting OpenCode. The recorder is a side channel: a failure never changes a tool result, a settlement message, or an MCP call outcome.

Execution safety

Automatic paths do not execute pi-lens's cold analyzer or turn-end scans by default.

Host trust gate

Execution-sensitive options are ignored unless the host environment contains:

PILENS_BRIDGE_TRUSTED_OPTIONS=1

This gate cannot be set through opencode.json. It covers command, allowCommandOverride, inheritEnv, coldFallback, turnEndTests, turnEndScans, and autoSession. A project or repository configuration can set the option names, but without the host gate the bridge logs one notice and uses the safe default.

Turn-end settlement

turnEndScans defaults to false; settlement does not run without it. If pi-lens's own test lane is enabled, turnEndTests is also required. The bridge reads pi-lens's effective tests.enabled toggle (PI_LENS_CONFIG_PATH, otherwise ~/.pi-lens/config.json); unreadable or malformed config counts as enabled, so failures fail closed.

pi-lens's turn-end pass includes scanners beyond tests (for example knip, madge, and dependency/cascade work). The scans opt-in covers that whole pass; the bridge cannot selectively disable individual pi-lens lanes.

MCP environment

OpenCode merges the host environment into an MCP child, so a config-level environment map cannot remove provider tokens. When the bridge creates the MCP entry itself, it registers a small launcher instead of the server directly. The launcher starts pi-lens with the analyzer allowlist and proxies stdio. inheritEnv plus the host gate switches both CLI children and the launcher to full inheritance. A user-written MCP entry is never changed.

Cold analyzer

With no confirmed warm MCP server, edit-time analysis returns an unavailable note instead of invoking the cold analyzer. This check is best-effort: pi-lens-analyze can still fall back to its internal cold path if the server disconnects after the check. The bridge does not claim that cold execution is impossible without an upstream warm-only contract.

Environment

Analyzer children and the bridge-owned MCP launcher receive an allowlisted environment (PATH, home, temp, locale, Windows process plumbing, XDG_*, PI_LENS_*). Provider keys, registry tokens, NODE_OPTIONS, and NODE_PATH are not forwarded. Full environment inheritance requires the host gate.

Output

Analyzer and settlement text is stripped of control sequences, pattern-redacted for common credentials, framed as untrusted data, and capped. Per-block and total injection caps bound a wide patch; truncation is visible. Redaction is pattern-based and best-effort; it is not a guarantee that every secret shape is caught.

Command override

A configured command requires both allowCommandOverride: true and the host gate. It is ignored otherwise.

When pi-lens is missing

The bridge is off: the first covered edit of a session after a completed failed probe carries one line naming the remedy (npm i -g pi-lens), no analysis runs, and no lifecycle settlement or MCP registration happens. Rechecks run in the background with 60s, 5m, and 15m backoff; unrelated tool calls are not delayed. While the first probe is still running, the bridge does not claim pi-lens is missing. Install pi-lens and the bridge recovers without an OpenCode restart. If pi-lens disappears later, a runtime ENOENT enters the same recovering state.

Options

Pass options in the plugins entry of opencode.json. All are optional; the zero-option install is the supported path.

{
  "plugins": [
    {
      "package": "pi-lens-bridge",
      "options": {
        "cooldownMs": 3000,
      },
    },
  ],
}

| Option | Default | Meaning | | --- | --- | --- | | command | resolved from pi-lens | Explicit argv prefix for the analysis CLI; requires allowCommandOverride and the host gate. | | allowCommandOverride | false | Explicit consent for command; also requires the host gate. | | extensions | TS/JS family, Python, Rust, Go, shell, Markdown, HTML/CSS, JSON, protobuf | Extensions analyzed after an edit. | | exclude | node_modules, .git, dist, build, target, vendor, .venv, __pycache__ | Glob patterns; a pattern without a leading / matches at any depth. At most 256 patterns of 512 characters. | | cooldownMs | 3000 | Minimum gap between analyses of one path in one session. 0 disables deferral. | | maxFindings | 10 | Findings rendered per injection; the rest is reported as a count. | | timeoutMs | 20000 | Per-analysis subprocess ceiling; the inline pass still stops waiting at 6s. | | turnEndTests | false | Allow settlement while pi-lens's own test lane is enabled. Executes repository tests. Requires the host gate. | | turnEndScans | false | Allow turn-end settlement, including project scans. Requires the host gate. | | coldFallback | false | Allow the cold analyzer when no warm MCP server is confirmed. Requires the host gate. May execute project-local tools. | | inheritEnv | false | Forward the full host environment to analyzer children and the self-registered MCP launcher. Requires the host gate. Exposes host secrets. | | autoSession | false | Add PI_LENS_MCP_AUTO_SESSION=1 to the self-registered MCP entry. Requires the host gate. | | forceSettlement | false | Run settlement even when no covered edit was registered; turnEndScans is still required. | | mcpRegistration | true | Create the bridge-owned pi-lens MCP entry when the user has none. |

Turn-end settlement uses a fixed 60s subprocess budget because it runs after the execution already ended. Settlement is serialized: one process at a time across all sessions. Terminal events are coalesced per session.

Upgrading from 1.x

This is a breaking release. The host gate, turnEndScans, and full-report settlement admission are new. Users who need the previous behavior must set PILENS_BRIDGE_TRUSTED_OPTIONS=1 in the host environment and enable turnEndTests / turnEndScans / coldFallback / inheritEnv explicitly.

MCP registration and health

The bridge records the entry it created. If the user writes or edits the pi-lens entry, it is treated as user-owned and never modified. A self-owned entry is updated when the resolved server path or environment changes. A failed registration retries with bounded backoff. The MCP transform cannot distinguish a user-removed entry from a fresh config replay, so self-registration is maintained while enabled; set mcpRegistration: false or disable the plugin to opt out.

The bridge checks the host's MCP status before using the warm lane (cached for 5 seconds, single-flight, refreshed on mcp.status.changed). Pending, disabled, failed, or missing entries produce an unavailable note instead of a silent cold fallback. A disabled or differently-built user entry is reported once and left untouched.

Update checks

The probe is log-only and runs at most once per 24 hours. A per-plugin memory latch single-flights the probe; no durable-storage read or network call happens inside the window. The probe runs from a neutral temporary directory with an empty npm user config, using npm.cmd on Windows, so a project .npmrc cannot steer registry or credential settings. The reported version is validated and sanitized.

Distribution

The published package carries index.ts, tui.tsx, src/, LICENSE, README.md, and package.json; it never ships tests or a dependency on pi-lens. License: MIT. Supported Node: >=22.19.0.

@opencode/plugin is a development dependency; the host provides it at runtime. @opentui/core, @opentui/solid, and solid-js are peer dependencies used only by the ./tui entry; the host supplies them to TUI plugins. npm ls --omit=dev on the package is empty apart from the package itself.

npm publish runs scripts/pack-audit.mjs first (prepublishOnly). The audit fails on tests, sensitive-looking files, credential-shaped content, missing license/repository/engine metadata, a pi-lens dependency, or a host-provided OpenCode runtime dependency.

Disable and roll back

  • Disable without uninstalling: append -pilens-bridge to plugins.
  • Remove: opencode plugin remove pi-lens-bridge (and drop the entry if the CLI leaves it). Pull-based pi-lens MCP tools keep working unchanged.
  • Roll back to 1.x: reinstall the previous package. The only new durable state is the plugin-scoped MCP ownership record, which older versions ignore.

Development

The package lives in the private ocp repository at modules/pilens-bridge/. The loop points a project config entry at the checkout by absolute path; publishing is a separate release step.

npm ci
npm test          # behavioral tests, no pi-lens install required
npm run lint
npm run typecheck
npm run format:check
npm run pack:audit

CI runs the full modules/scripts/check.sh gate on Ubuntu, macOS, and Windows.