How pi-lens is configured, and what you can change. This page is the overview hub. For the full per-field docs of the config JSON, see the Configuration reference; for the complete environment-variable reference, see Environment variables; for the CLI flags in context, see Usage.
pi-lens ships with sensible defaults, so zero configuration is needed — it works out of the box. Everything below is optional tuning.
Tool root resolution is recorded in the pi-lens extension log as one bounded
line per session key: cwd <kind> <tool> cwd=<path> reason=<dispatch-root|marker:<name>|git-root|file-dir-fallback|home-cap>.
Fallbacks also create one tool-cwd-resolution degradation record per tool and
session, so repeated files do not create unbounded health or log rows.
- Environment variables (
PI_LENS_*) — read at process start; set them in the shell that launches pi, your process manager, or CI. Best for machine- or CI-scoped switches and for the handful of tuning knobs that have no config key. - CLI flags (
--no-lsp,--immediate-format, …) — per-session, passed on the pi command line. - Config JSON — a per-user global file (
~/.pi-lens/config.json) and an optional per-project file (.pi-lens.jsonat the repo root).
Every runtime toggle is settable both from the CLI and from config.json;
the two surfaces are driven by one declarative registry
(clients/lens-flag-registry.ts), so neither can gain a toggle the other lacks.
For a single toggle, highest priority first:
- Environment variable, for the toggles that have one bound (only
PI_LENS_NO_CONTEXT_INJECTIONtoday). - CLI flag.
- Nearest project
.pi-lens.jsonthat defines the key — for the three project-scoped mutation controls only (format.enabled,autofix.enabled,actionableWarnings.autoFix.enabled). In a monorepo the closest config to the edited file wins. - Global
~/.pi-lens/config.json. - Built-in default.
The --no-* one-way rule. Config keys are positive ("enabled": true means
the feature runs), so a --no-* flag corresponds to setting its key false. A
--no-* flag on the command line is a one-way switch: it can disable but never
re-enable. --no-lsp overrides lsp.enabled: true, but nothing on the CLI
overrides lsp.enabled: false. To re-enable, set the config key back to true.
Each is settable via the CLI flag or the config.json key. The Default
column is the effective behavior when nothing is set.
| CLI flag | config.json key |
Scope | Default |
|---|---|---|---|
--no-lens |
lens.enabled |
global | pi-lens on |
--no-lsp |
lsp.enabled |
global | LSP diagnostics on |
--no-autoformat |
format.enabled |
project | autoformat on (deferred) |
--immediate-format |
format.mode ("immediate") |
global | "deferred" |
--no-autofix |
autofix.enabled |
project | autofix on |
--no-tests |
tests.enabled |
global | test runner on |
--no-delta |
delta.enabled |
global | delta mode on (new diagnostics only) |
--lens-guard |
guard.enabled |
global | off |
| --no-opengrep | opengrep.enabled | global | Opengrep scanner on |
| --no-read-guard | readGuard.enabled | global | read-before-edit monitor on |
| --no-lens-context | contextInjection.enabled | global | context injection on |
| --lens-turn-summary | turnSummary.enabled | global | off |
| --lens-actionable-warnings | actionableWarnings.enabled | global | off |
| --lens-actionable-warning-actions | actionableWarnings.includeLspCodeActions | global | off |
| --lens-actionable-warning-autofix | actionableWarnings.autoFix.enabled | project | off |
| --lens-actionable-warning-all | actionableWarnings.deltaOnly (false) | global | deltaOnly on (report this turn only) |
| --lens-compact-tool-line | ui.compactToolLine | global | off (two-row tool rendering) |
| --no-lazy-tools | tools.lazy | global | lazy tools on (six situational tools start inactive) |
| --lens-turn-end-madge | turnEnd.madge.enabled | global | off (madge runs at session start, not per turn) |
--no-lazy-tools keeps every pi-lens tool active for the whole session, so the
advertised tool list never changes. The pi_lens_activate_tools loader stays
registered and keeps its usual description; under this flag the tools it names
are already active, so calling it is a no-op.
--lens-guard is EXPERIMENTAL and strictly opt-in. When enabled, actual
git commit/git push commands are blocked only for current, structured
blocking findings (including blocking test failures); advisory/no-action-required
findings do not block. Stale, malformed, or ambiguous persisted state blocks
conservatively until checks run again.
--immediate-format and --lens-actionable-warning-all are not --no-* flags,
so they set a value rather than flipping a boolean off.
These take values (numbers, arrays, strings) rather than being on/off, so they have no CLI flag. See the Configuration reference for full field docs.
| Key | Where | Default | What it does |
|---|---|---|---|
ignore |
global + project | [] |
Gitignore-style globs excluded from every scan |
widget.visible |
global | true |
Whether the diagnostics widget shows at session start |
dispatch.runnerTimeoutFloorMs |
global | none (no floor) | Minimum wall-clock budget per dispatch runner |
format.mode |
global | "deferred" |
"deferred" (at agent_end) or "immediate" |
actionableWarnings.autoFix.maxFixes |
global | 5 |
Cap on quickfixes applied per turn (0 = report only) |
rules.high-complexity.threshold |
project | 15 |
Cyclomatic-complexity threshold |
rules.high-fan-out.threshold |
project | 20 |
Distinct-function-call threshold |
rules.<id>.disable |
project | absent | Disable diagnostics for a rule (output-only filter, project-wide; same normalization as pi-lens-ignore) |
rules.<id>.select |
project | absent | Allowlist of rule ids (output-only filter, project-wide across every key; disable wins over select) |
maxProjectFiles |
project | 2000 |
Base scale knob; derives five subsystem size budgets |
reviewGraph.maxFiles |
project | derived (clamped 100–20000) |
Explicit review-graph file budget |
trivy.enabled / trivy.minSeverity |
project | off | Opt-in Trivy vulnerability scanning |
helm.renderValidation.enabled |
project | off | Opt-in helm template rendering plus rendered-manifest validation. Rendering executes chart templates, so it also requires host project trust and is read from the chart's own project root — see below |
User-level. Applies to every project. Honors all flag keys from the
table above plus the non-flag global knobs (ignore, widget.visible,
dispatch.runnerTimeoutFloorMs, format.mode,
actionableWarnings.autoFix.maxFixes). On Windows the path is
%USERPROFILE%\.pi-lens\config.json.
{
"lsp": { "enabled": true },
"tests": { "enabled": false },
"widget": { "visible": false },
"format": { "enabled": true, "mode": "immediate" },
"actionableWarnings": {
"enabled": true,
"autoFix": { "enabled": false, "maxFixes": 5 }
}
}Per-repo. Discovered by walking upward from the current directory, so a
monorepo can keep one config at the repo root and every subdirectory picks it up
(closest config wins per edited file). pi-lens.json (no leading dot) is also
accepted.
A project file honors only:
- the three mutation controls —
format.enabled,autofix.enabled,actionableWarnings.autoFix.enabled; ignore,rules,maxProjectFiles,reviewGraph,trivy, andhelm.
Rendering a Helm chart runs the chart's own Go templates, so this switch is not sufficient on its own. Two independent conditions must both hold:
- The project consents.
helm.renderValidation.enabledmust betrue, read from the.pi-lens.jsonthat governs the chart's own project root — not the current working directory. An opt-in in an unrelated directory does not authorize rendering another project's chart. - The host trusts the project.
.pi-lens.jsonis a tracked file, so a cloned repository can arrive with the switch already on and would otherwise authorize execution of its own templates. In untrusted mode pi-lens refuses to render and reports the refusal, naming trust as the reason, rather than skipping silently. This is the same trust gate that governs LSP server spawns and tool auto-installs.
Most toggles are global-only. Putting a global-only key such as
"lsp": { "enabled": false } in a .pi-lens.json is not honored at project
scope — pi-lens logs a one-time warning saying so (rather than silently doing
nothing) and you should set it in ~/.pi-lens/config.json or pass the CLI flag
instead. Foreign LSP-loader namespaces that a shared file legitimately carries
(servers, serverOverrides, disabledServers, warmFiles) and $schema are
tolerated without warning; anything else is logged once as a likely typo.
{
"ignore": ["**/*.test.ts", "vendor/**"],
"rules": {
"high-complexity": { "threshold": 25 },
"high-fan-out": { "threshold": 30 },
"no-eval": { "disable": ["no-eval", "ast-grep:no-eval", "no-eval-js"] }
},
"maxProjectFiles": 5000,
"format": { "enabled": false }
}A project's own mutation-control value wins over the global default in either
direction (a repo can re-enable a mutation path the user disabled globally, and
vice versa); only an explicit disabling CLI flag (--no-autoformat,
--no-autofix) outranks it. See
Mutation controls for the full precedence.
Environment variables are read once at process start; set them in the launching
shell (export VAR=… in bash, $env:VAR = "…" in PowerShell), your process
manager, or CI config. The handful you are most likely to reach for:
PI_LENS_NO_CONTEXT_INJECTION=1— disable automatic context injection while keeping tools, LSP, read-guard, and formatting active.PILENS_DATA_DIR— relocate per-project persistent state (caches, snapshot, review graph) out of the workspace.PI_LENS_HOME— relocate the machine-global root (logs, tool binaries, install caches, instance registry).PI_LENS_MAX_PROJECT_FILES— base project-size scale knob (default2000).PI_LENS_STARTUP_MODE— force the startup path:full,minimal, orquick.
Full environment-variable reference: environment-variables.md — every supported variable with its default, behavior, and precedence (install control, scale/limit knobs, logging, language-specific, and more).
- Configuration reference — full field-by-field docs for
~/.pi-lens/config.jsonand.pi-lens.json. - Usage — the CLI flags in context.
- Environment variables — the complete environment-variable reference.