Rename through the language server
Regex rename misses re-exports, shadowed locals, and string-keyed access. lsp action=rename asks the server for a WorkspaceEdit and applies it atomically across every touched file. If the server refuses (the symbol is unrenameable, or one of the edits would clash), nothing is written. The same applies to rename_file, which rewrites imports along with the move.
For other structural rewrites where no symbol is involved — codemods over syntax patterns, large mechanical refactors — see structural edits.
Actions
| Action | What it returns | When to reach for it |
|---|---|---|
| Navigation | ||
definition | Location(s) defining the symbol under the cursor. | “Where does this come from?” before reading a caller. |
type_definition | Location(s) of the symbol’s type declaration. | The value is an instance; you want the class/interface. |
implementation | Concrete implementations of an interface or abstract method. | Tracing a trait/interface to its impls. |
references | Every callsite of the symbol, project-wide. | Sizing a change before you make it. |
hover | Type signature and doc comment for the symbol. | Inferred types, generic instantiations, doc strings. |
symbols | Document outline (with file) or workspace search (with file="*" + query). | Find a symbol by name without knowing the file. |
| Diagnostics & fixes | ||
diagnostics | Errors, warnings, hints for the file (or workspace with file="*"). | Check a file after an edit; sanity-check the workspace. |
code_actions | Server-offered fixes/refactors for a range; filter with query (e.g. quickfix). | “Add missing import”, “Implement trait”, organize imports. |
| Refactor | ||
rename | Atomic WorkspaceEdit renaming the symbol everywhere it’s referenced. | Any cross-file symbol rename. |
rename_file | Move/rename a file and rewrite imports to match. | Reshuffling module layout without breaking callers. |
| Server management | ||
status | Which servers are running, idle, or missing on PATH. | Diagnostics come back empty — is the server even up? |
capabilities | What the active server actually supports. | Before requesting features (e.g. call hierarchy) that may be unimplemented. |
reload | Restart the server for a file, or file="*" for every server. | After installing a missing toolchain, or to clear a stale state. |
request | Raw LSP request: query names the method, payload carries JSON params. | An LSP feature the wrapper doesn’t expose directly. |
Pointing at a symbol
Most actions take file + line and need a column to resolve the symbol. Pass symbol instead of counting characters: the tool finds the symbol on that line and uses its offset. When the same name appears more than once on a line, append #N for the N-th occurrence (1-indexed). For definition, references, and rename, symbol is required alongside line — guessing a column is how renames go wrong.
lsp action=references file=src/server/auth.ts line=42 symbol="issueToken"
lsp action=definition file=src/parse.ts line=88 symbol="parse#2"Servers
omp auto-detects servers from a defaults table (typescript-language-server, rust-analyzer, pyright, gopls, clangd, …) and starts them on demand. Override servers in an lsp.json (or .lsp.json/lsp.yaml) file — project-wide at <project>/lsp.json or <project>/.omp/lsp.json, user-wide at ~/.omp/agent/lsp.json. The whole tool is gated by lsp.enabled; disable for a single session with --no-lsp. See Settings for the config knobs.
Worked example: rename across the codebase
The function issueToken lives in src/auth/jwt.ts and is called from a handful of handlers and tests. To rename it to mintToken without missing a callsite or breaking a re-export:
# 1. Confirm what changes (server-computed, no edits yet).
lsp action=references file=src/auth/jwt.ts line=14 symbol="issueToken"
# 2. Apply the rename atomically.
lsp action=rename file=src/auth/jwt.ts line=14 symbol="issueToken" new_name="mintToken"
# 3. Re-check the workspace for fallout.
lsp action=diagnostics file="*"Step 2 either writes every touched file at once or writes nothing. Step 3 surfaces anything the rename couldn’t fix — dynamic lookups by string, doc comments referring to the old name, a downstream package that imported the symbol by another path.
Common pitfalls
Diagnostics empty but the build fails
Run lsp action=status. The server for that language may be missing on PATH. Install it (
rust-analyzer, gopls, …) and then
lsp action=reload file="*".
Rename refused
The server flagged the symbol as unrenameable (often a built-in, external type, or a string-only key).
Fix the affected sites with structural edits instead.
Wrong occurrence picked up
When the name repeats on the line, use symbol="name#2" to disambiguate.\n