Profile
Back to NewsBack
GitHub Trending 9 min
Reader Mode
apmantza/pi-lens: Real-time code feedback for pi — LSP, linters, formatters, structural analysis

apmantza/pi-lens: Real-time code feedback for pi — LSP, linters, formatters, structural analysis

12 hours ago

pi-lens

pi-lens

omp status</a>

pi-lens gives AI coding agents fast, language-aware feedback while they write/edit.

Working in this project as an AI agent? Read the agent guide
for how pi-lens surfaces diagnostics (honesty labels, blockers, read-before-edit)
and how to respond.

What It Does

  • LSP diagnostics and navigation across supported languages
  • Impact cascade diagnostics that show which related files were affected and run LSP diagnostics on them
  • Language-specific linters, type-checkers, and scanners on every write/edit
  • Safe formatting/autofix where tools are configured or confidently detected
  • ast-grep and tree-sitter structural rules for correctness/security smells
  • Agent-facing tools for LSP navigation/diagnostics, AST search/replace,
diagnostics state, and project intelligence
  • Review-graph intelligence for supported languages via bundled tree-sitter WASMs
  • Ranked identifier search (symbol_search) over an always-warm word index,
feeding the discovery funnel (symbol_search → module_report → read_symbol)
  • Diagnostic triage (lens_diagnostic_mark): findings can be marked
false-positive, suppressed in source, deferred, or flagged-to-fix — honored across all surfaces
  • /lens-map — interactive HTML dependency map of the project
  • Read-guard and edit-autopatch support to reduce bad edits
  • Background security/dependency scans for opted-in projects
  • Runtime health telemetry (/lens-health) including a bounded degradation
ledger for silently-degraded behavior (LSP breakers, formatter skips/failures, idle evictions, timeouts)
  • MCP server (experimental) so Claude Code or any MCP client can drive the
same diagnostics/read-substitute tools pi-lens exposes to pi

Architecture

Most lifecycle events enter through one wrapper, which drops and counts events that arrive on a replaced session. tool_call registers raw: it delegates straight to a handler that owns its own total guard. Events fan out into the edit-time lane and the LSP lane. Both lanes write into the findings stores. Nothing reaches the agent from those stores until a freshness gate or an explicit age label clears it.

flowchart TD
    subgraph host["pi host"]
        HOST["Host events<br/>tool_call, tool_result, turn_start/end,<br/>session_start/shutdown, agent_end, context"]
        WRAP["Stale-ctx wrapper<br/>skips and counts events on a replaced session<br/>tool_result, turn_start, turn_end, agent_end,<br/>agent_settled, session_start, context"]
    end

subgraph guards["Guards"] RG["Read-guard<br/>blocks edits that lack prior reading"] GG["Git-guard<br/>holds commit/push while findings stay unresolved"] end

subgraph edit["Edit-time lane"] PIPE["Post-write pipeline<br/>secrets, format, autofix, sync, lint, tests"] PLAN["Dispatch plan<br/>per file kind, per capability group"] RUN["Runners<br/>format, lint, types, security, smells, docs"] STRUCT["Structural rules<br/>tree-sitter queries and ast-grep"] BUS["files-touched bus<br/>tells extensions which paths moved"] end

subgraph lsp["LSP lane"] POOL["Client pool<br/>warm reuse, idle eviction"] DIAGS["File and workspace diagnostics"] CASC["Impact cascade<br/>tiered wait policy"] end

STORES["Findings stores<br/>widget state, warning caches, project snapshot"]

subgraph gate["Freshness gating"] FRESH["Path freshness<br/>mtime vs scan time, past-EOF, dependency drift"] DISPO["Dispositions<br/>false-positive, suppress, defer, flagged"] LABEL["Explicit age label<br/>for findings no path gate can check"] end

subgraph deliver["Delivery surfaces"] TURN["Turn-end findings injection"] WIDGET["Widget and footer tally"] TOOLS["lens_diagnostics tool"] NUDGE["Agent nudges"] end

SESSION["Session lifecycle<br/>primary, sequential replacement, concurrent secondary"] SINKS["Observability sinks<br/>latency.log, degradation ledger, bounded telemetry,<br/>cache observability, cascade and tree-sitter logs"] CONFIG["Config-core<br/>resolve, merge, deny"] REVIEWGRAPH["Review-graph intelligence<br/>call graph, reverse deps, import resolution"]

HOST --> WRAP HOST -->|tool_call, raw| RG HOST -->|tool_call, raw| GG WRAP -->|session_start| SESSION WRAP -->|tool_result| PIPE WRAP -->|tool_result, records reads and writes| RG SESSION --> POOL SESSION --> STORES PIPE --> PLAN PLAN --> RUN PLAN --> STRUCT PIPE --> POOL PIPE --> BUS CONFIG --> PIPE CONFIG --> PLAN STRUCT --> REVIEWGRAPH REVIEWGRAPH --> CASC POOL --> DIAGS DIAGS --> CASC RUN --> STORES STRUCT --> STORES DIAGS --> STORES CASC --> STORES BUS --> NUDGE RG -->|read and edit history filter| NUDGE STORES --> FRESH STORES --> LABEL FRESH --> DISPO DISPO --> TURN DISPO --> WIDGET DISPO --> TOOLS LABEL --> TURN TURN --> GG WRAP --> SINKS PIPE --> SINKS RUN --> SINKS STRUCT --> SINKS POOL --> SINKS CASC --> SINKS RG --> SINKS GG --> SINKS FRESH --> SINKS

Architecture-level view, updated when a lane changes. Per-tool inventories live in features and language coverage. Today the edit-time lane carries 45+ runner modules over 35+ file kinds, and the LSP lane speaks to 50 language server definitions.

The gating box is an abstraction, not a call order. Freshness covers several independent mechanisms: path freshness against scan time, past-EOF line checks, and forward-import dependency drift. Dispositions are one more filter alongside them, not a second stage every finding walks through. Read the box as "a finding passes the gates that apply to it", and see clients/finding-delivery-gate.ts for the per-surface contract.

Install

pi install npm:pi-lens

Or from git:

pi install git:github.com/apmantza/pi-lens

pi-lens delivers its four skills through the pi.skills package manifest, so install it as a package (npm:, git:, or a local path); a package install honours the host's packages[].skills filters (for example [], !skills//SKILL.md, or -skills//SKILL.md). Loading the extension file directly (pi --extension ./index.js) does not read that manifest and loads no pi-lens skills.

Requires Node.js >=22.19.0 (matches the pi host's own floor — see engines in package.json), and a pi host of 0.86.1 or newer. pi 0.80–0.85 keep the prompt outside the request the extension can write to, so pi-lens delivers no findings there; docs/release-qa-baseline.md lists the certified hosts.

Letting a coding agent do it: paste this into its prompt.

Install pi-lens (npm:pi-lens) into pi, then read AGENTS.md in
https://github.com/apmantza/pi-lens for how the extension works and how it
expects to be operated.
npm v12 users: dependency lifecycle scripts (e.g. @ast-grep/cli's
postinstall) now require explicit approval — if npm install warns about
unreviewed install scripts, review and allow them with
npm approve-scripts, or trust the allowScripts entries already declared
in this package's package.json (maintainers: see CONTRIBUTING.md
"Lifecycle-script approvals"). Installing from a git source (pi install
git:... / pi update --extension git:...) may similarly prompt for
git-dependency approval; accept it to let the prepare build step run.

Android/Termux fallback

Try the normal install first. If it fails in @ast-grep/cli's postinstall.js with Failed to locate @ast-grep/cli native binary, the fallback below has worked in one Termux environment:

pkg install rust clang
cargo install ast-grep --locked
ast-grep --version
npm_config_ignore_scripts=true pi install npm:pi-lens

npm_config_ignore_scripts=true skips every dependency lifecycle script for that pi install command, not only the failing @ast-grep/cli script. Use it only for this fallback after installing and checking the Rust-built ast-grep binary separately. pi update runs the same postinstall, so set the variable for it too. ast-grep --version must succeed from a new shell, which means ~/.cargo/bin is on your PATH.

In the verified environment, /lens-health reported zero pipeline crashes and listed the ast-grep and bash LSP servers as available. This confirms startup and server discovery only; ast_grep_search was not tested end to end.

pi-lens only looks for an ast-grep on PATH (such as Cargo's ~/.cargo/bin/ast-grep) when pi trusts the project, so in an untrusted project this fallback leaves ast_grep_search unavailable. The in-process ast-grep rules (@ast-grep/napi) and Biome have no Android build, so they stay unavailable either way.

Documentation

  • Agent guide — how an AI agent should consume and respond to pi-lens
  • Agent tools — pi tool names, scopes, and arguments
  • Usage guide — lifecycle, tool behavior, MCP notes, and
troubleshooting
  • Features — detailed feature reference
  • Word index — identifier search (symbol_search) and
the discovery funnel suppress, defer, flagged-to-fix
  • Settings — the configuration hub: defaults, env vars, CLI
flags, and global vs project config at a glance full reference and formatters
  • Dependencies — auto-install policy and external tools
  • Custom rules — project ast-grep and tree-sitter rules
  • MCP server — experimental MCP server for Claude Code and
other MCP clients decisions, linked from the engineering-defect catalog

Contributing

See CONTRIBUTING.md for the development workflow, runner, LSP, formatter, and rule checklists, and issue/PR conventions.

Security issues should be reported privately; see SECURITY.md. pi-lens is released under the MIT License.

Contributors

Thanks goes to these wonderful people:


Apostolos Mantzaris

💻 📖 🤔 🚧 👀

Kenneth McCormick

🐛 💻 🤔 📖 ⚠️

Anh Chu

💻

minicx

💻

silvanshade

💻

Tifan Dwi Avianto

💻

Amit

💻 🐛

Fractiunate // David Rahäuser

💻

Vitali Karasenko

💻 🤔

V

💻

Fabio Dee

💻

moj02090

💻

Micah Halter

💻

Julien Ellie

💻

Ruben Paz

💻 🐛

C.Junxiang

💻 🐛

Trevon

💻

Aaron Bell

💻 🐛

Will Mitchell

💻

spyrosbazios

💻

Roman Galeev

💻

jerryfan

💻

Max L.

💻

David Ryan

💻

JayceFreeman

💻

Heitor Ramon Ribeiro

💻

Chris Patti

💻 🐛

Chenxin Yan

💻 📖 🐛

flowing-abyss

💻

shaochong-theoai

💻 🤔

Xu Yili

🐛 💻

Ricardo Raposo

💻

Justin Smestad

💻 🤔

anasalsbey-glitch

💻 🐛

정제훈

💻 🤔

Myke Stubbs

💻 🐛

JSap0914

💻

Kent Hou Man

💻 🐛

Jakub Neumann

💻 🐛 🤔

CyYu

💻

Carolina

🐛 🤔

LeakedBy

🐛

Matthew Booth

🐛

Wiedzmin89

🤔

Virgile

🐛

Finn

🤔

Wayne E

🐛

RimuruW

🤔

Bjynt

🐛 🤔

Tri Van Pham

🐛

BingWuJ

🐛

tackleberrybey

🐛

Mariann Abshire

🐛

ProbabilityEngineer

🤔

Leonardo Rick

🐛 🤔

Ken Banks

🐛

Rico Sta. Cruz

🤔

Nikita Bilous

🐛

Andrea Arturo Venti Fuentes

🐛

dacec354

🐛

Brandon Martin

🐛

Alper Tarhan

🐛

Andrius Solopovas

🐛

Graham Jenkins

🐛

Wings Butterfly

🐛

Johannes Klauss

🤔

Tan Yong Sheng

🤔

Frédéric

🐛

Salvador Fuentes Jr

🐛

Viktor

🐛 🤔

Gregory Orton

🐛

Jim Allen

🐛

quantfiction

🐛

Art

🐛

Colin Swenson-Healey

🐛

Laurent Wiesel

🐛

Rei Starks

🐛

Roberto Freitas

🐛

tmttodd

🐛

smaharnav

🐛

Mza.Guille

🐛

Jason Rimmer

🐛

Arthur Heymans

🤔

Blue-B

🐛 🤔

Biser Perchinkov

🐛

Peter Nagy

🐛

Orest Tokovenko

🐛 🤔

Federico Pasqua

🐛 🤔

Ronald

🐛 🤔

Aaron Ky-Riesenbach

🐛

可爱的龙

🐛

pppobear

🐛

Bertrand Cachet

💻 🤔

earthchen

💻 🐛

Don Yin

💻 🐛 🤔 📖 ⚠️

ELA718

📖

Sujeito Operator

💻

Dan Blah

🐛

Nathan Cooke

💻

Eli Stark

💻 🐛

Marvin Aziz

💻 🐛

Mark

💻

aeturnal

💻 🐛

floatGray

💻

Thomas F Steeples

💻 🐛

Ama Senevirathne

💻

AcademyKUB8

💻 🐛

soulocker

🐛

Johanderson Mogollon

🤔 🐛

kurihada

🐛

Giraffe224

🐛

Robert Navarro

🐛 💻

Marc

🐛

Heyner Javier Marmol Verbel

🐛

Stijnus

🐛

macroxing

🐛

John Tracy

💻

woyxiang

🤔

Juncanthia

🐛

Kevin S Kirkup

🐛

George Harker

💻 🐛 🤔

Duy /zuey/

🤔 💻

luw2007

🐛

WrongWorry

🐛

nanaxx131-gif

🐛

MateusCx

🐛

Hugh Zadora
<

... (README truncated for length)

NeshDevTech

NeshDevTech is a professional technology firm passionate about creating innovative, high-performance web and mobile solutions.

Core Services
  • Custom Laravel Apps
  • SPA (React & Vue.js)
  • Flutter Mobile Apps
  • SEO & Performance Opt
Get in Touch
Available for Projects

Need a high-performing system? Let's discuss your project.


© 2026 NeshDevTech. All rights reserved.

Built with

Chat with me