mi-lsp · git:20261021.5e90791 · 2026-10-21 · sha256 1b548c872d5f43bc

mi-lsp git:20261021.5e90791A

Immutable. This exact content never changes and is served at /api/v1/blob/1b548c872d5f43bc.

---
name: mi-lsp
description: Navigate code/docs, find files and check diagnostics after editing. Same CLI/provider for pi, Claude Code, Codex and PiG.
---

# mi-lsp

One binary, one provider manifest, one skill. No harness-specific hooks required.

**Producto y distribución:** `fgpaz/mi-lsp` mantiene la CLI, su contrato y estas
referencias de producto. La distribución común de skills para los asistentes es
`fgpaz/claude-skills` (`mi-lsp/`), no una segunda instalación desde este repo.
Los instaladores `install-agent.sh` y `install-agent.ps1` usan ese origen común
por defecto; el origen del binario sigue siendo `fgpaz/mi-lsp`. Actualizar la skill
por su instalador normal y recargar skills, sin editar cachés ni reiniciar sesiones.
Use `mi-lsp models` for the small executable surface; `mi-lsp nav --help` and
`mi-lsp provider-manifest` retain the full advanced catalog and legacy APIs.

| Need | Code Mode operation | Direct CLI |
|---|---|---|
| Goal / code or canonical docs entry | `lsp.intent` | `mi-lsp nav intent "<goal>"` |
| Read known ranges | `lsp.read` | `mi-lsp nav multi-read path:20-80` |
| Text matches | `lsp.search` | `mi-lsp nav search "<pattern>"` |
| Symbol references | `lsp.refs` | `mi-lsp nav refs "<symbol>"` |
| Errors/warnings after editing | `lsp.diagnostics` | `mi-lsp nav diagnostics path` or `--changed` |
| File names / glob | `fs.find` | `mi-lsp find-files "<pattern>"` |

Set `MI_LSP_CLIENT_NAME` to the harness and `MI_LSP_SESSION_ID` to the session
for direct CLI use. Reuse the resolved workspace; specify `--workspace` when
ambiguous. Code Mode uses `workspace` in the input object.

## Small, composable calls

These are **mi-mcp execute sandbox globals** projected from the provider by a
published H3 consumer supporting `model_alias`, not arbitrary host tool names.
Metadata alone or an older gateway (CLI129) does not make them executable:

```js
const [files, context] = await Promise.all([
  fs.find({pattern: "*.go", workspace: "project", max_items: 10}),
  lsp.intent({question: "where is request routing?", workspace: "project"}),
]);
return {files, context};
```

```js
const [read, diagnostics] = await Promise.all([
  lsp.read({ranges: ["src/router.go:20-80"], workspace: "project"}),
  lsp.diagnostics({file: "src/router.go", workspace: "project"}),
]);
return {read, diagnostics};
```

### `execute` body: the returned value is the result

- The body of a mi-mcp `execute` call is an async function body and **what it
  returns is the result**. One result → `return await lsp.intent({...});`.
  Several results → one single `return` carrying an object or array, so no
  result is dropped.
- The mi-mcp sandbox does not define `console`: a `console.log(...)` inside that
  body ends the call with `script_error` ("console is not defined") and prints
  nothing. Observed on mi-mcp 0.3.139; the durable rule comes from the sandbox
  source in fgpaz/mi-mcp (`core/sandbox/child.go`, `core/sandbox/scriptapi.go`):
  the exported value of the body is the delivered result, and `text()`/`json()`
  stay available as the published payload channel. A body that only declares
  variables and never returns delivers an empty result.
- Independent calls may run concurrently (`Promise.all`, or `Promise.allSettled`
  when one failure must not discard the others); the results still travel in that
  one structured `return`.
- **This is not the harness `codemode` tool.** That other surface has its own
  contract, where `console.log`, `text(value)` and a top-level `return` are
  valid. `console.log` is also valid in Node, for example in the `.mjs` scripts
  of this repo. Read every example against the backend that runs it; nothing
  here replaces `console` globally.
- **Compatibility is per backend and version, not a universal cut.** The `return`
  contract above is credited for the mi-mcp `execute` sandbox as observed on
  0.3.139. For another version or another backend, check the current contract
  before assuming it.
- **Legacy examples.** An `execute` body that prints with `console.log` (for
  example `console.log(await lsp.read({...}))`) is outdated for that backend
  only: label it legacy instead of deleting it, and never generalize it to
  another surface.

After each edit, invoke diagnostics for edited files (or `changed: true` for a
batch), inspect errors and repair relevant ones before requesting parent tests.
A missing backend or partial result is not a clean diagnostic run. This skill
requests the call; automatic after-edit integration is owned and verified by the
harness adapter, never inferred from a manual call.

Default navigation budget: 20 items / approximately 2000 tokens. Narrow paths,
ranges and patterns first. Raise `max_items` / `token_budget` only for a concrete
omission. Preserve warnings, authority, workspace, truncation and typed failures.
Follow exact emitted `continuation.next` / `expansions[].command` before widening;
advanced CLI operations remain executable directly. A literal requested operation
stays direct. Lexical candidates are not semantic evidence.

## Honest recovery

If an alias is absent, inspect `herramientas.describe({cli:"lsp", comando:"diagnostics"})`
inside execute, or the installed `mi-lsp provider-manifest`. Do not invent argv.
Legacy `milsp.*` remains supported. Provider restrictions such as fixed
`--no-auto-register` remain binding. Installation/init/index/restarts are separate
operations, never implicit prerequisites to a read.

External fallback requires visible `reason_code` plus bounded sanitized `detail`:
`unsupported_operation`, `unavailable_binary`, `invalid_workspace`, or
`explicit_incomplete`. Retain partial evidence; timeout/silence is not success.
Use bounded local file/search fallback only with that reason. Never publish secrets,
raw prompts or transcripts. Plugin installation / tool listing is not runtime QA.

Distribution and per-user configuration: [all harnesses](references/all-harnesses.md).
Advanced recipes remain in `references/`; load only the needed recipe.

## Canonical wiki-first rule

`WIKI-CONTRACT-v1` is the canonical contract; its typed `links` feed the unified wiki+code graph.

When the task asks for the canonical document, applicable RS/RF/TP/CT/TECH/DB, specification meaning, or requirement traceability, start from governance-backed wiki surfaces:

1. Use `nav wiki inventory` when the owning workspace is unknown. It returns a bounded per-workspace catalog; add `--with-layer-counts` when layer counts are needed.
2. Use `nav wiki-root` (alias `nav wiki root`) when the portable wiki root is needed. Pass `--role producto|ecosistema|gobierno_local` when the workspace declares `[[canon]]`; do not hardcode `.docs/wiki`.
3. Use `nav route` for the least expensive canonical anchor, then `nav wiki search`, `nav wiki pack`, or `nav wiki trace` for the bounded reading set.
4. Use `nav wiki map` only for a compact knowledge-wiki catalog; it does not return full bodies.

Only use `nav search --include-content` after the canonical anchor is known, or when the question is explicitly implementation-first. Treat broad search hits from prompts, audits, generated paths, and support artifacts as non-authoritative when a `nav wiki *` surface can answer the question. Follow exact `continuation.next` and `next_queries` before widening a query. Use `--layer RS,RF,FL,TP,CT,TECH,DB` to narrow canonical discovery. The five fan-out wiki operations (`search`, `route`, `trace`, `pack`, `inventory`) accept `--all-workspaces`; `nav wiki map` remains single-workspace.

## Intent and graph routing

Use `nav intent "<goal>"` as the first hybrid entry point for a goal-shaped request. Supported graph/change goals route to the bounded planner; documentation questions remain in `mode=docs`, and symbol-like questions remain in `mode=code`. Preserve the returned sections, candidates, omissions, authority, and exact expansions. Follow the emitted `expansions[].command` or `continuation.next`; do not invent a broader command or infer a selector.

The planner may expand to these graph operations:

- change explanation and impact: `nav explain-change`
- affected code, tests, and docs: `nav affected`
- incoming callers or outgoing callees: `nav callers` / `nav callees`
- a path between selectors: `nav path`
- one exact edge: `nav explain`
- a symbol neighborhood: `nav neighbors`
- a bounded combined packet: `nav change-pack`

`nav explain-change` is an expansion of `nav intent`, not a routing opt-out. `nav neighbors` is the exposed command for a neighborhood query; `nav related` remains the separate definition/callers/implementors/tests summary. For wiki-centered graph navigation, use `nav wiki graph --mode neighbors|path|explain|affected|change-pack|matrix`; `nav wiki trace` and `nav trace` retain their canonical document-to-code trace surfaces.

Preview is evidence, not completion. Keep `change`, `affected`, `callers`, `callees`, `tests`, `contracts`, and `wiki` sections when present, along with graph provenance, freshness, candidates, fallbacks, and omissions. A timeout, silence, or a `DONE`/`PASS` label without fresh evidence is not success.

## Unified wiki-code context

The wiki is authoritative; catalog, bindings, graph, SQLite, and caches are derived. The existing `nav.trace`, `nav.wiki.trace`, `nav.pack`, `nav.wiki.pack`, `nav.related`, `nav.neighbors`, `nav.prepare`, and `nav.change-pack` surfaces may add the read-only `wiki_code_context` envelope. This is additive and does not introduce a second public router.

Keep the evidence lanes distinct: `direct_code` for exact active bindings, `tests` for exact test bindings, `supporting_code` only when the graph is current, and bounded lexical `candidates` that never become direct claims. In code-to-wiki results, `wiki_context` is the canonical reverse projection. Report independent freshness for `docs_manifest`, `bindings`, `catalog`, `graph`, and `authority`; preserve typed omissions such as `graph_stale`. Planned bindings are nonnavigable, and retired bindings are excluded by default except for an explicit old ID/path that yields a bounded `superseded_by` redirect. Raw and audit artifacts are not authority.

Use [references/compound-commands.md](references/compound-commands.md) for schemas and fields, and [references/recipes.md](references/recipes.md) for bounded graph, trace, and change-pack recipes. Keep the workspace explicit in every direct CLI example.

## Hot path

- Resolve the workspace and executable: `mi-lsp workspace which --format toon`
- Resolve the canonical wiki root: `mi-lsp nav wiki-root --workspace <alias> --format toon`
- Search canonical documentation: `mi-lsp nav wiki search "<topic>" --workspace <alias> --layer RS,RF,FL,TP,CT,TECH,DB --format toon`
- Trace a requirement or document: `mi-lsp nav wiki trace <ID> --workspace <alias> --format toon` or `mi-lsp nav trace <ID> --workspace <alias> --format toon`
- Explain change impact: `mi-lsp nav intent "explain the impact of this change" --workspace <alias> --format toon`
- Inspect affected paths: `mi-lsp nav affected <path> --include-tests --include-docs --workspace <alias> --format toon`
- Inspect callers, callees, paths, and neighbors: `mi-lsp nav callers <symbol> --workspace <alias> --format toon`, `mi-lsp nav callees <symbol> --workspace <alias> --format toon`, `mi-lsp nav path <from> <to> --workspace <alias> --format toon`, and `mi-lsp nav neighbors <symbol> --workspace <alias> --format toon`
- Build a bounded change packet: `mi-lsp nav change-pack <ref> --workspace <alias> --format toon`
- Query the unified wiki graph: `mi-lsp nav wiki graph --mode neighbors --workspace <alias> --format toon`

Prefer these bounded surfaces over repeated raw searches or full-file reads. If a result is truncated, use its exact continuation or narrowing hint.