<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>LSP on 奇诺分享 | 重在分享</title>
        <link>https://blog.ccino.org/tags/lsp/</link>
        <description>Recent content in LSP on 奇诺分享 | 重在分享</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-cn</language>
        <lastBuildDate>Fri, 26 Jun 2026 08:00:00 +0800</lastBuildDate><atom:link href="https://blog.ccino.org/tags/lsp/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>终端里的 AI Agent，终于开始长出 IDE 的眼睛</title>
        <link>https://blog.ccino.org/p/copilot-cli-lsp-code-intelligence-2026/</link>
        <pubDate>Fri, 26 Jun 2026 08:00:00 +0800</pubDate>
        
        <guid>https://blog.ccino.org/p/copilot-cli-lsp-code-intelligence-2026/</guid>
        <description>&lt;img src="https://blog.ccino.org/p/copilot-cli-lsp-code-intelligence-2026/imgs/cover.png" alt="Featured image of post 终端里的 AI Agent，终于开始长出 IDE 的眼睛" /&gt;&lt;p&gt;GitHub 最近给 Copilot CLI 加了一个看起来很小的能力：通过 &lt;strong&gt;LSP（Language Server Protocol，语言服务器协议）&lt;/strong&gt; 接入 language servers（语言服务器），让命令行里的 AI 编程智能体也能拿到定义跳转、引用查找、类型信息和 hover 文档。&lt;/p&gt;
&lt;p&gt;这件事如果只按功能更新看，很容易被低估。毕竟 LSP 不是新东西，VS Code、JetBrains、Vim、Neovim 早就靠它提供代码智能。很多开发者每天都在用 go to definition、find references、rename symbol，却不会特意想起背后的协议。&lt;/p&gt;
&lt;p&gt;但放到 AI 编程工具里，这个更新就不只是“Copilot CLI 多了一个插件”。它更像一个提醒：&lt;strong&gt;AI Agent 不能永远靠读文本理解代码。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;过去一年，大家讨论 Claude Code、Codex、Cursor、Copilot，常常把重点放在模型能力、上下文长度、价格和工具调用上。哪个模型更会改 bug？哪个 agentic coding 工具更能自主跑完任务？哪个订阅更划算？这些问题当然重要，但它们都默认了一个前提：Agent 已经“看懂”了代码。&lt;/p&gt;
&lt;p&gt;实际情况没那么乐观。很多时候，Agent 只是把代码库当成一堆文本文件在搜索。&lt;/p&gt;
&lt;h2 id=&#34;没有-lsp-的-agent其实很像一个没有-ide-的新人&#34;&gt;没有 LSP 的 Agent，其实很像一个没有 IDE 的新人
&lt;/h2&gt;&lt;p&gt;GitHub 官方博客里举了一个很直观的例子：如果没有 language server，Copilot CLI 为了理解一个 Java 依赖里的 API，可能会去 Maven 本地仓库找 JAR 文件，解压到临时目录，再用 grep 在 &lt;code&gt;.class&lt;/code&gt; 文件附近搜索方法名。&lt;/p&gt;
&lt;p&gt;Python 项目里，它可能去 &lt;code&gt;site-packages&lt;/code&gt; 里翻源码；TypeScript 项目里，它可能一路钻进 &lt;code&gt;node_modules&lt;/code&gt;；遇到大型 monorepo，它就开始用文件搜索、关键词匹配、上下文拼接来推断一个函数到底从哪里来、签名是什么、有没有重载。&lt;/p&gt;
&lt;p&gt;这不是 Agent 偷懒，而是它能用的感官太少。&lt;/p&gt;
&lt;p&gt;一个有经验的开发者打开 IDE，不会只靠全文搜索写代码。你看到一个函数，会跳到定义；看到一个类型，会查它的泛型参数；不确定调用关系，会找引用；要改名字，会让 IDE 做符号级重命名，而不是手动搜索替换。&lt;/p&gt;
&lt;p&gt;这些动作看起来普通，本质上是语言服务器、编译器、索引器在帮你回答问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这个符号真正定义在哪里？&lt;/li&gt;
&lt;li&gt;这个调用解析到哪个重载？&lt;/li&gt;
&lt;li&gt;这个类型来自源码、依赖包，还是生成代码？&lt;/li&gt;
&lt;li&gt;这个字段改名会影响哪些文件？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;没有这些能力，AI Agent 再聪明，也很容易变成“在一堆文本里猜答案”。上下文窗口再长，也只是让它一次能塞进更多文本，不等于它理解了代码的语义结构。&lt;/p&gt;
&lt;h2 id=&#34;lsp-给-agent-的不是信息量而是信息的坐标系&#34;&gt;LSP 给 Agent 的不是信息量，而是信息的坐标系
&lt;/h2&gt;&lt;p&gt;&lt;img src=&#34;https://blog.ccino.org/p/copilot-cli-lsp-code-intelligence-2026/imgs/semantic-map.png&#34;
	width=&#34;1672&#34;
	height=&#34;941&#34;
	srcset=&#34;https://blog.ccino.org/p/copilot-cli-lsp-code-intelligence-2026/imgs/semantic-map_hu_8f92e735b498d1b5.png 480w, https://blog.ccino.org/p/copilot-cli-lsp-code-intelligence-2026/imgs/semantic-map_hu_b67c01fb8e5a9347.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;代码语义坐标系：从 grep 到 LSP&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;177&#34;
		data-flex-basis=&#34;426px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;LSP 最容易被误解成“给 Agent 多一点上下文”。这说法不算错，但不够准确。&lt;/p&gt;
&lt;p&gt;真正关键的是，LSP 给的是一套&lt;strong&gt;代码语义坐标系&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;全文搜索能告诉你某个字符串在哪里出现过，language server 能告诉你某个符号在当前语言规则下指向哪里。两者差别很大。一个项目里可能有很多同名函数、同名变量、同名字段，grep 只能把它们全找出来；LSP 可以基于作用域、导入、泛型、重载和编译配置判断当前这一处到底引用的是谁。&lt;/p&gt;
&lt;p&gt;这对 AI Agent 很关键。&lt;/p&gt;
&lt;p&gt;因为 Agent 做复杂任务时，很多错误并不是“不知道某段代码存在”，而是“误读了这段代码之间的关系”。比如它看到一个 &lt;code&gt;execute&lt;/code&gt; 方法，以为是当前类里的实现，实际调用的是依赖包里的重载；它看到一个 TypeScript 类型，以为字段可选，实际经过泛型约束后是必填；它搜索到一个旧函数，以为还能用，实际项目已经迁移到新接口。&lt;/p&gt;
&lt;p&gt;人类开发者在 IDE 里会下意识用跳转和类型提示纠正这些误读。Agent 如果没有同等能力，就只能靠模型概率和文本线索补洞。&lt;/p&gt;
&lt;p&gt;这也是为什么 Copilot CLI 的 LSP Setup skill 值得关注。按 GitHub 的介绍，它会引导用户选择语言、检测操作系统、查找对应 language server、安装依赖、写入 &lt;code&gt;lspServers&lt;/code&gt; 配置，并验证二进制是否可用。它支持的不是一个特定语言，而是一套让 CLI Agent 接入语言服务器的流程。&lt;/p&gt;
&lt;p&gt;配置大概长这样：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;lspServers&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;java&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;jdtls&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;fileExtensions&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;#34;.java&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;java&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这段配置本身不神秘。真正有意思的是，它把以前属于 IDE 的能力，搬进了命令行 Agent 的工作环境。&lt;/p&gt;
&lt;h2 id=&#34;ai-编程工具正在补传统-ide-的课&#34;&gt;AI 编程工具正在补传统 IDE 的课
&lt;/h2&gt;&lt;p&gt;过去一两年，AI 编程工具给人的感觉是“从聊天框杀进开发流程”。Cursor 把聊天和编辑器结合，Claude Code 把终端变成主战场，Codex 和 Copilot CLI 也都在探索命令行 Agent 的形态。&lt;/p&gt;
&lt;p&gt;这条路一开始很自然：先让模型能读文件、改文件、跑命令、提交 diff。只要能把一个任务闭环跑完，用户就会觉得惊艳。&lt;/p&gt;
&lt;p&gt;但用久了以后，问题也会冒出来。Agent 能改文件，不代表它真的理解项目；能跑测试，不代表它知道为什么失败；能搜索代码，不代表它知道符号关系；能读 20 万 token，不代表它知道哪 200 行才关键。&lt;/p&gt;
&lt;p&gt;所以 AI 编程工具会慢慢补传统 IDE 的课。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.ccino.org/p/copilot-cli-lsp-code-intelligence-2026/imgs/engineering-senses.png&#34;
	width=&#34;1672&#34;
	height=&#34;941&#34;
	srcset=&#34;https://blog.ccino.org/p/copilot-cli-lsp-code-intelligence-2026/imgs/engineering-senses_hu_3c346c3642b0f223.png 480w, https://blog.ccino.org/p/copilot-cli-lsp-code-intelligence-2026/imgs/engineering-senses_hu_528595b8a61f3ccb.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;AI Agent 的工程感官：模型负责决策，工具提供事实&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;177&#34;
		data-flex-basis=&#34;426px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;LSP 是第一层。它解决“代码语义”问题。再往后，还有更多类似的工程感官：&lt;/p&gt;
&lt;p&gt;测试框架告诉 Agent 行为有没有坏；类型系统告诉 Agent 改动是不是成立；运行时日志告诉 Agent 线上到底发生了什么；调试器告诉 Agent 状态如何流动；依赖图告诉 Agent 哪些模块真的相关；代码所有权和历史提交告诉 Agent 哪些地方不能随便动。&lt;/p&gt;
&lt;p&gt;这些东西都不是模型参数的一部分，但它们决定了 Agent 在真实项目里的判断质量。&lt;/p&gt;
&lt;p&gt;这也是我越来越不愿意把 AI 编程工具简单理解成“模型竞争”的原因。模型当然是核心，但模型像大脑，工具链像身体和感官。一个再聪明的人，如果只能隔着一堆文本截图看代码，也很难稳定完成复杂重构。&lt;/p&gt;
&lt;h2 id=&#34;上下文窗口不是万能药&#34;&gt;上下文窗口不是万能药
&lt;/h2&gt;&lt;p&gt;很多人会把 Agent 的失败归因于上下文不够长。这个判断有一部分对。代码库很大，任务很复杂，短上下文确实容易漏信息。&lt;/p&gt;
&lt;p&gt;但 LSP 这件事说明，问题不只是“塞不下”。&lt;/p&gt;
&lt;p&gt;如果 Agent 不知道一个符号真正指向哪里，给它更多搜索结果，可能只是给它更多噪音。它会看到十几个相似函数、二十处历史调用、三套旧接口，然后在里面选一个看起来最像的答案。上下文越长，未必越准，反而可能让误判更隐蔽。&lt;/p&gt;
&lt;p&gt;语义工具的价值在于过滤噪音。它不是把所有东西都塞给模型，而是在模型提问时给出结构化答案：这个符号的定义在这里；这个引用列表是这些；这个类型展开后长这样；这个重命名会影响这些位置。&lt;/p&gt;
&lt;p&gt;换句话说，未来的 coding agent（编程智能体）不应该像一个“超大号全文搜索器”，而应该像一个会调用 IDE、编译器、测试和运行时的工程助手。&lt;/p&gt;
&lt;p&gt;这也解释了为什么不同 AI 编程产品正在走向类似方向。Cursor 的优势在编辑器上下文；Claude Code 的优势在终端和任务执行；JetBrains 的优势在成熟 IDE 与语言分析；GitHub Copilot 的优势在代码托管、开发者生态和 Copilot 系列入口。大家路线不同，但最后都会碰到同一个问题：Agent 必须接入真实工程系统，而不是只接入文件系统。&lt;/p&gt;
&lt;h2 id=&#34;对开发者来说重点不是马上换工具&#34;&gt;对开发者来说，重点不是马上换工具
&lt;/h2&gt;&lt;p&gt;看到 Copilot CLI 接入 LSP，没必要立刻得出“Copilot 要超过 Claude Code”这类结论。现在各家工具迭代很快，单点功能很难决定最终胜负。&lt;/p&gt;
&lt;p&gt;更实际的问题是：你现在用的 AI 编程工具，有没有接入项目里已经存在的工程信号？&lt;/p&gt;
&lt;p&gt;比如：&lt;/p&gt;
&lt;p&gt;你的 Agent 是否能使用语言服务器，还是只会 grep？它能不能稳定跑类型检查和测试？它能不能读懂 monorepo 的 workspace 配置？它遇到第三方依赖时，是查官方文档、类型定义，还是在本地包里乱翻？它改完代码后，有没有明确的验证路径？&lt;/p&gt;
&lt;p&gt;这些问题比“哪个模型更聪明”更接近真实工作流。&lt;/p&gt;
&lt;p&gt;如果你是个人开发者，最简单的改法不是搭一套复杂平台，而是把项目里的验证入口整理清楚：类型检查命令、测试命令、lint 命令、启动命令、关键目录说明、常见坑。再进一步，就是给 Agent 配上语言服务器、文档入口和固定检查流程。&lt;/p&gt;
&lt;p&gt;这和我之前一直说的 Harness 思维有点关系，但角度不一样。Harness（支架）偏执行流程和边界控制，LSP 偏代码语义感知。前者回答“Agent 做事时怎么不失控”，后者回答“Agent 做事前到底看没看懂”。&lt;/p&gt;
&lt;p&gt;二者缺一不可。只有 Harness，没有语义感知，Agent 可能很守规矩地做错事；只有语义感知，没有 Harness，Agent 可能很懂代码但仍然乱改、乱跑、乱提交。&lt;/p&gt;
&lt;h2 id=&#34;真正的变化ai-agent-开始承认自己需要工具&#34;&gt;真正的变化：AI Agent 开始承认自己需要工具
&lt;/h2&gt;&lt;p&gt;早期 AI 编程演示里，最吸引人的叙事是“你只要说一句话，AI 就能写完代码”。这个叙事很有传播力，但对真实软件工程来说有点危险。&lt;/p&gt;
&lt;p&gt;真实项目不是面试题。它有历史包袱、框架约定、隐式边界、依赖版本、测试盲区和团队习惯。一个 Agent 如果只靠模型记忆和当前上下文，很容易写出看起来合理、实际不合项目语义的代码。&lt;/p&gt;
&lt;p&gt;GitHub Copilot CLI 接入 LSP 的意义，就在于它承认了一个朴素事实：AI Agent 需要工具，而且需要的是工程师每天已经在用的那些工具。&lt;/p&gt;
&lt;p&gt;不是所有问题都应该交给模型硬想。符号定义让 language server 查，类型约束让编译器查，行为回归让测试查，线上异常让日志查。模型负责理解目标、拆解任务、选择工具、整合结果；工程工具负责给它可靠的局部事实。&lt;/p&gt;
&lt;p&gt;这可能才是 AI 编程从 demo 走向日常工作的关键分界线。&lt;/p&gt;
&lt;p&gt;不是让 Agent 看起来更像人，而是让它更像一个接入了完整工具链的工程师。&lt;/p&gt;
&lt;h2 id=&#34;参考来源&#34;&gt;参考来源
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.blog/ai-and-ml/github-copilot/give-github-copilot-cli-real-code-intelligence-with-language-servers/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;GitHub Blog：Give GitHub Copilot CLI real code intelligence with language servers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://docs.github.com/en/copilot/concepts/agents/copilot-cli/lsp-servers&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;GitHub Docs：Using LSP servers with GitHub Copilot CLI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上来源主要用于观察 GitHub Copilot CLI 的发布口径和功能说明，不等同于独立性能基准测试。文章中的产品趋势判断，是基于公开资料和个人使用 AI 编程工具的经验推演。&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
