# LSP diagnostics
[Feature docs index](README.md) · [Repository README](../../README.md)
## Overview
LSP diagnostics are an opt-in live feedback loop for coding sessions. After successful `write` or `hash_edit`, magi-code can sync the changed file to a language server, wait briefly for fresh diagnostics, and append a capped `DIAGNOSTICS` block to the same tool result.
This gives faster, immediate feedback on syntax, types, and compiler-style diagnostics after edits. It complements normal project checks; it does not replace `cargo check`, tests, linters, or repository-specific verification.
## Enablement and settings
LSP is disabled by default. Enable it in non-secret `settings.json` only when the needed language servers are installed on `PATH`.
```json
{
"capabilities": { "lsp": {
"enabled": true,
"inject_diagnostics_on_edit": true,
"diagnostics_wait_ms": 2000,
"idle_shutdown_minutes": 10,
"servers": {
"rust-analyzer": { "command": "rust-analyzer", "args": [] },
"typescript-language-server": { "command": "typescript-language-server", "args": ["--stdio"] }
}
}
} }
```
Fields:
| `enabled` | Starts LSP support for the session. Default `false`; disabled mode spawns no language servers and injects no diagnostics. |
| `inject_diagnostics_on_edit` | When `true`, successful `write` and `hash_edit` calls can append fresh diagnostics to tool output. Default `true` when LSP is enabled. |
| `diagnostics_wait_ms` | Total edit-injection LSP budget, including cold spawn, initialize, sync, and diagnostic wait. Default `2000`; max `30000`. |
| `idle_shutdown_minutes` | Idle server shutdown window. Default `10`; max `240`. |
| `servers` | Optional command/args overrides for built-in server route keys. Values are direct process args, not shell-expanded. |
## Supported language defaults
Built-in routes:
| `.rs` | `rust` | `rust-analyzer` | `rust-analyzer` |
| `.ts`, `.tsx` | `typescript` | `typescript-language-server` | `typescript-language-server --stdio` |
| `.js`, `.jsx` | `javascript` | `typescript-language-server` | `typescript-language-server --stdio` |
| `.py` | `python` | `pyright-langserver` | `pyright-langserver --stdio` |
| `.go` | `go` | `gopls` | `gopls` |
First release supports command/args overrides for these route keys. It does not add code actions, rename, formatting, hover, completion, semantic tokens, custom extension routing, or multi-root workspaces.
## Edit injection behavior
Injection runs only after successful `write` or `hash_edit` file mutations. The changed file must be a UTF-8 text file inside the workspace root and match a supported route. Shell/external-editor changes are not watched.
When fresh diagnostics arrive before `diagnostics_wait_ms`, magi-code appends a redacted block shaped like:
```text
DIAGNOSTICS (rust-analyzer, src/example.rs):
ERROR [E0382] line 42: borrow of moved value: `value`
WARNING [unused_imports] line 3: unused import: `std::fmt`
(2 shown, 0 truncated)
```
Injected blocks show errors and warnings, omit information/hints, cap at 20 diagnostics, and cap appended text at about 2 KiB. No fresh diagnostics before the deadline means no block is appended; magi-code does not emit empty placeholders.
## Limits and caps
| Edit injection | 20 diagnostics and about 2 KiB appended text. |
| Edit wait | `diagnostics_wait_ms`, including spawn/init/sync/wait. |
| Server lifetime | Autonomous watchdog shutdown after `idle_shutdown_minutes` without accepted live-client use; planned idle shutdown/restart does not consume recovery budget. |
Caps keep provider-visible tool output small and deterministic.
## Degradation/failure behavior
LSP never changes edit success. Missing binaries, spawn failures, crashes, stale diagnostics, indexing delays, timeouts, unsupported file types, and disabled settings cause injection to be skipped.
Server lifecycle behavior:
- Servers spawn lazily on the first matching edit.
- Warm servers are reused within the session.
- Idle servers are stopped by the autonomous watchdog after the configured idle window and restart on the next matching edit.
- Unexpected client failures allow two recoveries after the initial attempt; the third unexpected failure disables that server for the session. Planned idle stop/restart does not change this counter.
- Edit injection stays quiet unless fresh diagnostics are available.
## Privacy/redaction boundaries
LSP output follows normal tool-output privacy rules:
- Injected diagnostics are redacted before provider-visible output or session persistence.
- Raw language-server stdout/stderr is never exposed to provider context, sessions, hooks, or docs.
- Server child processes run with filtered environment handling; provider API keys and token-shaped environment variables are not forwarded.
- Edit diagnostic injection is workspace-bound.
- `settings.json` is non-secret; do not place credentials in LSP server command args.
## Troubleshooting
Missing server:
- Confirm `capabilities.lsp.enabled=true`.
- Install the needed language server and confirm its command is on `PATH`.
- Override `capabilities.lsp.servers.<server>.command` and `args` only when the default command differs.
Indexing delay:
- Some servers need time to index project metadata before returning useful diagnostics.
- Increase `diagnostics_wait_ms` only if slower edit results are acceptable.
- Run normal project checks when LSP output is incomplete or stale.
Stale diagnostics:
- Edit injection requires fresh diagnostics for the synced file version when the server supplies versions.
- If no block appears, run another edit or use normal project checks.
- Cached diagnostics are the latest known language-server state, not a final build result.
## Related docs
- [PRD-0076: Post-Edit LSP Diagnostic Injection](../prd/0076-post-edit-lsp-diagnostic-injection.md)
- [ADR-0056: Narrow Embedded LSP to Post-Edit Diagnostic Injection](../adr/0056-narrow-embedded-lsp-to-post-edit-diagnostic-injection.md)
- [PRD-0071: LSP-Backed Live Diagnostics](../prd/0071-lsp-backed-live-diagnostics.md) (superseded history)
- [ADR-0047: Embedded Blocking LSP Client Runtime](../adr/0047-embedded-blocking-lsp-client-runtime.md) (superseded history)
- [Tools and safety model](tools-and-safety.md)
- [Configuration](configuration.md)
---
[Back to feature docs](README.md) · [Back to repository README](../../README.md)