你是否见过 GitHub Copilot CLI 把 JAR 文件解压到临时目录,用 grep 搜索 .class 文件,再从原始字节码中拼凑出 API 签名?这个智能体确实很机灵,但没有语言服务器,它最多也就只能做到这一步了。
语言服务器协议(LSP)是支撑 VS Code 等编辑器中“跳转到定义”、“查找引用”和类型解析的标准协议。它在终端中同样好用。LSP Setup 技能可为 Copilot CLI 自动完成 LSP 服务器的安装与配置,让智能体获得关于你代码的精确、结构化的回答,而不是依赖文本搜索的启发式方法。
在这篇文章中,你将了解这个技能在底层是如何工作的,查看它生成的配置格式,并为它当前支持的 14 种语言中的任意一种完成设置。
问题所在:基于启发式的代码理解
在没有 LSP 服务器的情况下,GitHub Copilot CLI 中的智能体只能通过文本搜索和二进制提取来逆向推导 API 信息。对于一个 Java 项目,这可能是这样:
# Find the dependency JAR
find ~/.m2/repository -name "*httpclient*.jar"
# Extract it to a temp directory
mkdir /tmp/httpclient && cd /tmp/httpclient
jar xf ~/.m2/repository/org/apache/httpcomponents/httpclient/4.5.14/httpclient-4.5.14.jar
# Search extracted class files for a method
grep -r "execute" --include="*.class" . 对于 Python,智能体可能会 cat 位于 site-packages 中的文件。对于 TypeScript,它会遍历 node_modules。这些基于文本的方法在简单场景下可行,但它们是在对原始文本做模式匹配,而非真正的语义分析,因此会遗漏泛型、重载和传递类型,而且完全看不到编译后的字节码。这恰恰是语言服务器所能弥补的空白。
LSP 服务器从结构上解决了这个问题。当智能体发送针对某个符号的 textDocument/definition 请求时,语言服务器会返回精确的源码位置、完全解析后的类型以及签名。
什么是智能体技能?
智能体技能是一套可复用的指令集,用于扩展 AI 编程智能体能做的事。技能以带有 YAML frontmatter 的 Markdown 文件定义,并遵循标准结构:触发描述、分步骤的工作流程、参考数据和行为约束。
LSP Setup 技能利用这一结构来引导智能体完成多步骤的安装流程:检测操作系统、选择合适的包管理器、编写有效的配置,并验证结果。
LSP Setup 技能的工作原理
被触发后,该技能会执行一个七步工作流程:
1. 语言选择
智能体使用带有选项集的 ask_user 来确定用户需要为哪种语言提供 LSP 支持。这一步决定后续所有步骤。
2. 操作系统检测
智能体会运行 uname -s(或在 Windows 上检查 $env:OS / %OS%)来确定目标平台。安装命令因操作系统而异。例如,macOS 上使用 brew install jdtls,而 Linux 上则从 eclipse.org 下载。
3. LSP 服务器查询
该技能包含一个参考文件(references/lsp-servers.md),其中收录了 14 种语言的精选数据:各操作系统的安装命令、二进制文件名以及可直接使用的配置片段。智能体会读取该文件并选择匹配的条目。
4. 配置范围
智能体会询问配置应该放在哪一级:
- 用户级:
~/.copilot/lsp-config.json——适用于所有仓库 - 仓库级:位于仓库根目录的
lsp.json或.github/lsp.json——仅作用于单个项目
当两者同时存在时,仓库级配置优先。
5. 安装
智能体会运行相应的安装命令。例如:
# TypeScript on any OS
npm install -g typescript typescript-language-server
# Java on macOS
brew install jdtls
# Rust on any OS
rustup component add rust-analyzer 6. 配置
智能体会将一个条目写入或合并到所选的配置文件中。该格式使用一个 lspServers 对象,其中每个键都是一个服务器标识符:
{
"lspServers": {
"java": {
"command": "jdtls",
"args": [],
"fileExtensions": {
".java": "java"
}
}
}
} 该技能强制执行的关键规则:
command必须在$PATH(PATH)中,或为绝对路径args通常包含标准 I/O 传输方式所需的"--stdio"(某些服务器如jdtls会在内部处理此操作)fileExtensions将每个扩展名(含前导点)映射到一个 语言标识符- 配置文件中已有的条目会被保留——智能体只做合并,绝不覆盖
7. 验证
智能体会运行 which <binary>(Windows 上为 where.exe)以确认服务器可访问,然后验证配置文件是否为格式良好的 JSON。
支持的语言
该技能自带一套 预定义的语言服务器,覆盖多种编程语言。如果编程智能体遇到尚未映射的语言,它会搜索合适的服务器,并引导你完成手动配置。
设置完成后会有什么变化
配置好 LSP 服务器后,CLI 智能体可以:
- 解析依赖项中的类型 —— 不再需要在 JAR 文件中 grep,也不必
node_modules - 跳转到第三方库中的定义,即使源代码没有检入仓库
- 查找某个符号在整个项目中的所有引用
- 查看任意函数、类或类型的悬停文档
这意味着智能体花在工具调用上的时间更少,并且首次生成的代码更准确。对你来说,这意味着更少的时间浪费在等待智能体反编译 JAR 文件或翻查 node_modules 来回答一个你的 IDE 早已知道答案的问题上,也减少了因误读函数签名而走上的弯路。智能体在理解你的代码时,拥有与你编辑器中 go-to-definition 相同的结构化理解能力,因此你可以把更大、更棘手的任务交给它,并信任其结果。
- 下载技能:访问 Awesome Copilot LSP Setup 技能页面,点击 Download 按钮获取 ZIP 文件。
- 解压 ZIP 到
~/.copilot/skills/,运行以下命令:
unzip lsp-setup.zip -d ~/.copilot/skills/ - [重启 GitHub Copilot CLI:如果 Copilot CLI 已经在运行,请先输入
/exit。然后重新启动copilot,让它加载新技能。 - [让智能体设置语言服务器:例如,[“为 Java 设置 LSP” 或 “为 Python 启用代码智能”。
- [验证:在技能安装并配置好 LSP 服务器后,再重启一次 Copilot CLI(
/exit,然后重新启动),运行/lsp检查服务器状态,并尝试对某个依赖中的符号使用跳转到定义功能。
该技能是 Awesome Copilot 项目的一部分。它是开源的,欢迎贡献和反馈!
Ever watched GitHub Copilot CLI extract a JAR file to a temporary directory, grep through .class files, and piece together an API signature from raw bytecode? The agent is resourceful, but without a language server, that’s the best it can do.
The Language Server Protocol (LSP) is the standard that powers go to definition, find references, and type resolution in editors like VS Code. It works just as well in the terminal. The LSP Setup skill automates the installation and configuration of LSP servers for Copilot CLI, so the agent gets precise, structured answers about your code instead of relying on text search heuristics.
In this post, you’ll learn how the skill works under the hood, see the configuration format it generates, and get set up for any of the 14 languages it supports today.
The problem: heuristic code understanding
Without an LSP server, the agent in GitHub Copilot CLI reverse-engineers API information through text search and binary extraction. For a Java project, that might look like:
# Find the dependency JAR
find ~/.m2/repository -name "*httpclient*.jar"
# Extract it to a temp directory
mkdir /tmp/httpclient && cd /tmp/httpclient
jar xf ~/.m2/repository/org/apache/httpcomponents/httpclient/4.5.14/httpclient-4.5.14.jar
# Search extracted class files for a method
grep -r "execute" --include="*.class" . For Python, the agent might cat files inside site-packages. For TypeScript, it walks node_modules. These text-based approaches work for simple cases, but they’re doing pattern-matching over raw text rather than true semantic analysis, so they miss generics, overloads, and transitive types, and can’t see compiled bytecode at all. That’s exactly the gap a language server close.
An LSP server solves this structurally. When the agent sends a textDocument/definition request for a symbol, the language server returns the exact source location, fully resolved type, and signature.
What is an agent skill?
Agent skill is a reusable instruction set that extends what an AI coding agent can do. Skills are defined in Markdown files with YAML frontmatter and follow a standard structure: trigger descriptions, step-by-step workflows, reference data, and behavioral constraints.
The LSP Setup skill uses this structure to guide the agent through a multi-step installation process, detecting the operating system, choosing the right package manager, writing valid configuration, and verifying the result.
How the LSP Setup skill works
When triggered, the skill executes a seven-step workflow:
1. Language selection
The agent uses ask_user with a set of choices to determine which language the user needs LSP support for. This drives all subsequent steps.
2. Operating system detection
The agent runs uname -s (or checks $env:OS / %OS% on Windows) to determine the target platform. Install commands vary by operating system. For example, brew install jdtls on macOS versus downloading from eclipse.org on Linux.
3. LSP server lookup
The skill includes a reference file (references/lsp-servers.md) with curated data for 14 languages: install commands per operating system, binary names, and ready-to-use config snippets. The agent reads this file and selects the matching entry.
4. Configuration scope
The agent asks whether the config should be:
- User-level:
~/.copilot/lsp-config.json—applies to all repositories - Repository-level:
lsp.jsonat the repository root or.github/lsp.json—scoped to a single project
Repository-level configuration takes precedence when both exist.
5. Installation
The agent runs the appropriate install command. For example:
# TypeScript on any OS
npm install -g typescript typescript-language-server
# Java on macOS
brew install jdtls
# Rust on any OS
rustup component add rust-analyzer 6. Configuration
The agent writes or merges an entry into the chosen config file. The format uses a lspServers object where each key is a server identifier:
{
"lspServers": {
"java": {
"command": "jdtls",
"args": [],
"fileExtensions": {
".java": "java"
}
}
}
} Key rules the skill enforces:
commandmust be on$PATHor an absolute pathargstypically includes"--stdio"for standard I/O transport (some servers likejdtlshandle this internally)fileExtensionsmaps each extension (with leading dot) to a language identifier- Existing entries in the config file are preserved — the agent merges, never overwrites
7. Verification
The agent runs which <binary> (or where.exe on Windows) to confirm the server is accessible, then validates the config file is well-formed JSON.
Supported languages
The skill comes with a set of predefined language servers for several programming languages. If the coding agent faces one that it is not mapped out already, it will search for an appropriate server and walk you through manual configuration.
What changes after setup
Once an LSP server is configured, the CLI agent can:
- Resolve types across dependencies — no more grepping through JAR files or
node_modules - Jump to definitions in third-party libraries, even when source isn’t checked into the repository
- Find all references to a symbol across the project
- Read hover documentation for any function, class, or type
This means the agent spends less time on tool calls and produces more accurate code on the first pass. For you, that’s less time waiting while the agent decompiles a JAR file or greps through node_modules to answer a question your IDE already knows, and fewer wrong turns built on a misread signature. The agent reasons about your code with the same structured understanding you get from go-to-definition in your editor, so you can hand it bigger, gnarlier tasks and trust the result.
- Download the skill: visit the Awesome Copilot LSP Setup skill page and click the Download button to get a ZIP file.
- Extract the ZIP to
~/.copilot/skills/by running:
unzip lsp-setup.zip -d ~/.copilot/skills/ - Restart GitHub Copilot CLI: if Copilot CLI is already running, type
/exitfirst. Then relaunchcopilotso it picks up the new skill. - Ask the agent to set up a language server: for example, “set up LSP for Java” or “enable code intelligence for Python”.
- Verify: after the skill installs and configures the LSP server, restart Copilot CLI one more time (
/exit, then relaunch), run/lspto check the server status, and try go-to-definition on a symbol from one of your dependencies.
The skill is part of the Awesome Copilot project. It’s open source, so contributions and feedback are welcome!