关于
This skill provides comprehensive code exploration by building a navigable dependency map for any symbol or file. It synthesizes relationships across implementations, call hierarchies, references, and source code to help developers understand unfamiliar codebases. Use it when you need a complete structural overview beyond simple symbol lookup.
快速安装
Claude Code
推荐npx skills add blackwell-systems/agent-lsp -a claude-code/plugin add https://github.com/blackwell-systems/agent-lspgit clone https://github.com/blackwell-systems/agent-lsp.git ~/.claude/skills/lsp-understand在 Claude Code 中复制并粘贴此命令以安装该技能
技能文档
Requires the agent-lsp MCP server.
lsp-understand
Deep-dive exploration of unfamiliar code — given a symbol or file, synthesizes hover info, implementations, call hierarchy (bounded to 2 levels), all references, and source into a structured Code Map.
Read-only — does not modify any files.
Differentiation from lsp-explore
/lsp-explore is a single-symbol pass: given one symbol name, it runs hover +
implementations + call hierarchy + references and produces a per-symbol report.
Use lsp-explore for quick "what is this one thing" questions.
/lsp-understand is broader in three ways:
- Accepts a file path as input — explores all exported symbols in that file as a group (Mode B), rather than requiring a single symbol name.
- Synthesizes cross-symbol relationships — produces a dependency map showing how entry points call each other, share callers, or implement the same interface, rather than isolated per-symbol reports.
- Enforces a 2-level call hierarchy depth limit — prevents infinite recursion in deeply connected code.
Use lsp-understand for "how does this module work as a whole."
Input — Two Modes
Mode A (symbol): User provides a symbol name in dot notation
(e.g., "codec.Encode", "Handler.ServeHTTP").
Mode B (file): User provides an absolute file path. All exported symbols in the file become the entry points.
Prerequisites
Call mcp__lsp__get_server_capabilities before Step 2 to determine which
capabilities are available. Skip steps that require missing capabilities:
go_to_implementation: skip Step 2b ifimplementationProvider: falsefind_callers: skip Steps 2c and 2d ifcallHierarchyProvider: false; note in the Code Map output that call hierarchy was unavailable
Step 1 — Entry Point Resolution
Mode A: Single Symbol
Call mcp__lsp__go_to_symbol to locate the symbol definition:
mcp__lsp__go_to_symbol({
"symbol_path": "<dot-notation name>", // e.g. "codec.Encode"
"workspace_root": "<root>" // optional
})
→ returns: file_path, line, column (1-indexed)
Record file_path, line, and column. If go_to_symbol returns nothing,
report:
Symbol not found:
<name>Check the dot-notation path (e.g. "Package.Symbol") and ensure the workspace root covers the file.
Stop immediately — do not proceed to Step 2.
The single symbol becomes the sole entry point.
Mode B: File Path
Call mcp__lsp__open_document then mcp__lsp__list_symbols:
mcp__lsp__open_document({ "file_path": "<absolute path>" })
mcp__lsp__list_symbols({ "file_path": "<absolute path>" })
→ returns: list of symbols with kind, line, column
Filter to exported symbols:
- Go: uppercase first letter
- TypeScript/JavaScript:
exportkeyword - Rust:
pubvisibility
Cap at 10 exported symbols maximum. If more than 10 are found, prioritize top-level functions and types; skip constants and variables.
Each filtered symbol becomes an entry point with its file_path, line, and
column.
Step 2 — Per-Symbol Analysis
For each entry point, run the following sub-steps. Where possible, parallelize calls within each step.
2a — Type Info and Docs
Call mcp__lsp__inspect_symbol using position_pattern with the @@
marker (see references/patterns.md):
mcp__lsp__inspect_symbol({
"file_path": "<file>",
"position_pattern": "<symbol@@name>",
"line_scope_start": <line - 5>,
"line_scope_end": <line + 5>
})
→ returns: hover text with type signature and doc comment
Store result as hover_text. If the call fails or returns nothing, set
hover_text to an empty string. Do not stop.
2b — Implementations (capability-gated)
If implementationProvider is available in server capabilities:
mcp__lsp__go_to_implementation({
"file_path": "<file>",
"line": <line>,
"column": <column>
})
→ returns: list of concrete implementation locations
Skip if capability is absent. Record "not supported by this server" rather
than stopping.
2c — Incoming Call Hierarchy (bounded to 2 levels)
If callHierarchyProvider is available:
Level 1 — Direct callers:
mcp__lsp__find_callers({
"file_path": "<file>",
"line": <line>,
"column": <column>,
"direction": "incoming"
})
→ returns: list of direct caller functions with file and line
Level 2 — Callers of callers:
For each Level 1 caller, call mcp__lsp__find_callers once more:
mcp__lsp__find_callers({
"file_path": "<caller file>",
"line": <caller line>,
"column": <caller column>,
"direction": "incoming"
})
→ returns: Level 2 callers
STOP at Level 2 — do not recurse further under any circumstances.
If Level 2 callers > 10: summarize by count and file, do not list individually.
2d — Outgoing Calls (Level 1 only)
If callHierarchyProvider is available:
mcp__lsp__find_callers({
"file_path": "<file>",
"line": <line>,
"column": <column>,
"direction": "outgoing"
})
→ returns: list of functions this symbol calls
Level 1 only — no recursion.
2e — All References
mcp__lsp__find_references({
"file_path": "<file>",
"line": <line>,
"column": <column>,
"include_declaration": false
})
→ returns: every usage site across the workspace
Group by file and count distinct files.
2f — Source
mcp__lsp__get_symbol_source({
"file_path": "<file>",
"line": <line>,
"column": <column>
})
→ returns: implementation body
Step 3 — Synthesize Relationships
After analyzing all entry points, identify cross-symbol relationships:
- Internal calls: Which entry points call each other? (from outgoing calls in Step 2d)
- Shared callers: Which entry points are called by the same Level 1 callers?
- Shared interface: Which entry points implement the same interface? (from Step 2b)
This synthesis step is what distinguishes /lsp-understand from running
multiple /lsp-explore calls. The output is a dependency map, not isolated
per-symbol reports.
Step 4 — Output: Code Map
Produce a structured Code Map with these sections:
## Code Map: <target>
### Summary
<2-3 sentence description of what this code does, synthesized from
hover docs and source reading>
### Symbols (<N> analyzed)
#### <SymbolName>
- **Type:** <type signature from hover>
- **Source:** <file:line>
- **Incoming callers (L1):** <list; count only if > 5>
- **Incoming callers (L2):** <summarized; e.g., "called by 3 HTTP handlers">
- **Outgoing calls:** <what this symbol calls>
- **Implements:** <interface name, if applicable>
- **References:** N sites across M files
### Dependency Relationships
<symbols that call each other, as a simple text diagram or list>
e.g.:
HandlerA → Parse → Validate
HandlerB → Parse
### Entry Points to This Code
<top-level callers that are NOT in this file — where does outside code
call in?>
### Depth-limit Note
Call hierarchy stopped at 2 levels. <N> additional callers exist beyond
Level 2 — use /lsp-explore on specific symbols to drill deeper.
Depth Control Rules
These limits are hard constraints — never exceed them:
- Incoming call hierarchy recursion stops at Level 2
- Outgoing calls: Level 1 only, no recursion
- If Level 2 callers > 10: summarize by count and file, do not list individually
- Do NOT follow call chains beyond these limits under any circumstances
Example
Goal: understand how the file pkg/codec/encoder.go works as a whole
Step 1 — Mode B (file path)
open_document: pkg/codec/encoder.go
list_symbols: pkg/codec/encoder.go
→ exported symbols: Encoder (type), Encode (func), Reset (func), NewEncoder (func)
→ 4 exported symbols (under 10 cap)
get_server_capabilities
→ go_to_implementation: supported
→ find_callers: supported
Step 2 — Per-symbol analysis (run in parallel across symbols)
Symbol: NewEncoder (pkg/codec/encoder.go:12)
inspect_symbol → "func NewEncoder(w io.Writer) *Encoder"
go_to_implementation → 0 (concrete function)
find_callers incoming L1 → 5 callers
find_callers incoming L2 → 3 callers of those callers
find_callers outgoing → calls: bufio.NewWriter
find_references → 5 sites in 3 files
get_symbol_source → implementation body
Symbol: Encode (pkg/codec/encoder.go:28)
inspect_symbol → "func (e *Encoder) Encode(v any) error"
go_to_implementation → implements codec.Encoder interface
find_callers incoming L1 → 8 callers (listed)
find_callers incoming L2 → > 10: "12 additional callers across 5 files"
find_callers outgoing → calls: NewEncoder, e.w.Flush
find_references → 8 sites in 5 files
get_symbol_source → implementation body
(similar for Encoder type and Reset func...)
Step 3 — Synthesize relationships
- Encode calls NewEncoder (internal dependency)
- NewEncoder and Encode share callers in cmd/main.go
- Encode implements codec.Encoder interface
## Code Map: pkg/codec/encoder.go
### Summary
This file implements a streaming JSON encoder backed by a buffered writer.
NewEncoder constructs an Encoder wrapping any io.Writer; Encode serializes
values and flushes. Reset allows reuse without allocation.
### Symbols (4 analyzed)
#### NewEncoder
- **Type:** func NewEncoder(w io.Writer) *Encoder
- **Source:** pkg/codec/encoder.go:12
- **Incoming callers (L1):** cmd.main, app.Start, loader.Load, test.Setup, bench.Run
- **Incoming callers (L2):** 3 callers across 2 files
- **Outgoing calls:** bufio.NewWriter
- **Implements:** n/a
- **References:** 5 sites across 3 files
#### Encode
- **Type:** func (e *Encoder) Encode(v any) error
- **Source:** pkg/codec/encoder.go:28
- **Incoming callers (L1):** 8 callers (cmd/main.go, internal/app.go, ...)
- **Incoming callers (L2):** 12 additional callers across 5 files (depth limit reached)
- **Outgoing calls:** NewEncoder, e.w.Flush
- **Implements:** codec.Encoder
- **References:** 8 sites across 5 files
...
### Dependency Relationships
cmd.main → NewEncoder → bufio.NewWriter
cmd.main → Encode → NewEncoder
Encode → Reset
### Entry Points to This Code
- cmd.main (cmd/main.go:14)
- app.Start (internal/app.go:31)
- loader.Load (internal/loader.go:55)
### Depth-limit Note
Call hierarchy stopped at 2 levels. 12 additional callers exist beyond
Level 2 for Encode — use /lsp-explore on specific symbols to drill deeper.
GitHub 仓库
常见问题
什么是 lsp-understand Skill?
lsp-understand 是一个 Claude Skill,作者为 blackwell-systems。Skill 将 Claude 按需加载的说明和资源打包,让 Claude 无需额外提示即可执行与 lsp-understand 相关的任务。
如何安装 lsp-understand?
使用本页的安装命令:将 lsp-understand 作为插件添加到 Claude Code,或将其仓库克隆到 skills 目录,然后重启 Claude 以加载该 Skill。
lsp-understand 属于哪个分类?
lsp-understand 属于元分类。
lsp-understand 可以免费使用吗?
可以。lsp-understand 已收录在 AIMCP,可免费安装。
相关推荐技能
Content Collections 是一个 TypeScript 优先的构建工具,可将本地 Markdown/MDX 文件转换为类型安全的数据集合。它专为构建博客、文档站和内容密集型 Vite+React 应用而设计,提供基于 Zod 的自动模式验证。该工具涵盖从 Vite 插件配置、MDX 编译到生产环境部署的完整工作流。
这个Claude Skill为开发者提供完整的Polymarket预测市场开发支持,涵盖API调用、交易执行和市场数据分析。关键特性包括实时WebSocket数据流,可监控实时交易、订单和市场动态。开发者可用它构建预测市场应用、实施交易策略并集成实时市场预测功能。
该Skill帮助开发者创建OpenCode插件,用于接入命令、文件、LSP等25+种事件。它提供了插件结构、事件API规范和JavaScript/TypeScript实现模式,适合需要拦截操作、扩展功能或自定义事件处理的场景。开发者可通过它快速构建响应式模块来增强OpenCode AI助手的能力。
SGLang是一个专为LLM设计的高性能推理框架,特别适用于需要结构化输出的场景。它通过RadixAttention前缀缓存技术,在处理JSON、正则表达式、工具调用等具有重复前缀的复杂工作流时,能实现极速生成。如果你正在构建智能体或多轮对话系统,并追求远超vLLM的推理性能,SGLang是理想选择。
