pi-lens 3.1.1 → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,712 +1,712 @@
1
- # pi-lens
2
-
3
- **pi extension for real-time code quality.** 31 LSP servers, tree-sitter structural analysis, AST pattern matching, auto-install for TypeScript/Python tooling, duplicate detection, complexity metrics, and inline blockers with comprehensive `/lens-booboo` reports.
4
-
5
- ## What pi-lens Does
6
-
7
- **For every file you edit:**
8
- 1. **Auto-formats** — Detects and runs formatters (Biome, Prettier, Ruff, gofmt, rustfmt, etc.)
9
- 2. **Type-checks** — TypeScript, Python, Go, Rust (31 languages with `--lens-lsp`)
10
- 3. **Scans for secrets** — Blocks on hardcoded API keys, tokens, passwords
11
- 4. **Runs linters** — Biome (TS/JS), Ruff (Python), plus structural analysis
12
- 5. **Tree-sitter analysis** — Deep structural patterns (empty catch, eval, deep nesting, mixed async styles)
13
- 6. **Auto-installs** — TypeScript, Python, Biome, Ruff tools install automatically on first use
14
- 7. **Only shows NEW issues** — Delta-mode tracks baselines and filters pre-existing problems
15
-
16
- **🔴 Blockers** (type errors, secrets, empty catches) appear inline and stop the agent until fixed.
17
- **🟡 Warnings** (complexity, code smells) go to `/lens-booboo` — run it to see them all.
18
-
19
- ## Quick Start
20
-
21
- ```bash
22
- # Install
23
- pi install npm:pi-lens
24
-
25
- # Standard mode (auto-formatting, type-checking, linting enabled by default)
26
- pi
27
-
28
- # Disable auto-formatting if needed
29
- pi --no-autoformat
30
-
31
- # Full LSP mode (31 language servers)
32
- pi --lens-lsp
33
-
34
- # Fastest mode (LSP + concurrent execution) (Experimental)
35
- pi --lens-lsp --lens-effect
36
- ```
37
-
38
- ## Install
39
-
40
- ```bash
41
- pi install npm:pi-lens
42
- ```
43
-
44
- Or directly from git:
45
-
46
- ```bash
47
- pi install git:github.com/apmantza/pi-lens
48
- ```
49
-
50
- ---
51
-
52
- ## Features
53
-
54
- ### Auto-Formatting (Default Enabled)
55
-
56
- pi-lens **automatically formats** every file you write or edit. Formatters are auto-detected based on your project configuration.
57
-
58
- **Priority:** **Biome** is the default. **Prettier** runs only if Biome is not configured. This prevents race conditions and ensures consistent formatting.
59
-
60
- | Formatter | Languages | Detection | Installation | Role |
61
- |-----------|-----------|-----------|--------------|------|
62
- | **Biome** ⭐ | TS/JS/JSON/CSS | `biome.json` or `@biomejs/biome` in devDependencies | ✅ Automatic | **Default** |
63
- | **Prettier** | TS/JS/JSON/CSS/Markdown | `.prettierrc` or `prettier` in devDependencies | Manual (`npm install -g prettier`) | Fallback |
64
- | **Ruff** ⭐ | Python | `[tool.ruff]` in `pyproject.toml` | ✅ Automatic | **Default** |
65
- | **Black** | Python | `[tool.black]` in `pyproject.toml` | Manual (`pip install black`) | Fallback |
66
- | **gofmt** | Go | `go` binary available | Manual (included with Go SDK) | Default |
67
- | **rustfmt** | Rust | `rustfmt` binary available | Manual (included with Rust toolchain) | Default |
68
- | **zig fmt** | Zig | `zig` binary available | Manual (included with Zig SDK) | Default |
69
- | **dart format** | Dart | `dart` binary available | Manual (included with Dart SDK) | Default |
70
- | **shfmt** | Shell | `shfmt` binary available | Manual (download binary) | Default |
71
- | **mix format** | Elixir | `mix` binary available | Manual (included with Elixir) | Default |
72
-
73
- ⭐ = Auto-installed (no manual setup required)
74
-
75
- **How it works:**
76
- 1. Agent writes a file
77
- 2. pi-lens detects formatters based on config files/dependencies
78
- 3. Biome takes priority; Prettier runs only if Biome is not configured
79
- 4. FileTime tracking ensures safety (agents re-read if file changes externally)
80
-
81
- **Safety:** If a formatter changes the file, the agent is notified and must re-read before next edit — preventing stale content overwrites.
82
-
83
- **Disable:**
84
- ```bash
85
- pi --no-autoformat # Skip automatic formatting
86
- ```
87
-
88
- ---
89
-
90
- ### Auto-Linting (Default Enabled)
91
-
92
- pi-lens **automatically lints** every file you write or edit. Linters are auto-detected based on your project configuration.
93
-
94
- | Linter | Languages | Installation | Role | Priority |
95
- |--------|-----------|--------------|------|----------|
96
- | **Biome** ⭐ | TS/JS/JSON/CSS | ✅ Automatic | **Default** | 10 |
97
- | **Ruff** ⭐ | Python | ✅ Automatic | **Default** | 10 |
98
- | **oxlint** | TS/JS | Manual (`npm i -g oxlint`) | Fast alternative | 12 |
99
- | **ESLint** | JS/Vue/Svelte | `npx` via `--lens-lsp` | LSP only | - |
100
- | **shellcheck** | Bash/sh/zsh/fish | Manual (`apt install shellcheck`) | Shell scripts | 20 |
101
-
102
- ⭐ = Auto-installed (no manual setup required)
103
-
104
- **Priority:** Lower numbers = run earlier. Biome/Ruff run first, followed by specialized linters.
105
-
106
- **How it works:**
107
- 1. Agent writes a file
108
- 2. pi-lens detects linters based on config files and file type
109
- 3. Biome takes priority for TS/JS; Ruff takes priority for Python
110
- 4. Multiple linters can run on the same file (e.g., Biome + oxlint)
111
- 5. Issues are delta-tracked (only new issues shown after first write)
112
-
113
- **Notes:**
114
- - Biome and Ruff are **dual-purpose** (lint + format)
115
- - oxlint is a faster Rust-based alternative to ESLint
116
- - ESLint only runs when `--lens-lsp` is enabled
117
- - shellcheck requires manual installation on most systems
118
-
119
- ---
120
-
121
- ### LSP Support (NEW) — 31 Language Servers
122
-
123
- Enable full Language Server Protocol support with `--lens-lsp`:
124
-
125
- | Category | Languages |
126
- |----------|-----------|
127
- | **Core** | TypeScript, Python, Go, Rust, Ruby, PHP, C#, F#, Java, Kotlin |
128
- | **Native** | C/C++, Zig, Swift, Haskell, OCaml, Lua, Dart |
129
- | **Functional** | Elixir, Gleam, Clojure, Haskell |
130
- | **DevOps** | Terraform, Nix, Docker, Bash |
131
- | **Config** | YAML, JSON, Prisma |
132
- | **Web** | Vue, Svelte, CSS/SCSS/Sass/Less |
133
-
134
- **Auto-installation (4 core tools):** TypeScript, Python, and formatting tools auto-install on first use to `.pi-lens/tools/`. Other LSP servers are launched via `npx` when available or require manual installation.
135
-
136
- **Usage:**
137
- ```bash
138
- pi --lens-lsp # Enable LSP
139
- pi --lens-lsp --lens-effect # LSP + concurrent execution
140
- ```
141
-
142
- ### `pi` vs `pi --lens-lsp`
143
-
144
- | Feature | `pi` (Default) | `pi --lens-lsp` |
145
- |---------|----------------|-----------------|
146
- | **Type Checking** | Built-in TypeScriptClient | Full LSP (31 language servers) |
147
- | **Auto-format** | ✅ Biome, Prettier, Ruff, etc. | ✅ Same |
148
- | **Auto-fix** | ✅ Enabled by default | ✅ Same |
149
- | **Secrets scan** | ✅ Blocks on hardcoded secrets | ✅ Same |
150
- | **Languages** | TypeScript, Python (built-in) | 31 languages via LSP |
151
- | **Python** | Ruff/pyright (built-in) | Pyright LSP |
152
- | **Go, Rust, etc.** | Basic linting | Full LSP support |
153
-
154
- **Recommendation:** Use `pi` for TypeScript/Python projects. Use `pi --lens-lsp` for multi-language projects or when you need full language server features.
155
-
156
- See [docs/LSP_CONFIG.md](docs/LSP_CONFIG.md) for configuration options.
157
-
158
- ---
159
-
160
- ### Execution Modes
161
-
162
- | Mode | Flag | Description |
163
- |------|------|-------------|
164
- | **Sequential** | (default) | Runners execute one at a time |
165
- | **Concurrent** | `--lens-effect` | All runners in parallel via Effect-TS (Experimental) |
166
-
167
- ---
168
-
169
- ### On every write / edit
170
-
171
- Every file write/edit triggers multiple analysis phases:
172
-
173
- **Execution flow:**
174
- 1. **Secrets scan** (pre-flight) — Hardcoded secrets block immediately (non-runner check)
175
- 2. **LSP integration** (Phase 3, with `--lens-lsp`) — Real-time type errors from language servers
176
- 3. **Dispatch system** — Routes file to appropriate runners by `FileKind`
177
- 4. **Runners execute** by priority (lower = earlier). See [Runners](#runners) section for full list.
178
- 5. **Test runner detection** (post-write) — Detects Jest/Vitest/Pytest and runs relevant tests
179
-
180
- **With `--lens-effect`:** Dispatch runners execute concurrently via Effect-TS. Test runner remains sequential (step 5).
181
-
182
- **Delta mode behavior:**
183
- - **First write:** All issues tracked and stored in baseline
184
- - **Subsequent edits:** Only **NEW** issues shown (pre-existing issues filtered out)
185
- - **Goal:** Don't spam agent with issues they didn't cause
186
-
187
- **Output shown inline:**
188
- ```
189
- 🔴 STOP — 1 issue(s) must be fixed:
190
- L23: var total = sum(items); — use 'let' or 'const'
191
- ```
192
-
193
- > **Note:** Only **blocking** issues (`ts-lsp`, `pyright` errors, `type-safety` switch errors, secrets) appear inline. Warnings are tracked but not shown inline (noise reduction) — run `/lens-booboo` to see all warnings.
194
-
195
- ---
196
-
197
- ### Runners
198
-
199
- pi-lens uses a **dispatcher-runner architecture** for extensible multi-language support. Runners are executed by priority (lower = earlier).
200
-
201
- | Runner | Language | Priority | Output | Description |
202
- |--------|----------|----------|--------|-------------|
203
- | **ts-lsp** | TypeScript | 5 | Blocking | TypeScript errors (hard stops) |
204
- | **pyright** | Python | 5 | Blocking | Python type errors (hard stops) |
205
- | **biome** | TS/JS | 10 | Warning | Linting issues (delta-tracked) |
206
- | **ruff** | Python | 10 | Warning | Python linting (delta-tracked) |
207
- | **oxlint** | TS/JS | 12 | Warning | Fast Rust-based JS/TS linter |
208
- | **tree-sitter** | TS/JS, Python | 14 | Mixed | AST-based structural analysis (17 patterns) |
209
- | **ast-grep-napi** | TS/JS | 15 | Warning | **Unified structural analysis** (104 rules) |
210
- | **type-safety** | TS | 20 | Mixed | Switch exhaustiveness (blocking), other (warning) |
211
- | **shellcheck** | Shell | 20 | Warning | Bash/sh/zsh/fish linting |
212
- | **python-slop** | Python | 25 | Warning | AI slop detection (~40 patterns) |
213
- | **spellcheck** | Markdown | 30 | Warning | Typo detection in docs |
214
- | **similarity** | TS | 35 | Silent | Semantic duplicate detection (metrics only) |
215
- | **architect** | All | 40 | Warning | Architectural rule violations |
216
- | **go-vet** | Go | 50 | Warning | Go static analysis |
217
- | **rust-clippy** | Rust | 50 | Warning | Rust linting |
218
-
219
- **Priority legend:**
220
- - **5** — Type checkers (blocking errors)
221
- - **10-15** — Linters and structural analysis
222
- - **20-30** — Specialized checks (safety, slop, spellcheck)
223
- - **35** — Metrics only (silent)
224
- - **40-50** — Language-specific and architectural
225
-
226
- **Output semantics:**
227
- - **Blocking** — Hard stop, must fix (type errors, secrets)
228
- - **Warning** — Shown in `/lens-booboo`, not inline (noise reduction)
229
- - **Silent** — Tracked in metrics only, never shown
230
-
231
- **Consolidated runners:** `ast-grep` (CLI) and `ts-slop` merged into `ast-grep-napi` — unified 104-rule set
232
-
233
- **Tree-sitter runner patterns** (priority 14, AST-based structural analysis):
234
-
235
- TypeScript/JavaScript (12 patterns):
236
- - 🔴 **Error**: empty-catch, hardcoded-secrets, eval
237
- - 🟡 **Warning**: debugger, await-in-loop, console-statement, long-parameter-list, nested-ternary, deep-promise-chain, mixed-async-styles, deep-nesting
238
-
239
- Python (6 patterns):
240
- - 🔴 **Error**: bare-except, mutable-default-arg, eval-exec, unreachable-except
241
- - 🟡 **Warning**: wildcard-import, is-vs-equals
242
-
243
- **Custom tree-sitter queries:** Add `.yml` files to `.pi-lens/rules/tree-sitter-queries/{typescript,python}/`
244
-
245
- **AI Slop Detection:**
246
- - `python-slop` runner (priority 25): ~40 patterns for Python code quality
247
- - `ast-grep-napi` runner (priority 15): 33 slop patterns + 71 security/architecture rules for TypeScript/JavaScript
248
-
249
- ---
250
-
251
- ### Additional Safeguards
252
-
253
- Safeguards that run **before** the dispatch system:
254
-
255
- #### Secrets Scanning (Pre-flight)
256
-
257
- Runs on every file write/edit **before** any other checks. Scans for:
258
- - Stripe/OpenAI keys (`sk-*`)
259
- - GitHub tokens (`ghp_*`, `github_pat_*`)
260
- - AWS keys (`AKIA*`)
261
- - Slack tokens (`xoxb-*`, `xoxp-*`)
262
- - Private keys (`BEGIN PRIVATE KEY`)
263
- - Hardcoded passwords and API keys
264
-
265
- **Behavior:** Always blocking, always runs on all file types. Cannot be disabled — security takes precedence.
266
-
267
- #### Agent Behavior Warnings
268
-
269
- Inline heuristics to catch anti-patterns in real-time:
270
-
271
- **Blind Write Detection**
272
- - **Triggers:** Agent edits a file without reading it in the last 5 tool calls
273
- - **Warning:** `⚠ BLIND WRITE — editing 'file.ts' without reading in the last 5 tool calls.`
274
- - **Why:** Prevents edits based on stale assumptions
275
-
276
- **Thrashing Detection**
277
- - **Triggers:** 3+ consecutive identical tool calls within 30 seconds
278
- - **Warning:** `🔴 THRASHING — 3 consecutive 'edit' calls with no other action.`
279
- - **Why:** Catches stuck loops where the agent repeats failed actions
280
-
281
- **Behavior:** Warnings appear inline but do **not** block execution.
282
-
283
- #### Custom ast-grep Rules
284
-
285
- Create your own structural rules in `.pi-lens/rules/`:
286
-
287
- ```yaml
288
- # .pi-lens/rules/no-console-prod.yml
289
- id: no-console-prod
290
- language: javascript
291
- rule:
292
- pattern: console.$METHOD($$$ARGS)
293
- message: "Remove console statements before production"
294
- severity: warning
295
- ```
296
-
297
- See [docs/ast-grep-rules.md](docs/ast-grep-rules.md) for full guide.
298
-
299
- ---
300
-
301
- ### At Session Start
302
-
303
- When pi starts a new session, pi-lens performs initialization scans to establish baselines and surface existing technical debt:
304
-
305
- **Initialization sequence:**
306
- 1. **Reset session state** — Clear metrics and complexity baselines
307
- 2. **Initialize LSP** (with `--lens-lsp`) — Detect and auto-install language servers
308
- 3. **Pre-install TypeScript LSP** (with `--lens-lsp`) — Warm up cache for instant response
309
- 4. **Detect available tools** — Biome, ast-grep, Ruff, Knip, jscpd, Madge, type-coverage, Go, Rust
310
- 5. **Load architect rules** — If `architect.yml` or `.architect.yml` present
311
- 6. **Detect test runner** — Jest, Vitest, Pytest, etc.
312
-
313
- **Cached scans** (with 5-min TTL):
314
- | Scan | Tool | Cached | Purpose |
315
- |------|------|--------|---------|
316
- | **TODOs** | Internal | No | Tech debt markers |
317
- | **Dead code** | Knip | Yes | Unused exports/files/deps |
318
- | **Duplicates** | jscpd | Yes | Copy-paste detection |
319
- | **Exports** | ast-grep | No | Function index for similarity |
320
-
321
- **Error debt tracking** (with `--error-debt` flag):
322
- - If tests passed at end of previous session but fail now → **regression detected**
323
- - Blocks agent until tests pass again
324
-
325
- **Output:** Scan results appear in session startup notification
326
-
327
- ---
328
-
329
- ### Code Review
330
-
331
- ```
332
- /lens-booboo [path]
333
- ```
334
-
335
- Full codebase analysis with **10 tracked runners** producing a comprehensive report:
336
-
337
- | # | Runner | What it finds |
338
- |---|--------|---------------|
339
- | 1 | **ast-grep (design smells)** | Structural issues (empty catch, no-debugger, etc.) |
340
- | 2 | **ast-grep (similar functions)** | Duplicate function patterns across files |
341
- | 3 | **semantic similarity (Amain)** | 57×72 matrix semantic clones (>75% similarity) |
342
- | 4 | **complexity metrics** | Low MI, high cognitive complexity, AI slop indicators |
343
- | 5 | **TODO scanner** | TODO/FIXME annotations and tech debt markers |
344
- | 6 | **dead code (Knip)** | Unused exports, files, dependencies |
345
- | 7 | **duplicate code (jscpd)** | Copy-paste blocks with line/token counts |
346
- | 8 | **type coverage** | Percentage typed vs `any`, low-coverage files |
347
- | 9 | **circular deps (Madge)** | Import cycles and dependency chains |
348
- | 10 | **architectural rules** | Layer violations, file size limits, path rules |
349
-
350
- **Output:**
351
- - **Terminal:** Progress `[1/10] runner...` with timing, summary with findings per runner
352
- - **JSON:** `.pi-lens/reviews/booboo-{timestamp}.json` (structured data for AI processing)
353
- - **Markdown:** `.pi-lens/reviews/booboo-{timestamp}.md` (human-readable report)
354
-
355
- **Usage:**
356
- ```bash
357
- /lens-booboo # Scan current directory
358
- /lens-booboo ./src # Scan specific path
359
- ```
360
-
361
- ---
362
-
363
- ### Test Runner
364
-
365
- **Auto-detected test runners:**
366
- | Runner | Config Files | Languages |
367
- |--------|--------------|-----------|
368
- | **Vitest** | `vitest.config.ts`, `vitest.config.js` | TypeScript, JavaScript |
369
- | **Jest** | `jest.config.js`, `jest.config.ts`, `package.json` (jest field) | TypeScript, JavaScript |
370
- | **Pytest** | `pytest.ini`, `setup.cfg`, `pyproject.toml` | Python |
371
-
372
- **Behavior:**
373
- - **On file write:** Detects corresponding test file and runs it
374
- - **Pattern matching:** `file.ts` → `file.test.ts` or `__tests__/file.test.ts`
375
- - **Output:** Inline pass/fail with failure details (shown with lint results)
376
- - **Flag:** Use `--no-tests` to disable automatic test running
377
-
378
- **Execution flow:**
379
- 1. Agent writes `src/utils.ts`
380
- 2. pi-lens finds `src/utils.test.ts` (or `__tests__/utils.test.ts`)
381
- 3. Runs only that test file (not full suite)
382
- 4. Results appear inline:
383
- ```
384
- [tests] 3 passed, 1 failed (42ms)
385
- ✓ should calculate total
386
- ✗ should handle empty array (expected 0, got undefined)
387
- ```
388
-
389
- **Why only corresponding tests?**
390
- Running the full suite on every edit would be too slow. Targeted testing gives immediate feedback for the code being edited.
391
-
392
- ---
393
-
394
- ### Complexity Metrics
395
-
396
- pi-lens calculates comprehensive code quality metrics for every source file:
397
-
398
- | Metric | Range | Description | Thresholds |
399
- |--------|-------|-------------|------------|
400
- | **Maintainability Index (MI)** | 0-100 | Composite score combining complexity, size, and structure | <20: 🔴 Unmaintainable, 20-40: 🟡 Poor, >60: ✅ Good |
401
- | **Cognitive Complexity** | 0+ | Human mental effort to understand code (nesting penalties) | >20: 🟡 Hard to understand, >50: 🔴 Very complex |
402
- | **Cyclomatic Complexity** | 1+ | Independent code paths (branch points + 1) | >10: 🟡 Complex function, >20: 🔴 Highly complex |
403
- | **Max Cyclomatic** | 1+ | Worst function in file | >10 flagged |
404
- | **Nesting Depth** | 0+ | Maximum block nesting level | >4: 🟡 Deep nesting, >6: 🔴 Excessive |
405
- | **Code Entropy** | 0-8+ bits | Shannon entropy — unpredictability of code patterns | >3.5: 🟡 Risky AI-induced complexity |
406
- | **Halstead Volume** | 0+ | Vocabulary × length — unique ops/operands | High = many different operations |
407
-
408
- **AI Slop Indicators:**
409
- - Low MI + high cognitive complexity + high entropy = potential AI-generated spaghetti code
410
- - Excessive comments (>40%) + low MI = hand-holding anti-patterns
411
- - Single-use helpers with high entropy = over-abstraction
412
-
413
- **Usage:**
414
- - `/lens-booboo` — Shows complexity table for all files
415
- - `tool_result` — Complexity tracked per file, AI slop warnings inline
416
-
417
- ---
418
-
419
- ## Dependent Tools
420
-
421
- pi-lens works out of the box for TypeScript/JavaScript. For full language support, install these tools — **all are optional and gracefully skip if not installed**:
422
-
423
- ### JavaScript / TypeScript
424
-
425
- | Tool | Install | What it does |
426
- |------|---------|--------------|
427
- | `@biomejs/biome` | `npm i -D @biomejs/biome` | Linting + formatting |
428
- | `oxlint` | `npm i -D oxlint` | Fast Rust-based JS/TS linting |
429
- | `knip` | `npm i -D knip` | Dead code / unused exports |
430
- | `jscpd` | `npm i -D jscpd` | Copy-paste detection |
431
- | `type-coverage` | `npm i -D type-coverage` | TypeScript `any` coverage % |
432
- | `@ast-grep/napi` | `npm i -D @ast-grep/napi` | Fast structural analysis (TS/JS) |
433
- | `@ast-grep/cli` | `npm i -D @ast-grep/cli` | Structural pattern matching (all languages) |
434
- | `typos-cli` | `cargo install typos-cli` | Spellcheck for Markdown |
435
-
436
- ### Python
437
-
438
- | Tool | Install | What it does |
439
- |------|---------|--------------|
440
- | `ruff` | `pip install ruff` | Linting + formatting |
441
- | `pyright` | `pip install pyright` | Type-checking (catches type errors) |
442
-
443
- ### Go
444
-
445
- | Tool | Install | What it does |
446
- |------|---------|--------------|
447
- | `go` | [golang.org](https://golang.org) | Built-in `go vet` for static analysis |
448
-
449
- ### Rust
450
-
451
- | Tool | Install | What it does |
452
- |------|---------|--------------|
453
- | `rust` + `clippy` | [rustup.rs](https://rustup.rs) | Linting via `cargo clippy` |
454
-
455
- ### Shell
456
-
457
- | Tool | Install | What it does |
458
- |------|---------|--------------|
459
- | `shellcheck` | `apt install shellcheck` / `brew install shellcheck` | Shell script linting (bash/sh/zsh/fish) |
460
-
461
- ---
462
-
463
- ## Commands
464
-
465
- | Command | Description |
466
- |---------|-------------|
467
- | `/lens-booboo` | Full codebase review (10 analysis runners) |
468
- | `/lens-format` | Apply Biome formatting |
469
- | `/lens-tdi` | Technical Debt Index and trends |
470
-
471
- ---
472
-
473
- ## Execution Modes
474
-
475
- | Mode | Command | What happens |
476
- |------|---------|--------------|
477
- | **Standard** (default) | `pi` | Auto-formatting, TS/Python type-checking, sequential execution |
478
- | **Full LSP** | `pi --lens-lsp` | Real LSP servers (31 languages), sequential execution |
479
- | **Fastest** | `pi --lens-lsp --lens-effect` | Real LSP + concurrent execution (all runners in parallel) |
480
-
481
-
482
- ### Flag Reference
483
-
484
- | Flag | Description |
485
- |------|-------------|
486
- | `--lens-lsp` | Use real Language Server Protocol servers instead of built-in type-checking |
487
- | `--lens-effect` | Run all runners **concurrently** (faster) instead of sequentially (Experimental) |
488
- | `--lens-verbose` | Enable detailed console logging |
489
- | `--no-autoformat` | Disable automatic formatting (formatting is **enabled by default**) |
490
- | `--no-autofix` | Disable all auto-fixing (Biome + Ruff autofix is **enabled by default**) |
491
- | `--no-autofix-biome` | Disable Biome auto-fix only |
492
- | `--no-autofix-ruff` | Disable Ruff auto-fix only |
493
- | `--no-oxlint` | Skip Oxlint linting |
494
- | `--no-shellcheck` | Skip shellcheck for shell scripts |
495
- | `--no-tests` | Disable automatic test running on file write |
496
- | `--no-madge` | Skip circular dependency checks |
497
- | `--no-ast-grep` | Skip ast-grep structural analysis |
498
- | `--no-biome` | Skip Biome linting |
499
- | `--no-lsp` | Skip TypeScript/Python type checking |
500
- | `--error-debt` | Track test regressions across sessions |
501
-
502
- **Recommended combinations:**
503
- ```bash
504
- pi # Default: auto-format, auto-fix, built-in type-checking
505
- pi --lens-lsp # LSP type-checking (31 languages)
506
- pi --lens-lsp --lens-effect # LSP + concurrent execution (fastest)
507
- ```
508
-
509
- ---
510
-
511
- ## TypeScript LSP — tsconfig detection
512
-
513
- The LSP walks up from the edited file's directory until it finds a `tsconfig.json`. If found, it uses that project's exact `compilerOptions` (paths, strict settings, lib, etc.). If not found, it falls back to sensible defaults:
514
-
515
- - `target: ES2020`
516
- - `lib: ["es2020", "dom", "dom.iterable"]`
517
- - `moduleResolution: bundler`
518
- - `strict: true`
519
-
520
- The compiler options are refreshed automatically when you switch between projects within a session.
521
-
522
- ---
523
-
524
- ## Exclusion Criteria
525
-
526
- pi-lens automatically excludes certain files from analysis to reduce noise and focus on production code.
527
-
528
- ### Test Files
529
-
530
- All runners respect test file exclusions — both in the dispatch system (`skipTestFiles: true`) and the `/lens-booboo` command.
531
-
532
- **Excluded patterns:**
533
- ```
534
- **/*.test.ts **/*.test.tsx **/*.test.js **/*.test.jsx
535
- **/*.spec.ts **/*.spec.tsx **/*.spec.js **/*.spec.jsx
536
- **/*.poc.test.ts **/*.poc.test.tsx
537
- **/test-utils.ts **/test-*.ts
538
- **/__tests__/** **/tests/** **/test/**
539
- ```
540
-
541
- **Why:** Test files intentionally duplicate patterns (test fixtures, mock setups) and have different complexity standards. Including them creates false positives.
542
-
543
- ### Build Artifacts (TypeScript Projects)
544
-
545
- In TypeScript projects (detected by `tsconfig.json` presence), compiled `.js` files are excluded:
546
-
547
- ```
548
- **/*.js **/*.jsx (when corresponding .ts/.tsx exists)
549
- ```
550
-
551
- **Why:** In TS projects, `.js` files are build artifacts. Analyzing them duplicates every issue (once in source `.ts`, once in compiled `.js`).
552
-
553
- **Note:** In pure JavaScript projects (no `tsconfig.json`), `.js` files are **included** as they are the source files.
554
-
555
- ### Excluded Directories
556
-
557
- | Directory | Reason |
558
- |-----------|--------|
559
- | `node_modules/` | Third-party dependencies |
560
- | `.git/` | Version control metadata |
561
- | `dist/`, `build/` | Build outputs |
562
- | `.pi-lens/`, `.pi/` | pi agent internal files |
563
- | `.next/`, `.ruff_cache/` | Framework/build caches |
564
- | `coverage/` | Test coverage reports |
565
-
566
- ### Per-Runner Exclusion Summary
567
-
568
- | Runner | Test Files | Build Artifacts | Directories |
569
- |--------|-----------|-----------------|-------------|
570
- | **dispatch runners** | ✅ `skipTestFiles` | ✅ `.js` excluded in TS | ✅ `EXCLUDED_DIRS` |
571
- | **booboo /lens-booboo** | ✅ `shouldIncludeFile()` | ✅ `isTsProject` check | ✅ `EXCLUDED_DIRS` |
572
- | **Secrets scan** | ❌ No exclusion (security) | ❌ No exclusion | ✅ Dirs excluded |
573
-
574
- ---
575
-
576
- ## Caching Architecture
577
-
578
- pi-lens uses a multi-layer caching strategy to avoid redundant work:
579
-
580
- ### 1. Tool Availability Cache
581
-
582
- **Location:** `clients/tool-availability.ts`
583
-
584
- ```
585
- ┌─────────────────────────────────────────┐
586
- │ TOOL AVAILABILITY CACHE │
587
- │ Map<toolName, {available, version}> │
588
- │ • Persisted for session lifetime │
589
- │ • Refreshed on extension restart │
590
- └─────────────────────────────────────────┘
591
- ```
592
-
593
- Avoids repeated `which`/`where` calls to check if `biome`, `ruff`, `pyright`, etc. are installed.
594
-
595
- ### 2. Dispatch Baselines (Delta Mode)
596
-
597
- **Location:** `clients/dispatch/dispatcher.ts`
598
-
599
- ```
600
- ┌─────────────────────────────────────────┐
601
- │ DISPATCH BASELINES │
602
- │ Map<filePath, Diagnostic[]> │
603
- │ • Cleared at turn start │
604
- │ • Updated after each runner execution │
605
- │ • Filters: only NEW issues shown │
606
- └─────────────────────────────────────────┘
607
- ```
608
-
609
- Delta mode tracking: first edit shows all issues, subsequent edits only show issues that weren't there before.
610
-
611
- ### 3. Client-Level Caches
612
-
613
- | Client | Cache | TTL | Purpose |
614
- |--------|-------|-----|---------|
615
- | **Knip** | `clients/cache-manager.ts` | 5 min | Dead code analysis (slow) |
616
- | **jscpd** | `clients/cache-manager.ts` | 5 min | Duplicate detection (slow) |
617
- | **Type Coverage** | In-memory | Session | `any` type percentage |
618
- | **Complexity** | In-memory | File-level | MI, cognitive complexity per file |
619
-
620
- ### 4. Session Turn State
621
-
622
- **Location:** `clients/cache-manager.ts`
623
-
624
- ```
625
- ┌─────────────────────────────────────────┐
626
- │ TURN STATE TRACKING │
627
- │ • Modified files this turn │
628
- │ • Modified line ranges per file │
629
- │ • Import changes detected │
630
- │ • Turn cycle counter (max 10) │
631
- └─────────────────────────────────────────┘
632
- ```
633
-
634
- Tracks which files were edited in the current agent turn for:
635
- - jscpd: Only re-scan modified files
636
- - Madge: Only check deps if imports changed
637
- - Cycle detection: Prevents infinite fix loops
638
-
639
- ### 5. Runner Internal Caches
640
-
641
- | Runner | Cache | Notes |
642
- |--------|-------|-------|
643
- | `ast-grep-napi` | Rule descriptions | Loaded once per session |
644
- | `biome` | Tool availability | Checked once, cached |
645
- | `pyright` | Command path | Venv lookup cached |
646
- | `ruff` | Command path | Venv lookup cached |
647
-
648
- ---
649
-
650
- ## Project Structure
651
-
652
- ```
653
- pi-lens/
654
- ├── clients/ # Lint tool wrappers and utilities
655
- │ ├── bus/ # Event bus system (Phase 1)
656
- │ │ ├── bus.ts
657
- │ │ ├── events.ts
658
- │ │ └── integration.ts
659
- │ ├── dispatch/ # Dispatcher and runners
660
- │ │ ├── dispatcher.ts
661
- │ │ └── runners/ # Individual runners
662
- │ │ ├── ast-grep-napi.ts # Fast TS/JS runner
663
- │ │ ├── python-slop.ts # Python slop detection
664
- │ │ ├── ts-lsp.ts # TS type checking
665
- │ │ ├── biome.ts
666
- │ │ ├── ruff.ts
667
- │ │ ├── pyright.ts
668
- │ │ ├── go-vet.ts
669
- │ │ └── rust-clippy.ts
670
- │ ├── lsp/ # LSP client system (Phase 3)
671
- │ │ ├── client.ts
672
- │ │ ├── server.ts # 31 LSP server definitions
673
- │ │ ├── language.ts
674
- │ │ ├── launch.ts
675
- │ │ └── config.ts # Custom LSP configuration
676
- │ ├── installer/ # Auto-installation (Phase 4)
677
- │ │ └── index.ts
678
- │ ├── services/ # Effect-TS services (Phase 2)
679
- │ │ ├── runner-service.ts
680
- │ │ └── effect-integration.ts
681
- │ ├── complexity-client.ts
682
- │ ├── type-safety-client.ts
683
- │ └── secrets-scanner.ts
684
- ├── commands/ # pi commands
685
- │ ├── booboo.ts
686
- │ └── fix-simplified.ts
687
- ├── docs/ # Documentation
688
- │ └── LSP_CONFIG.md # LSP configuration guide
689
- ├── rules/ # AST-grep rules
690
- │ └── ast-grep-rules/ # General structural rules
691
- ├── index.ts # Main entry point
692
- └── package.json
693
- ```
694
-
695
- ---
696
-
697
- ## Changelog
698
-
699
- See [CHANGELOG.md](CHANGELOG.md) for full history.
700
-
701
- ### Latest Highlights
702
-
703
- - **LSP Support:** 31 Language Server Protocol clients (4 core auto-installed, others via npx or manual)
704
- - **Concurrent Execution:** Effect-TS-based parallel runner execution with `--lens-effect`
705
- - **NAPI Runner:** 100x faster TypeScript/JavaScript structural analysis (~9ms vs ~1200ms)
706
- - **Slop Detection:** 30+ TypeScript and 40+ Python patterns for AI-generated code quality issues
707
-
708
- ---
709
-
710
- ## License
711
-
712
- MIT
1
+ # pi-lens
2
+
3
+ **pi extension for real-time code quality.** 31 LSP servers, tree-sitter structural analysis, AST pattern matching, auto-install for TypeScript/Python tooling, duplicate detection, complexity metrics, and inline blockers with comprehensive `/lens-booboo` reports.
4
+
5
+ ## What pi-lens Does
6
+
7
+ **For every file you edit:**
8
+ 1. **Auto-formats** — Detects and runs formatters (Biome, Prettier, Ruff, gofmt, rustfmt, etc.)
9
+ 2. **Type-checks** — TypeScript, Python, Go, Rust (31 languages with `--lens-lsp`)
10
+ 3. **Scans for secrets** — Blocks on hardcoded API keys, tokens, passwords
11
+ 4. **Runs linters** — Biome (TS/JS), Ruff (Python), plus structural analysis
12
+ 5. **Tree-sitter analysis** — Deep structural patterns (empty catch, eval, deep nesting, mixed async styles)
13
+ 6. **Auto-installs** — TypeScript, Python, Biome, Ruff tools install automatically on first use
14
+ 7. **Only shows NEW issues** — Delta-mode tracks baselines and filters pre-existing problems
15
+
16
+ **🔴 Blockers** (type errors, secrets, empty catches) appear inline and stop the agent until fixed.
17
+ **🟡 Warnings** (complexity, code smells) go to `/lens-booboo` — run it to see them all.
18
+
19
+ ## Quick Start
20
+
21
+ ```bash
22
+ # Install
23
+ pi install npm:pi-lens
24
+
25
+ # Standard mode (auto-formatting, type-checking, linting enabled by default)
26
+ pi
27
+
28
+ # Disable auto-formatting if needed
29
+ pi --no-autoformat
30
+
31
+ # Full LSP mode (31 language servers)
32
+ pi --lens-lsp
33
+
34
+ # Fastest mode (LSP + concurrent execution) (Experimental)
35
+ pi --lens-lsp --lens-effect
36
+ ```
37
+
38
+ ## Install
39
+
40
+ ```bash
41
+ pi install npm:pi-lens
42
+ ```
43
+
44
+ Or directly from git:
45
+
46
+ ```bash
47
+ pi install git:github.com/apmantza/pi-lens
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Features
53
+
54
+ ### Auto-Formatting (Default Enabled)
55
+
56
+ pi-lens **automatically formats** every file you write or edit. Formatters are auto-detected based on your project configuration.
57
+
58
+ **Priority:** **Biome** is the default. **Prettier** runs only if Biome is not configured. This prevents race conditions and ensures consistent formatting.
59
+
60
+ | Formatter | Languages | Detection | Installation | Role |
61
+ |-----------|-----------|-----------|--------------|------|
62
+ | **Biome** ⭐ | TS/JS/JSON/CSS | `biome.json` or `@biomejs/biome` in devDependencies | ✅ Automatic | **Default** |
63
+ | **Prettier** | TS/JS/JSON/CSS/Markdown | `.prettierrc` or `prettier` in devDependencies | Manual (`npm install -g prettier`) | Fallback |
64
+ | **Ruff** ⭐ | Python | `[tool.ruff]` in `pyproject.toml` | ✅ Automatic | **Default** |
65
+ | **Black** | Python | `[tool.black]` in `pyproject.toml` | Manual (`pip install black`) | Fallback |
66
+ | **gofmt** | Go | `go` binary available | Manual (included with Go SDK) | Default |
67
+ | **rustfmt** | Rust | `rustfmt` binary available | Manual (included with Rust toolchain) | Default |
68
+ | **zig fmt** | Zig | `zig` binary available | Manual (included with Zig SDK) | Default |
69
+ | **dart format** | Dart | `dart` binary available | Manual (included with Dart SDK) | Default |
70
+ | **shfmt** | Shell | `shfmt` binary available | Manual (download binary) | Default |
71
+ | **mix format** | Elixir | `mix` binary available | Manual (included with Elixir) | Default |
72
+
73
+ ⭐ = Auto-installed (no manual setup required)
74
+
75
+ **How it works:**
76
+ 1. Agent writes a file
77
+ 2. pi-lens detects formatters based on config files/dependencies
78
+ 3. Biome takes priority; Prettier runs only if Biome is not configured
79
+ 4. FileTime tracking ensures safety (agents re-read if file changes externally)
80
+
81
+ **Safety:** If a formatter changes the file, the agent is notified and must re-read before next edit — preventing stale content overwrites.
82
+
83
+ **Disable:**
84
+ ```bash
85
+ pi --no-autoformat # Skip automatic formatting
86
+ ```
87
+
88
+ ---
89
+
90
+ ### Auto-Linting (Default Enabled)
91
+
92
+ pi-lens **automatically lints** every file you write or edit. Linters are auto-detected based on your project configuration.
93
+
94
+ | Linter | Languages | Installation | Role | Priority |
95
+ |--------|-----------|--------------|------|----------|
96
+ | **Biome** ⭐ | TS/JS/JSON/CSS | ✅ Automatic | **Default** | 10 |
97
+ | **Ruff** ⭐ | Python | ✅ Automatic | **Default** | 10 |
98
+ | **oxlint** | TS/JS | Manual (`npm i -g oxlint`) | Fast alternative | 12 |
99
+ | **ESLint** | JS/Vue/Svelte | `npx` via `--lens-lsp` | LSP only | - |
100
+ | **shellcheck** | Bash/sh/zsh/fish | Manual (`apt install shellcheck`) | Shell scripts | 20 |
101
+
102
+ ⭐ = Auto-installed (no manual setup required)
103
+
104
+ **Priority:** Lower numbers = run earlier. Biome/Ruff run first, followed by specialized linters.
105
+
106
+ **How it works:**
107
+ 1. Agent writes a file
108
+ 2. pi-lens detects linters based on config files and file type
109
+ 3. Biome takes priority for TS/JS; Ruff takes priority for Python
110
+ 4. Multiple linters can run on the same file (e.g., Biome + oxlint)
111
+ 5. Issues are delta-tracked (only new issues shown after first write)
112
+
113
+ **Notes:**
114
+ - Biome and Ruff are **dual-purpose** (lint + format)
115
+ - oxlint is a faster Rust-based alternative to ESLint
116
+ - ESLint only runs when `--lens-lsp` is enabled
117
+ - shellcheck requires manual installation on most systems
118
+
119
+ ---
120
+
121
+ ### LSP Support (NEW) — 31 Language Servers
122
+
123
+ Enable full Language Server Protocol support with `--lens-lsp`:
124
+
125
+ | Category | Languages |
126
+ |----------|-----------|
127
+ | **Core** | TypeScript, Python, Go, Rust, Ruby, PHP, C#, F#, Java, Kotlin |
128
+ | **Native** | C/C++, Zig, Swift, Haskell, OCaml, Lua, Dart |
129
+ | **Functional** | Elixir, Gleam, Clojure, Haskell |
130
+ | **DevOps** | Terraform, Nix, Docker, Bash |
131
+ | **Config** | YAML, JSON, Prisma |
132
+ | **Web** | Vue, Svelte, CSS/SCSS/Sass/Less |
133
+
134
+ **Auto-installation (4 core tools):** TypeScript, Python, and formatting tools auto-install on first use to `.pi-lens/tools/`. Other LSP servers are launched via `npx` when available or require manual installation.
135
+
136
+ **Usage:**
137
+ ```bash
138
+ pi --lens-lsp # Enable LSP
139
+ pi --lens-lsp --lens-effect # LSP + concurrent execution
140
+ ```
141
+
142
+ ### `pi` vs `pi --lens-lsp`
143
+
144
+ | Feature | `pi` (Default) | `pi --lens-lsp` |
145
+ |---------|----------------|-----------------|
146
+ | **Type Checking** | Built-in TypeScriptClient | Full LSP (31 language servers) |
147
+ | **Auto-format** | ✅ Biome, Prettier, Ruff, etc. | ✅ Same |
148
+ | **Auto-fix** | ✅ Enabled by default | ✅ Same |
149
+ | **Secrets scan** | ✅ Blocks on hardcoded secrets | ✅ Same |
150
+ | **Languages** | TypeScript, Python (built-in) | 31 languages via LSP |
151
+ | **Python** | Ruff/pyright (built-in) | Pyright LSP |
152
+ | **Go, Rust, etc.** | Basic linting | Full LSP support |
153
+
154
+ **Recommendation:** Use `pi` for TypeScript/Python projects. Use `pi --lens-lsp` for multi-language projects or when you need full language server features.
155
+
156
+ See [docs/LSP_CONFIG.md](docs/LSP_CONFIG.md) for configuration options.
157
+
158
+ ---
159
+
160
+ ### Execution Modes
161
+
162
+ | Mode | Flag | Description |
163
+ |------|------|-------------|
164
+ | **Sequential** | (default) | Runners execute one at a time |
165
+ | **Concurrent** | `--lens-effect` | All runners in parallel via Effect-TS (Experimental) |
166
+
167
+ ---
168
+
169
+ ### On every write / edit
170
+
171
+ Every file write/edit triggers multiple analysis phases:
172
+
173
+ **Execution flow:**
174
+ 1. **Secrets scan** (pre-flight) — Hardcoded secrets block immediately (non-runner check)
175
+ 2. **LSP integration** (Phase 3, with `--lens-lsp`) — Real-time type errors from language servers
176
+ 3. **Dispatch system** — Routes file to appropriate runners by `FileKind`
177
+ 4. **Runners execute** by priority (lower = earlier). See [Runners](#runners) section for full list.
178
+ 5. **Test runner detection** (post-write) — Detects Jest/Vitest/Pytest and runs relevant tests
179
+
180
+ **With `--lens-effect`:** Dispatch runners execute concurrently via Effect-TS. Test runner remains sequential (step 5).
181
+
182
+ **Delta mode behavior:**
183
+ - **First write:** All issues tracked and stored in baseline
184
+ - **Subsequent edits:** Only **NEW** issues shown (pre-existing issues filtered out)
185
+ - **Goal:** Don't spam agent with issues they didn't cause
186
+
187
+ **Output shown inline:**
188
+ ```
189
+ 🔴 STOP — 1 issue(s) must be fixed:
190
+ L23: var total = sum(items); — use 'let' or 'const'
191
+ ```
192
+
193
+ > **Note:** Only **blocking** issues (`ts-lsp`, `pyright` errors, `type-safety` switch errors, secrets) appear inline. Warnings are tracked but not shown inline (noise reduction) — run `/lens-booboo` to see all warnings.
194
+
195
+ ---
196
+
197
+ ### Runners
198
+
199
+ pi-lens uses a **dispatcher-runner architecture** for extensible multi-language support. Runners are executed by priority (lower = earlier).
200
+
201
+ | Runner | Language | Priority | Output | Description |
202
+ |--------|----------|----------|--------|-------------|
203
+ | **ts-lsp** | TypeScript | 5 | Blocking | TypeScript errors (hard stops) |
204
+ | **pyright** | Python | 5 | Blocking | Python type errors (hard stops) |
205
+ | **biome** | TS/JS | 10 | Warning | Linting issues (delta-tracked) |
206
+ | **ruff** | Python | 10 | Warning | Python linting (delta-tracked) |
207
+ | **oxlint** | TS/JS | 12 | Warning | Fast Rust-based JS/TS linter |
208
+ | **tree-sitter** | TS/JS, Python | 14 | Mixed | AST-based structural analysis (17 patterns) |
209
+ | **ast-grep-napi** | TS/JS | 15 | Warning | **Unified structural analysis** (104 rules) — ⚠️ Temporarily disabled for debugging |
210
+ | **type-safety** | TS | 20 | Mixed | Switch exhaustiveness (blocking), other (warning) |
211
+ | **shellcheck** | Shell | 20 | Warning | Bash/sh/zsh/fish linting |
212
+ | **python-slop** | Python | 25 | Warning | AI slop detection (~40 patterns) |
213
+ | **spellcheck** | Markdown | 30 | Warning | Typo detection in docs |
214
+ | **similarity** | TS | 35 | Silent | Semantic duplicate detection (metrics only) |
215
+ | **architect** | All | 40 | Warning | Architectural rule violations |
216
+ | **go-vet** | Go | 50 | Warning | Go static analysis |
217
+ | **rust-clippy** | Rust | 50 | Warning | Rust linting |
218
+
219
+ **Priority legend:**
220
+ - **5** — Type checkers (blocking errors)
221
+ - **10-15** — Linters and structural analysis
222
+ - **20-30** — Specialized checks (safety, slop, spellcheck)
223
+ - **35** — Metrics only (silent)
224
+ - **40-50** — Language-specific and architectural
225
+
226
+ **Output semantics:**
227
+ - **Blocking** — Hard stop, must fix (type errors, secrets)
228
+ - **Warning** — Shown in `/lens-booboo`, not inline (noise reduction)
229
+ - **Silent** — Tracked in metrics only, never shown
230
+
231
+ **Consolidated runners:** `ast-grep` (CLI) and `ts-slop` merged into `ast-grep-napi` — unified 104-rule set
232
+
233
+ **Tree-sitter runner patterns** (priority 14, AST-based structural analysis):
234
+
235
+ TypeScript/JavaScript (12 patterns):
236
+ - 🔴 **Error**: empty-catch, hardcoded-secrets, eval
237
+ - 🟡 **Warning**: debugger, await-in-loop, console-statement, long-parameter-list, nested-ternary, deep-promise-chain, mixed-async-styles, deep-nesting
238
+
239
+ Python (6 patterns):
240
+ - 🔴 **Error**: bare-except, mutable-default-arg, eval-exec, unreachable-except
241
+ - 🟡 **Warning**: wildcard-import, is-vs-equals
242
+
243
+ **Custom tree-sitter queries:** Add `.yml` files to `.pi-lens/rules/tree-sitter-queries/{typescript,python}/`
244
+
245
+ **AI Slop Detection:**
246
+ - `python-slop` runner (priority 25): ~40 patterns for Python code quality
247
+ - `ast-grep-napi` runner (priority 15): 33 slop patterns + 71 security/architecture rules for TypeScript/JavaScript
248
+
249
+ ---
250
+
251
+ ### Additional Safeguards
252
+
253
+ Safeguards that run **before** the dispatch system:
254
+
255
+ #### Secrets Scanning (Pre-flight)
256
+
257
+ Runs on every file write/edit **before** any other checks. Scans for:
258
+ - Stripe/OpenAI keys (`sk-*`)
259
+ - GitHub tokens (`ghp_*`, `github_pat_*`)
260
+ - AWS keys (`AKIA*`)
261
+ - Slack tokens (`xoxb-*`, `xoxp-*`)
262
+ - Private keys (`BEGIN PRIVATE KEY`)
263
+ - Hardcoded passwords and API keys
264
+
265
+ **Behavior:** Always blocking, always runs on all file types. Cannot be disabled — security takes precedence.
266
+
267
+ #### Agent Behavior Warnings
268
+
269
+ Inline heuristics to catch anti-patterns in real-time:
270
+
271
+ **Blind Write Detection**
272
+ - **Triggers:** Agent edits a file without reading it in the last 5 tool calls
273
+ - **Warning:** `⚠ BLIND WRITE — editing 'file.ts' without reading in the last 5 tool calls.`
274
+ - **Why:** Prevents edits based on stale assumptions
275
+
276
+ **Thrashing Detection**
277
+ - **Triggers:** 3+ consecutive identical tool calls within 30 seconds
278
+ - **Warning:** `🔴 THRASHING — 3 consecutive 'edit' calls with no other action.`
279
+ - **Why:** Catches stuck loops where the agent repeats failed actions
280
+
281
+ **Behavior:** Warnings appear inline but do **not** block execution.
282
+
283
+ #### Custom ast-grep Rules
284
+
285
+ Create your own structural rules in `.pi-lens/rules/`:
286
+
287
+ ```yaml
288
+ # .pi-lens/rules/no-console-prod.yml
289
+ id: no-console-prod
290
+ language: javascript
291
+ rule:
292
+ pattern: console.$METHOD($$$ARGS)
293
+ message: "Remove console statements before production"
294
+ severity: warning
295
+ ```
296
+
297
+ See [docs/ast-grep-rules.md](docs/ast-grep-rules.md) for full guide.
298
+
299
+ ---
300
+
301
+ ### At Session Start
302
+
303
+ When pi starts a new session, pi-lens performs initialization scans to establish baselines and surface existing technical debt:
304
+
305
+ **Initialization sequence:**
306
+ 1. **Reset session state** — Clear metrics and complexity baselines
307
+ 2. **Initialize LSP** (with `--lens-lsp`) — Detect and auto-install language servers
308
+ 3. **Pre-install TypeScript LSP** (with `--lens-lsp`) — Warm up cache for instant response
309
+ 4. **Detect available tools** — Biome, ast-grep, Ruff, Knip, jscpd, Madge, type-coverage, Go, Rust
310
+ 5. **Load architect rules** — If `architect.yml` or `.architect.yml` present
311
+ 6. **Detect test runner** — Jest, Vitest, Pytest, etc.
312
+
313
+ **Cached scans** (with 5-min TTL):
314
+ | Scan | Tool | Cached | Purpose |
315
+ |------|------|--------|---------|
316
+ | **TODOs** | Internal | No | Tech debt markers |
317
+ | **Dead code** | Knip | Yes | Unused exports/files/deps |
318
+ | **Duplicates** | jscpd | Yes | Copy-paste detection |
319
+ | **Exports** | ast-grep | No | Function index for similarity |
320
+
321
+ **Error debt tracking** (with `--error-debt` flag):
322
+ - If tests passed at end of previous session but fail now → **regression detected**
323
+ - Blocks agent until tests pass again
324
+
325
+ **Output:** Scan results appear in session startup notification
326
+
327
+ ---
328
+
329
+ ### Code Review
330
+
331
+ ```
332
+ /lens-booboo [path]
333
+ ```
334
+
335
+ Full codebase analysis with **10 tracked runners** producing a comprehensive report:
336
+
337
+ | # | Runner | What it finds |
338
+ |---|--------|---------------|
339
+ | 1 | **ast-grep (design smells)** | Structural issues (empty catch, no-debugger, etc.) |
340
+ | 2 | **ast-grep (similar functions)** | Duplicate function patterns across files |
341
+ | 3 | **semantic similarity (Amain)** | 57×72 matrix semantic clones (>75% similarity) |
342
+ | 4 | **complexity metrics** | Low MI, high cognitive complexity, AI slop indicators |
343
+ | 5 | **TODO scanner** | TODO/FIXME annotations and tech debt markers |
344
+ | 6 | **dead code (Knip)** | Unused exports, files, dependencies |
345
+ | 7 | **duplicate code (jscpd)** | Copy-paste blocks with line/token counts |
346
+ | 8 | **type coverage** | Percentage typed vs `any`, low-coverage files |
347
+ | 9 | **circular deps (Madge)** | Import cycles and dependency chains |
348
+ | 10 | **architectural rules** | Layer violations, file size limits, path rules |
349
+
350
+ **Output:**
351
+ - **Terminal:** Progress `[1/10] runner...` with timing, summary with findings per runner
352
+ - **JSON:** `.pi-lens/reviews/booboo-{timestamp}.json` (structured data for AI processing)
353
+ - **Markdown:** `.pi-lens/reviews/booboo-{timestamp}.md` (human-readable report)
354
+
355
+ **Usage:**
356
+ ```bash
357
+ /lens-booboo # Scan current directory
358
+ /lens-booboo ./src # Scan specific path
359
+ ```
360
+
361
+ ---
362
+
363
+ ### Test Runner
364
+
365
+ **Auto-detected test runners:**
366
+ | Runner | Config Files | Languages |
367
+ |--------|--------------|-----------|
368
+ | **Vitest** | `vitest.config.ts`, `vitest.config.js` | TypeScript, JavaScript |
369
+ | **Jest** | `jest.config.js`, `jest.config.ts`, `package.json` (jest field) | TypeScript, JavaScript |
370
+ | **Pytest** | `pytest.ini`, `setup.cfg`, `pyproject.toml` | Python |
371
+
372
+ **Behavior:**
373
+ - **On file write:** Detects corresponding test file and runs it
374
+ - **Pattern matching:** `file.ts` → `file.test.ts` or `__tests__/file.test.ts`
375
+ - **Output:** Inline pass/fail with failure details (shown with lint results)
376
+ - **Flag:** Use `--no-tests` to disable automatic test running
377
+
378
+ **Execution flow:**
379
+ 1. Agent writes `src/utils.ts`
380
+ 2. pi-lens finds `src/utils.test.ts` (or `__tests__/utils.test.ts`)
381
+ 3. Runs only that test file (not full suite)
382
+ 4. Results appear inline:
383
+ ```
384
+ [tests] 3 passed, 1 failed (42ms)
385
+ ✓ should calculate total
386
+ ✗ should handle empty array (expected 0, got undefined)
387
+ ```
388
+
389
+ **Why only corresponding tests?**
390
+ Running the full suite on every edit would be too slow. Targeted testing gives immediate feedback for the code being edited.
391
+
392
+ ---
393
+
394
+ ### Complexity Metrics
395
+
396
+ pi-lens calculates comprehensive code quality metrics for every source file:
397
+
398
+ | Metric | Range | Description | Thresholds |
399
+ |--------|-------|-------------|------------|
400
+ | **Maintainability Index (MI)** | 0-100 | Composite score combining complexity, size, and structure | <20: 🔴 Unmaintainable, 20-40: 🟡 Poor, >60: ✅ Good |
401
+ | **Cognitive Complexity** | 0+ | Human mental effort to understand code (nesting penalties) | >20: 🟡 Hard to understand, >50: 🔴 Very complex |
402
+ | **Cyclomatic Complexity** | 1+ | Independent code paths (branch points + 1) | >10: 🟡 Complex function, >20: 🔴 Highly complex |
403
+ | **Max Cyclomatic** | 1+ | Worst function in file | >10 flagged |
404
+ | **Nesting Depth** | 0+ | Maximum block nesting level | >4: 🟡 Deep nesting, >6: 🔴 Excessive |
405
+ | **Code Entropy** | 0-8+ bits | Shannon entropy — unpredictability of code patterns | >3.5: 🟡 Risky AI-induced complexity |
406
+ | **Halstead Volume** | 0+ | Vocabulary × length — unique ops/operands | High = many different operations |
407
+
408
+ **AI Slop Indicators:**
409
+ - Low MI + high cognitive complexity + high entropy = potential AI-generated spaghetti code
410
+ - Excessive comments (>40%) + low MI = hand-holding anti-patterns
411
+ - Single-use helpers with high entropy = over-abstraction
412
+
413
+ **Usage:**
414
+ - `/lens-booboo` — Shows complexity table for all files
415
+ - `tool_result` — Complexity tracked per file, AI slop warnings inline
416
+
417
+ ---
418
+
419
+ ## Dependent Tools
420
+
421
+ pi-lens works out of the box for TypeScript/JavaScript. For full language support, install these tools — **all are optional and gracefully skip if not installed**:
422
+
423
+ ### JavaScript / TypeScript
424
+
425
+ | Tool | Install | What it does |
426
+ |------|---------|--------------|
427
+ | `@biomejs/biome` | `npm i -D @biomejs/biome` | Linting + formatting |
428
+ | `oxlint` | `npm i -D oxlint` | Fast Rust-based JS/TS linting |
429
+ | `knip` | `npm i -D knip` | Dead code / unused exports |
430
+ | `jscpd` | `npm i -D jscpd` | Copy-paste detection |
431
+ | `type-coverage` | `npm i -D type-coverage` | TypeScript `any` coverage % |
432
+ | `@ast-grep/napi` | `npm i -D @ast-grep/napi` | Fast structural analysis (TS/JS) |
433
+ | `@ast-grep/cli` | `npm i -D @ast-grep/cli` | Structural pattern matching (all languages) |
434
+ | `typos-cli` | `cargo install typos-cli` | Spellcheck for Markdown |
435
+
436
+ ### Python
437
+
438
+ | Tool | Install | What it does |
439
+ |------|---------|--------------|
440
+ | `ruff` | `pip install ruff` | Linting + formatting |
441
+ | `pyright` | `pip install pyright` | Type-checking (catches type errors) |
442
+
443
+ ### Go
444
+
445
+ | Tool | Install | What it does |
446
+ |------|---------|--------------|
447
+ | `go` | [golang.org](https://golang.org) | Built-in `go vet` for static analysis |
448
+
449
+ ### Rust
450
+
451
+ | Tool | Install | What it does |
452
+ |------|---------|--------------|
453
+ | `rust` + `clippy` | [rustup.rs](https://rustup.rs) | Linting via `cargo clippy` |
454
+
455
+ ### Shell
456
+
457
+ | Tool | Install | What it does |
458
+ |------|---------|--------------|
459
+ | `shellcheck` | `apt install shellcheck` / `brew install shellcheck` | Shell script linting (bash/sh/zsh/fish) |
460
+
461
+ ---
462
+
463
+ ## Commands
464
+
465
+ | Command | Description |
466
+ |---------|-------------|
467
+ | `/lens-booboo` | Full codebase review (10 analysis runners) |
468
+ | `/lens-format` | Apply Biome formatting |
469
+ | `/lens-tdi` | Technical Debt Index and trends |
470
+
471
+ ---
472
+
473
+ ## Execution Modes
474
+
475
+ | Mode | Command | What happens |
476
+ |------|---------|--------------|
477
+ | **Standard** (default) | `pi` | Auto-formatting, TS/Python type-checking, sequential execution |
478
+ | **Full LSP** | `pi --lens-lsp` | Real LSP servers (31 languages), sequential execution |
479
+ | **Fastest** | `pi --lens-lsp --lens-effect` | Real LSP + concurrent execution (all runners in parallel) |
480
+
481
+
482
+ ### Flag Reference
483
+
484
+ | Flag | Description |
485
+ |------|-------------|
486
+ | `--lens-lsp` | Use real Language Server Protocol servers instead of built-in type-checking |
487
+ | `--lens-effect` | Run all runners **concurrently** (faster) instead of sequentially (Experimental) |
488
+ | `--lens-verbose` | Enable detailed console logging |
489
+ | `--no-autoformat` | Disable automatic formatting (formatting is **enabled by default**) |
490
+ | `--no-autofix` | Disable all auto-fixing (Biome + Ruff autofix is **enabled by default**) |
491
+ | `--no-autofix-biome` | Disable Biome auto-fix only |
492
+ | `--no-autofix-ruff` | Disable Ruff auto-fix only |
493
+ | `--no-oxlint` | Skip Oxlint linting |
494
+ | `--no-shellcheck` | Skip shellcheck for shell scripts |
495
+ | `--no-tests` | Disable automatic test running on file write |
496
+ | `--no-madge` | Skip circular dependency checks |
497
+ | `--no-ast-grep` | Skip ast-grep structural analysis |
498
+ | `--no-biome` | Skip Biome linting |
499
+ | `--no-lsp` | Skip TypeScript/Python type checking |
500
+ | `--error-debt` | Track test regressions across sessions |
501
+
502
+ **Recommended combinations:**
503
+ ```bash
504
+ pi # Default: auto-format, auto-fix, built-in type-checking
505
+ pi --lens-lsp # LSP type-checking (31 languages)
506
+ pi --lens-lsp --lens-effect # LSP + concurrent execution (fastest)
507
+ ```
508
+
509
+ ---
510
+
511
+ ## TypeScript LSP — tsconfig detection
512
+
513
+ The LSP walks up from the edited file's directory until it finds a `tsconfig.json`. If found, it uses that project's exact `compilerOptions` (paths, strict settings, lib, etc.). If not found, it falls back to sensible defaults:
514
+
515
+ - `target: ES2020`
516
+ - `lib: ["es2020", "dom", "dom.iterable"]`
517
+ - `moduleResolution: bundler`
518
+ - `strict: true`
519
+
520
+ The compiler options are refreshed automatically when you switch between projects within a session.
521
+
522
+ ---
523
+
524
+ ## Exclusion Criteria
525
+
526
+ pi-lens automatically excludes certain files from analysis to reduce noise and focus on production code.
527
+
528
+ ### Test Files
529
+
530
+ All runners respect test file exclusions — both in the dispatch system (`skipTestFiles: true`) and the `/lens-booboo` command.
531
+
532
+ **Excluded patterns:**
533
+ ```
534
+ **/*.test.ts **/*.test.tsx **/*.test.js **/*.test.jsx
535
+ **/*.spec.ts **/*.spec.tsx **/*.spec.js **/*.spec.jsx
536
+ **/*.poc.test.ts **/*.poc.test.tsx
537
+ **/test-utils.ts **/test-*.ts
538
+ **/__tests__/** **/tests/** **/test/**
539
+ ```
540
+
541
+ **Why:** Test files intentionally duplicate patterns (test fixtures, mock setups) and have different complexity standards. Including them creates false positives.
542
+
543
+ ### Build Artifacts (TypeScript Projects)
544
+
545
+ In TypeScript projects (detected by `tsconfig.json` presence), compiled `.js` files are excluded:
546
+
547
+ ```
548
+ **/*.js **/*.jsx (when corresponding .ts/.tsx exists)
549
+ ```
550
+
551
+ **Why:** In TS projects, `.js` files are build artifacts. Analyzing them duplicates every issue (once in source `.ts`, once in compiled `.js`).
552
+
553
+ **Note:** In pure JavaScript projects (no `tsconfig.json`), `.js` files are **included** as they are the source files.
554
+
555
+ ### Excluded Directories
556
+
557
+ | Directory | Reason |
558
+ |-----------|--------|
559
+ | `node_modules/` | Third-party dependencies |
560
+ | `.git/` | Version control metadata |
561
+ | `dist/`, `build/` | Build outputs |
562
+ | `.pi-lens/`, `.pi/` | pi agent internal files |
563
+ | `.next/`, `.ruff_cache/` | Framework/build caches |
564
+ | `coverage/` | Test coverage reports |
565
+
566
+ ### Per-Runner Exclusion Summary
567
+
568
+ | Runner | Test Files | Build Artifacts | Directories |
569
+ |--------|-----------|-----------------|-------------|
570
+ | **dispatch runners** | ✅ `skipTestFiles` | ✅ `.js` excluded in TS | ✅ `EXCLUDED_DIRS` |
571
+ | **booboo /lens-booboo** | ✅ `shouldIncludeFile()` | ✅ `isTsProject` check | ✅ `EXCLUDED_DIRS` |
572
+ | **Secrets scan** | ❌ No exclusion (security) | ❌ No exclusion | ✅ Dirs excluded |
573
+
574
+ ---
575
+
576
+ ## Caching Architecture
577
+
578
+ pi-lens uses a multi-layer caching strategy to avoid redundant work:
579
+
580
+ ### 1. Tool Availability Cache
581
+
582
+ **Location:** `clients/tool-availability.ts`
583
+
584
+ ```
585
+ ┌─────────────────────────────────────────┐
586
+ │ TOOL AVAILABILITY CACHE │
587
+ │ Map<toolName, {available, version}> │
588
+ │ • Persisted for session lifetime │
589
+ │ • Refreshed on extension restart │
590
+ └─────────────────────────────────────────┘
591
+ ```
592
+
593
+ Avoids repeated `which`/`where` calls to check if `biome`, `ruff`, `pyright`, etc. are installed.
594
+
595
+ ### 2. Dispatch Baselines (Delta Mode)
596
+
597
+ **Location:** `clients/dispatch/dispatcher.ts`
598
+
599
+ ```
600
+ ┌─────────────────────────────────────────┐
601
+ │ DISPATCH BASELINES │
602
+ │ Map<filePath, Diagnostic[]> │
603
+ │ • Cleared at turn start │
604
+ │ • Updated after each runner execution │
605
+ │ • Filters: only NEW issues shown │
606
+ └─────────────────────────────────────────┘
607
+ ```
608
+
609
+ Delta mode tracking: first edit shows all issues, subsequent edits only show issues that weren't there before.
610
+
611
+ ### 3. Client-Level Caches
612
+
613
+ | Client | Cache | TTL | Purpose |
614
+ |--------|-------|-----|---------|
615
+ | **Knip** | `clients/cache-manager.ts` | 5 min | Dead code analysis (slow) |
616
+ | **jscpd** | `clients/cache-manager.ts` | 5 min | Duplicate detection (slow) |
617
+ | **Type Coverage** | In-memory | Session | `any` type percentage |
618
+ | **Complexity** | In-memory | File-level | MI, cognitive complexity per file |
619
+
620
+ ### 4. Session Turn State
621
+
622
+ **Location:** `clients/cache-manager.ts`
623
+
624
+ ```
625
+ ┌─────────────────────────────────────────┐
626
+ │ TURN STATE TRACKING │
627
+ │ • Modified files this turn │
628
+ │ • Modified line ranges per file │
629
+ │ • Import changes detected │
630
+ │ • Turn cycle counter (max 10) │
631
+ └─────────────────────────────────────────┘
632
+ ```
633
+
634
+ Tracks which files were edited in the current agent turn for:
635
+ - jscpd: Only re-scan modified files
636
+ - Madge: Only check deps if imports changed
637
+ - Cycle detection: Prevents infinite fix loops
638
+
639
+ ### 5. Runner Internal Caches
640
+
641
+ | Runner | Cache | Notes |
642
+ |--------|-------|-------|
643
+ | `ast-grep-napi` | Rule descriptions | Loaded once per session |
644
+ | `biome` | Tool availability | Checked once, cached |
645
+ | `pyright` | Command path | Venv lookup cached |
646
+ | `ruff` | Command path | Venv lookup cached |
647
+
648
+ ---
649
+
650
+ ## Project Structure
651
+
652
+ ```
653
+ pi-lens/
654
+ ├── clients/ # Lint tool wrappers and utilities
655
+ │ ├── bus/ # Event bus system (Phase 1)
656
+ │ │ ├── bus.ts
657
+ │ │ ├── events.ts
658
+ │ │ └── integration.ts
659
+ │ ├── dispatch/ # Dispatcher and runners
660
+ │ │ ├── dispatcher.ts
661
+ │ │ └── runners/ # Individual runners
662
+ │ │ ├── ast-grep-napi.ts # Fast TS/JS runner
663
+ │ │ ├── python-slop.ts # Python slop detection
664
+ │ │ ├── ts-lsp.ts # TS type checking
665
+ │ │ ├── biome.ts
666
+ │ │ ├── ruff.ts
667
+ │ │ ├── pyright.ts
668
+ │ │ ├── go-vet.ts
669
+ │ │ └── rust-clippy.ts
670
+ │ ├── lsp/ # LSP client system (Phase 3)
671
+ │ │ ├── client.ts
672
+ │ │ ├── server.ts # 31 LSP server definitions
673
+ │ │ ├── language.ts
674
+ │ │ ├── launch.ts
675
+ │ │ └── config.ts # Custom LSP configuration
676
+ │ ├── installer/ # Auto-installation (Phase 4)
677
+ │ │ └── index.ts
678
+ │ ├── services/ # Effect-TS services (Phase 2)
679
+ │ │ ├── runner-service.ts
680
+ │ │ └── effect-integration.ts
681
+ │ ├── complexity-client.ts
682
+ │ ├── type-safety-client.ts
683
+ │ └── secrets-scanner.ts
684
+ ├── commands/ # pi commands
685
+ │ ├── booboo.ts
686
+ │ └── fix-simplified.ts
687
+ ├── docs/ # Documentation
688
+ │ └── LSP_CONFIG.md # LSP configuration guide
689
+ ├── rules/ # AST-grep rules
690
+ │ └── ast-grep-rules/ # General structural rules
691
+ ├── index.ts # Main entry point
692
+ └── package.json
693
+ ```
694
+
695
+ ---
696
+
697
+ ## Changelog
698
+
699
+ See [CHANGELOG.md](CHANGELOG.md) for full history.
700
+
701
+ ### Latest Highlights
702
+
703
+ - **LSP Support:** 31 Language Server Protocol clients (4 core auto-installed, others via npx or manual)
704
+ - **Concurrent Execution:** Effect-TS-based parallel runner execution with `--lens-effect`
705
+ - **NAPI Runner:** 100x faster TypeScript/JavaScript structural analysis (~9ms vs ~1200ms)
706
+ - **Slop Detection:** 30+ TypeScript and 40+ Python patterns for AI-generated code quality issues
707
+
708
+ ---
709
+
710
+ ## License
711
+
712
+ MIT