@gaodes/pi-lens
Real-time code feedback for pi — LSP, linters, formatters, type-checking, structural analysis & booboo
Package details
Install @gaodes/pi-lens from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@gaodes/pi-lens- Package
@gaodes/pi-lens- Version
3.8.41- Published
- May 3, 2026
- Downloads
- not available
- Author
- gaodes
- License
- MIT
- Types
- extension, skill
- Size
- 2 MB
- Dependencies
- 5 dependencies · 1 peer
Pi manifest JSON
{
"extensions": [
"./index.ts"
],
"skills": [
"./skills"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@gaodes/pi-lens
Fork of pi-lens by Apostolos Mantzaris — MIT License
This fork is maintained by El Che under the
@gaodesnpm scope. The original project and author retain full credit for their work.
Real-time inline code feedback for AI agents.
What It Does
On Write/Edit
On every write and edit, pi-lens runs a fast, language-aware pipeline (checks depend on file language, project config, and installed tools):
- Secrets scan — blocking; aborts the write if credentials are detected
- Auto-format — deferred to
agent_endby default; queued files are formatted once after all agent tool calls complete. Use--immediate-formatfor per-edit formatting - Auto-fix — safe autofixes from 6 tools (Biome
check --write, Ruffcheck --fix, ESLint--fix, stylelint--fix, sqlflufffix, RuboCop-a) applied before analysis - LSP file sync — opens/updates the file in active language servers
- Dispatch lint — parallel runner groups: LSP diagnostics, tree-sitter structural rules, ast-grep security/correctness rules, fact rules, language-specific linters, similarity detection
- Cascade diagnostics — review-graph impact cascade showing which other files were affected and how diagnostics propagated
Results are inline and actionable:
- Blocking issues — stop progress until fixed
- Warnings — summarized inline, detail in
/lens-booboo - Health/telemetry — available in
/lens-health
Agent End
At agent_end (once per user prompt, after all agent tool calls complete):
- Deferred formatting — any files queued during the turn are formatted once, synced to LSP, and tracked for read-guard coverage
- Summary notification — concise status: how many files were formatted, which changed, and whether any formatter failed
Session Start
At session_start, pi-lens:
- resets runtime state and diagnostic telemetry
- detects project root, language profile, and active tools
- applies language-aware startup defaults for tool preinstall
- warms caches and optional indexes (with overlap/session guardrails)
- emits missing-tool install hints for detected languages when relevant
- prepends session guidance before the user's prompt so provider bridges keep the real prompt active
- opens
warmFiles(if configured in.pi-lens/lsp.json) to seed lazy-indexing language servers like clangd before the first symbol query
For one-shot print sessions (for example pi --print ...), pi-lens auto-uses a quick startup path that skips heavy bootstrap work to reduce startup latency. Override with PI_LENS_STARTUP_MODE=full|minimal|quick.
Turn End
At turn_end, pi-lens:
- summarizes deferred findings (for example duplicates/circulars)
- persists turn findings for next context injection
- updates debt/diagnostic tracking and cleans transient state
- renders a review-graph impact cascade showing affected files and diagnostic propagation
- fires test runs for all modified files (non-blocking); failures are injected into the next turn's context when ready
- manages LSP server lifecycle with a 240s idle timeout (resets when editing resumes)
Install
pi install npm:@gaodes/pi-lens
Features
LSP Support
pi-lens includes 37 language server definitions. LSP is enabled by default (--lsp or no flag). Servers are auto-discovered from PATH, project node_modules, and managed installs. When a server is not installed, pi-lens offers an interactive install prompt.
LSP Idle Management: LSP servers shut down after 240 seconds of inactivity (no files modified) to free resources. The timer resets when you resume editing, preventing cold-start penalties during active development.
Warm files: For language servers that index lazily (e.g. clangd), configure warmFiles in .pi-lens/lsp.json to open entry-point files at session start so the server has AST/index context before the first symbol query:
{ "warmFiles": ["src/main.cpp", "src/lib.cpp"] }
LSP servers for: TypeScript, Deno, Python (pyright + pylsp), Go, Rust, Ruby (ruby-lsp + solargraph), PHP, C# (omnisharp), F#, Java, Kotlin, Swift, Dart, Lua, C/C++, Zig, Haskell, Elixir, Gleam, OCaml, Clojure, Terraform, Nix, Bash, Docker, YAML, JSON, HTML, TOML, Prisma, Vue, Svelte, ESLint, CSS.
Formatters
pi-lens auto-detects and runs 26 formatters based on project config:
biome, prettier, ruff, black, sqlfluff, gofmt, rustfmt, zig fmt, dart format, shfmt, nixfmt, mix format, ocamlformat, clang-format, ktlint, rubocop, standardrb, gleam format, terraform fmt, php-cs-fixer, csharpier, fantomas, swiftformat, stylua, ormolu, taplo
Detection rules:
- Config-gated: only runs when project config indicates usage (e.g.
biome.json,.prettierrc,ruff.toml) - Nearest-wins: when multiple formatter configs exist at different directory levels, the one closest to the edited file wins
- Biome-default: for JS/TS files without Prettier or Biome config, Biome is used as the default formatter
- Ruff-default: for Python files without Black config, Ruff format is used when available
Review Graph - Cascade Diagnostics
pi-lens builds a review graph (file → symbol → dependency) during session and uses it at turn end to render an impact cascade: which files were affected by a change and how diagnostics propagated through the dependency graph. Nodes track kind, language, and export status; edges track contains/imports/calls/references.
Read-Before-Edit Guard
pi-lens enforces a read-before-edit policy on all file writes and edits. Before allowing a write or edit tool call on an existing file, it verifies that the agent has previously read sufficient context:
- Zero-read block — blocks any edit to a file not read in the current session
- File-modified block — blocks if the file changed on disk since the last read (auto-format, external tool, or a previous edit that was then reformatted)
- Out-of-range block — blocks if the edit target lines fall outside the ranges previously read, ensuring the agent cannot modify code it hasn't seen
Coverage is tracked across multiple reads: two reads of lines 1–100 and 101–200 together satisfy a full-file write. Symbol-expanded reads (small reads silently widened to the enclosing symbol via tree-sitter) count toward coverage at the symbol level. Markdown, text, and log files are exempt.
Override for a single edit: /lens-allow-edit <path>
Configure behavior with --no-read-guard to disable entirely, or set mode to warn instead of block.
Opportunistic Read Expansion
When the agent reads a small slice of a file (≤ 60 lines), pi-lens transparently expands the read to the full enclosing symbol (function, method, or class) using the tree-sitter AST. The agent receives the full symbol as context, and the read guard records symbol-level coverage so edits anywhere within that symbol pass without requiring the agent to have read every line individually. Expansion runs within a 200 ms budget and falls back silently on unsupported file types or parse failures.
Supported: TypeScript, TSX, JavaScript, JSX, Python, Go, Rust, Ruby.
Fact Rules Pipeline
Covers JavaScript/TypeScript, Python, Go, Rust, Ruby, Shell, and CMake. Dispatch includes a fact-rule engine that extracts function-level metrics (cyclomatic complexity, nesting depth, outgoing calls) and evaluates quality rules inline:
- high-complexity — flags functions exceeding configurable CC thresholds
- unsafe-boundary — detects dangerous boundary crossings (unvalidated user input → trusted context)
- high-fan-out — flags excessive outgoing call count (default threshold: 20)
- comment-facts — classifies comment quality (TODO density, doc coverage)
- try-catch-facts — flags empty/obscuring catch blocks
- import-facts — detects circular/star/unused imports
- file-role — classifies files as source/test/config/vendor and adjusts severity
Tree-sitter Rules
Structural rules are organized by language in rules/tree-sitter-queries/:
- TypeScript (18 rules): console-statement, debugger, deep-nesting, eval, sql-injection, ssrf, weak-hash, unsafe-regex, variable-shadowing, and more
- Python (26 rules): debug statements, hardcoded secrets, mutable class attrs, unsafe regex, empty except, and more
- Go (17 rules): defer-in-loop, hardcoded secrets, unchecked errors, and more
- Rust (6 rules): unsafe blocks, unwrap outside tests, and more
- Ruby (15 rules): empty rescue, rescue Exception, debugger, hardcoded secrets, and more
Ast-Grep Rules
180+ rules in rules/ast-grep-rules/ across JS, TS, and Python:
- Security — no-eval, jwt-no-verify, no-hardcoded-secrets, no-insecure-randomness, no-inner-html, no-javascript-url, weak-rsa-key
- Correctness — strict-equality, no-cond-assign, no-constant-condition, no-dupe-keys, no-nan-comparison, array-callback-return, constructor-super
- Style/smells — nested-ternary, long-parameter-list, large-class, prefer-optional-chain, redundant-state, require-await
- Agent stubs — no-unimplemented-stub, no-raise-not-implemented, no-ellipsis-body
Dependencies
Auto-install behavior depends on gate type:
- Config-gated: installs only when project config/deps indicate usage
- Flow/language-gated: installs when the runtime path needs it for the current file/session flow
- Operational prewarm: installs during session warm scans / turn-end analysis paths
- GitHub release: platform-specific binary downloaded from GitHub releases to
~/.pi-lens/bin/
| Tool | Purpose | Auto-installed | Gate |
|---|---|---|---|
@biomejs/biome |
JS/TS lint/format/autofix | Yes | Config-gated |
prettier |
Formatting fallback | Yes | Config-gated |
yamllint |
YAML linting | Yes | Config-gated |
sqlfluff |
SQL linting/formatting | Yes | Config-gated |
ruff |
Python lint/format/autofix | Yes | Language-default + flow-gated |
typescript-language-server |
Unified LSP diagnostics | Yes | Language-default |
typescript |
TypeScript compiler | Yes | Language-default |
pyright |
Python type diagnostics fallback | Yes | Flow/language-gated |
@ast-grep/cli (sg) |
AST scans/search/replace | Yes | Operational prewarm |
knip |
Dead code analysis | Yes | Operational prewarm + config-gated |
jscpd |
Duplicate code detection | Yes | Operational prewarm + config-gated |
madge |
Circular dependency analysis | Yes | Turn-end analysis flow |
mypy |
Python type checking | Yes | Flow-gated |
stylelint |
CSS/SCSS/Less linting | Yes | Config-gated |
markdownlint-cli2 |
Markdown linting | Yes | Config-gated |
shellcheck |
Shell script linting | Yes | GitHub release |
shfmt |
Shell script formatting | Yes | GitHub release |
rust-analyzer |
Rust LSP | Yes | GitHub release |
golangci-lint |
Go linting | Yes | GitHub release |
hadolint |
Dockerfile linting | Yes | GitHub release |
ktlint |
Kotlin linting | Yes | GitHub release |
tflint |
Terraform linting | Yes | GitHub release |
taplo |
TOML linting/formatting | Yes | GitHub release |
terraform-ls |
Terraform LSP | Yes | GitHub release |
htmlhint |
HTML linting | Yes | Config-gated |
@prisma/language-server |
Prisma LSP | Yes | Flow-gated |
dockerfile-language-server-nodejs |
Dockerfile LSP | Yes | Flow-gated |
intelephense |
PHP LSP | Yes | Flow-gated |
bash-language-server |
Bash LSP | Yes | Language-default |
yaml-language-server |
YAML LSP | Yes | Language-default |
vscode-langservers-extracted |
JSON/ESLint/CSS/HTML LSP | Yes | Language-default |
vscode-css-languageserver |
CSS LSP | Yes | Language-default |
vscode-html-languageserver-bin |
HTML LSP | Yes | Language-default |
svelte-language-server |
Svelte LSP | Yes | Flow-gated |
@vue/language-server |
Vue LSP | Yes | Flow-gated |
psscriptanalyzer |
PowerShell linting | Manual | — |
Additional language servers (gopls, ruby-lsp, solargraph, etc.) are auto-detected from PATH or installed via native package managers (go install, gem install) when their language is detected.
Run
# Standard mode (LSP enabled by default)
pi
# Optional switches
pi --no-lsp # Disable unified LSP diagnostics
pi --no-autoformat # Skip auto-formatting entirely
pi --immediate-format # Format immediately after each edit instead of deferring to agent_end
pi --no-autofix # Skip auto-fix (Biome, Ruff, ESLint, stylelint, sqlfluff, RuboCop)
pi --no-tests # Skip test runner
pi --no-delta # Disable delta mode (show all diagnostics, not just new ones)
pi --lens-guard # Block git commit/push when unresolved blockers exist (experimental)
Environment Variables
PILENS_DATA_DIR— redirect per-project state (scanner caches, turn-state.json) out of the project directory. By default pi-lens writes<cwd>/.pi-lens/; if set, it writes to<PILENS_DATA_DIR>/<sanitized-cwd-slug>/instead. Useful for keeping repos clean or for mounted/ephemeral setups. Tool binaries always live in~/.pi-lens/bin/regardless.PI_LENS_STARTUP_MODE—full|minimal|quick. Override the auto-selected startup path. One-shotpi --printsessions auto-usequickto reduce latency.
Key Commands
/lens-booboo— full quality report for current project state/lens-health— runtime health, latency, and diagnostic telemetry/lens-tools— tool installation status: globally installed, auto-installed, or npx fallback/lens-tdi— Technical Debt Index (TDI) and project health trend
Language Coverage
pi-lens supports 35+ languages through dispatch runners and LSP integration.
Formatting uses a single selected formatter per file: explicit project config wins, otherwise pi-lens uses a smart default where supported, and config-first ecosystems do not autoformat without config.
Dispatch is diagnostics-oriented: automatic formatting and safe autofix happen in the post-write pipeline rather than through dispatch format-check runners.
| Language | LSP | Dispatch Runners | Formatter |
|---|---|---|---|
| JavaScript/TypeScript | ✓ | lsp, ts-lsp, biome-check-json, tree-sitter, ast-grep-napi, type-safety, similarity, fact-rules, eslint, oxlint | biome, prettier |
| Python | ✓ | lsp, pyright, ruff-lint, tree-sitter, python-slop | ruff, black |
| Go | ✓ | lsp, go-vet, golangci-lint, tree-sitter | gofmt |
| Rust | ✓ | lsp, rust-clippy, tree-sitter | rustfmt |
| Ruby | ✓ | lsp, rubocop, tree-sitter | rubocop, standardrb |
| C/C++ | ✓ | lsp, cpp-check | clang-format |
| Shell | ✓ | lsp, shellcheck | shfmt |
| CSS/SCSS/Less | ✓ | lsp, stylelint | biome, prettier |
| HTML | ✓ | lsp, htmlhint | prettier |
| YAML | ✓ | lsp, yamllint | prettier |
| JSON | ✓ | lsp | biome, prettier |
| SQL | — | sqlfluff | sqlfluff |
| Markdown | — | spellcheck, markdownlint | prettier |
| Docker | ✓ | lsp, hadolint | — |
| PHP | ✓ | lsp, php-lint, phpstan | php-cs-fixer |
| PowerShell | ✓ | lsp, psscriptanalyzer | — |
| Prisma | ✓ | lsp, prisma-validate | — |
| C# | ✓ | lsp, dotnet-build | csharpier |
| F# | ✓ | lsp | fantomas |
| Java | ✓ | lsp, javac | — |
| Kotlin | ✓ | lsp, ktlint | ktlint |
| Swift | ✓ | lsp | swiftformat |
| Dart | ✓ | lsp, dart-analyze | dart format |
| Lua | ✓ | lsp | stylua |
| Zig | ✓ | lsp, zig-check | zig fmt |
| Haskell | ✓ | lsp | ormolu |
| Elixir | ✓ | lsp, elixir-check, credo | mix format |
| Gleam | ✓ | lsp, gleam-check | gleam format |
| OCaml | ✓ | lsp | ocamlformat |
| Clojure | ✓ | lsp | — |
| Terraform | ✓ | lsp, tflint | terraform fmt |
| Nix | ✓ | lsp | nixfmt |
| TOML | ✓ | lsp, taplo | taplo |
| CMake | ✓ | lsp | — |
Statusbar Widget (PrimeCodex fork)
pi-lens integrates with pi-statusbar to show live code quality in the footer:
OK(green) — clean, no issuesLSP:2 · 3 issues · 5 fixed— combined view with worst-state coloring (green → yellow → red)- Updates after every
turn_endwith LSP count, unresolved diagnostics, pipeline crashes, and auto-fix count
Configure in prime-settings.json:
{
"pi-lens": {
"statusbar": {
"icon": "f121",
"icon_color": "accent",
"text_font_color": "dim",
"show_icon": true,
"show_text": true,
"min_width": 12,
"placement": { "line": 3, "side": "left", "index": 1 },
"separator_before": { "icon": "eb8a", "icon_color": "dim" },
"separator_after": { "icon": "eb8a", "icon_color": "dim" }
}
}
}
The existing ctx.ui.setStatus() fallback is preserved — if pi-statusbar is not loaded, the widget calls silently no-op.
Provenance
| What | Where |
|---|---|
| Upstream | npm:pi-lens · GitHub by Apostolos Mantziris |
| PrimeCodex source | ~/agents/primecodex/extensions/pi-lens/ |
| GitLab mirror | ssh://git@gitlab-ssh.elches.dev:2222/agents/primecodex/extensions/pi-lens.git |
| npm (fork) | @gaodes/pi-lens |
License
MIT — see LICENSE.
