这篇文章记录了作者为什么会持续关注 ace-tool 这个方向,并把它当成理解 Agent 代码上下文的一次学习与探索。 核心观点是:AI Coding 当前更缺少稳定、低噪音、可集成的代码语义上下文,而不是另一个更大的平台叙事。 ace-tool 在这里更像一个观察样本:基于 TypeScript Language Service,帮助作者思考代码导航、引用分析、改名预览和影响面判断这些能力为什么重要。
最近我一直在想一件事。
现在大家做 AI Coding,特别容易越做越大。一开始可能只是想解决一个很具体的问题,比如“怎么让 Agent 更懂代码库”,结果做着做着,就开始想做索引、做工作流、做记忆、做规划、做自动化、做 UI、做多 Agent,最后不知不觉就会走向一个更宏大的叙事:做一个全能的 AI 开发平台。
这条路当然没问题,也确实有很多值得做的事情。
但这段时间我反而越来越确定,至少对我来说,现在更想继续学习和探索的,不是再去拼一个大而全的东西,而是先把一个很窄、但非常关键的能力层想清楚、看扎实。
所以最后我把注意力更多放在了 ace-tool 这个方向上。
这个想法当然不是凭空来的。我确实受过一些项目和讨论的启发,尤其是看到越来越多人开始认真对待“代码上下文”这件事之后,我更确信:Agent 在代码库里真正缺的,往往不是“更聪明地说话”,而是“更准确地理解代码结构”。
是的,这个方向上已经有很多工具了。但我并不想再把它理解成一个要不断做大的平台命题,我更想把它当成一次对其中一层能力的持续学习和探索。
但最后我自己的判断是,不跟着把盘子越铺越大,而是先围绕 ace-tool 这种更专精、更克制的能力层继续观察、验证和积累理解。
这篇文章我想把三件事讲清楚:
ace-tool 的能力边界到底在哪里我现在更愿意把 ACE 理解成一个很朴素的词:Agent Context Engineering。
它不是什么神秘的新名词,也不是什么包装出来的概念。说白了,它就是在回答一个问题:
怎么把代码库里真正有用的上下文,准确地交给 Agent。
为什么这件事重要?
因为很多 AI Coding 的问题,根本不是模型能力本身的问题,而是上下文组织得太差。
最常见的情况就是,Agent 明明在“读代码”,但它拿到的其实只是一些零散文本:
这时候你会发现,问题根本不在于模型不会推理,而在于它没有站在一个足够稳的代码语义地基上。
所以在我看来,ACE 的核心不是“让 Agent 看到更多内容”,而是“让 Agent 看到更对的内容”。
不是把更多文件喂进去,而是把真正关键的结构拿出来。比如:
这些信息,本来就是代码库里存在的,只是过去更多是 IDE 在消费它们,人类在点击它们,Agent 很少真正稳定地拿到它们。
所以 ACE 做的事情,本质上不是发明新的代码知识,而是把原本散落在编辑器、语言服务、项目结构里的“工程语义”,重新整理成 Agent 可用的上下文。
我觉得这是现在很值得单独做的一层。
我后来越来越警惕一件事:一旦你开始做 AI Coding 工具,就很容易被“完整性”诱惑。
你会忍不住想:
然后这个项目就会从一个很锋利的问题,慢慢长成一个什么都想管的系统。
问题是,这条路不是不能走,而是太容易失焦。
因为盘子一旦铺开,你要解决的就不再只是“代码理解”了,而会变成:
每一项都很合理,但每一项都可能把一个项目拖进更大、更重、更慢的复杂度里。
所以我这次反而想反过来。
先别急着回答所有问题,先把其中一个最真实、最刚需、最有复用价值的问题做透:
Agent 进入代码库之后,怎么快速、准确、低噪音地理解它。
如果这层没做好,后面加再多规划、再多自动化、再多 workflow,地基还是虚的。
而 ace-tool,就是我现在用来继续理解这层问题的一个很具体的切口。
一句话说,ace-tool 是一个基于 TypeScript Language Service 的本地代码导航与重构分析工具。
它不是全文索引器,也不依赖外部向量服务。在我这里,它更像是一个观察样本:让我能更具体地理解,怎么把 IDE 里的关键语义能力,整理成 Agent 和人都能稳定使用的接口。
它当前提供的能力,主要包括这些:
如果把它说得更通俗一点:它做的不是“帮我搜更多”,而是“帮我少看错”。
我一直觉得,AI Coding 里一个特别隐蔽、但很要命的问题,就是上下文噪音。
不是没有信息,而是有太多“差不多像”的信息。尤其在真实项目里,字符串相同不代表语义相同,名字相近不代表落点一致,搜到了也不代表能安全修改。
所以 ace-tool 不是奔着“结果多”去的,而是奔着“结果准”去的。
我越来越觉得,一个方向值不值得继续探索,不是看它能不能把故事讲得很大,而是看它有没有把“不该干什么”讲清楚。
ace-tool 的边界,我现在反而很愿意提前说透。
这是它最强、也最明确的能力区间。
因为底层直接站在 TypeScript Language Service 上,而项目本身也已经覆盖了 .ts、.tsx、.js、.jsx、.vue 这些主链路文件,所以 definition、references、implementations、rename、type info、diagnostics、call hierarchy 这些能力,在这一条链路上是最稳的。
换句话说,ace-tool 当然已经包含 React 场景。
只要你的工程主要工作在 tsx/jsx 这条链路上,不管是组件、hook、type、function,还是模块依赖、改名影响、引用追踪,这套能力都是成立的。
但我还是想把话说准确一点:我说它支持 React,指的是它对 React 工程里的静态语义结构有很好的理解和导航能力;不是说它要做成一个 React 专项框架工具,更不是去覆盖运行时、渲染结果、框架生态里所有约定层的能力。
我比较在意这点,因为“支持 React”和“React 全场景理解”之间,其实差了很远。
这部分我也支持,但我没有打算把它包装成完整语言服务。
比如它现在能做的更偏向于:
id、script、stylesheet 这种结构信息这很好用,但我不想把这个能力说得太满。
因为这部分的定位,本来就是“补充理解”,不是“完整语义分析”。
我宁愿说清楚它现在就是辅助能力,也不想用一种听起来很全、但实际上会误导预期的说法。
如果一个问题本质上只是:
那我不会建议硬用 ace-tool。
这个时候最合适的还是:
fdrgast-grepjqyq一个工具是否成熟,有时候不在于它有没有更多入口,而在于它知不知道什么时候该让路。
我现在对 ace-tool 的期待,不是“什么都能做”,而是“在适合它的地方特别稳,不适合它的地方别硬来”。
这点我也不想藏着掖着。
ace-tool 不是来解决所有 Agent 问题的。
它不负责完整规划,不负责网页搜索,不负责全语言支持,不负责多 Agent 编排,也不负责替你变成一个总控台。
它更像是一层能力层。
但也正因为它只是一层能力层,所以它反而更容易被接到各种不同的工作流里。你可以把它接进 Codex,也可以接进别的 Agent,也可以只是把它当成一个自己用的 MCP 工具。
有时候,不试图统治全局,反而更有生命力。
如果只看功能表,ace-tool 其实不算那种“看起来很炸裂”的项目。
但它里面有几处设计,我自己是挺认同的。不是因为它们多复杂,而是因为它们很克制,也很贴近真实使用场景。
这可能是整个项目最核心的取舍。
现在很多 code context 产品,第一反应都是先扫仓库、切 chunk、做 embedding、建索引、再检索。
这个方向没有问题,但对 TS / JS / React / Vue 这种场景来说,我越来越觉得,TypeScript 自己已经是一个成熟得不能再成熟的代码理解系统了。
既然这样,我为什么不先直接复用它对当前 workspace 的理解,而是再重新造一套“第二层理解”?
这个判断带来的好处很实际:
我很喜欢这种做法的一点是,它不炫技。
它不是为了显得系统更大而去多造一层,而是先把现成最可靠的那层能力用起来。
这个点不显眼,但我觉得很值。
真实项目里,很多 symbol 并不是以“定义长什么样,暴露出来就长什么样”的方式存在的。
中间会有:
如果只是全文检索,你经常会搜到很多“看起来像”的地方,但不一定是你真正该跳过去分析的那个位置。
所以我在 ace-tool 里,不只是把 symbol 搜出来,而是专门去处理这些导出形态,并且给 candidate 做排序和消歧。
本质上,我想解决的不是“有没有这个词”,而是“你真正想找的那个 symbol,更可能是哪一个”。
这两个问题,差别很大。
这一点我现在反而越来越坚持。
很多工具为了让体验看起来顺,会在信息不够时帮你“猜一个最可能的”。
但在代码修改场景里,这其实很危险。尤其是 definition、references、rename 这些能力,一旦落点错了,后面一整串判断都会跟着偏。
所以 ace-tool 的做法是:如果同名定义太多,信息不足,那就老老实实返回 ambiguous,要求调用方继续给 filePath 做消歧。
这听起来没那么“智能”,但我觉得这是更工程的态度。
代码场景里最怕的不是不知道,而是假装知道。
我自己改代码的时候,特别在意一件事:引用结果到底是“看起来有用”,还是“真的能拿来做判断”。
因为如果一份 references 结果里混着:
那它虽然 technically 是“有结果”,但实际上你还是得自己再做一轮脑内过滤。
所以 ace-tool 在 references 这里没有停在“查全”,而是继续做了降噪能力,比如:
modeincludeDefinitionsincludeImportExportpathPrefix这类参数看起来不花哨,但在真实重构前评估里非常有用。
因为很多时候,提升效率靠的不是结果变多,而是噪音变少。
我挺喜欢 impact summary 这个能力。
因为它不是为了再多发明一个新功能,而是把几个高频分析动作顺手串起来了。
一个真实的工程动作,经常不是只问一个问题。比如准备改一个核心 symbol 时,我通常会连续问:
这些问题单独看都成立,但如果每次都要手动点五个入口,再自己拼起来,成本还是挺高的。
所以 impact summary 做的事情,本质上不是加新轮子,而是把这条高频链路打包成一个更顺手的入口。
我现在越来越认同一点:好的工具不只是提供原子能力,也应该理解真实工作流。
我对这点是有执念的。
很多 AI 工具一上来就喜欢直接替你执行,但代码里的 rename 其实是个高风险动作。尤其在复杂 workspace 里,rename 不是“把一个词替换掉”那么简单,它是一个带传播性的工程动作。
所以我更喜欢的做法是:
也就是说,先 preview,再决定要不要改。
这背后其实是一种很朴素的产品判断:在代码修改这件事上,确定性比自动化更重要。
这一点虽然小,但我觉得是必须的。
因为这种能力天然有两类调用方:
只给 text,人看着舒服,但机器不好接。
只给 JSON,机器容易处理,但人看着费劲。
所以我一开始就想清楚,它不该只偏向一边,而应该两边都能用。
这也是为什么我会把状态语义收得比较明确,比如:
okmissingambiguousunsupportedfailureunavailable因为我不想让它只是一个“给 demo 看起来能跑”的接口,而是想让它真的能成为上层系统可信赖的能力层。
回到最开始那个问题。
为什么不干脆把它推成一个更大的系统?
因为我现在越来越确信,今天这个阶段,AI Coding 领域最缺的,未必是另一个全家桶,而是一些真正稳定、真正可集成、真正能减少上下文噪音的基础能力。
ace-tool 让我能持续盯住的,就是其中一件很具体的事:
让 Agent 在 TS / JS / React / Vue 代码库里,不再只是“看到代码文本”,而是开始“看到代码结构”。
我很喜欢这件事的一点是,它没有那么大,也没有那么热闹。
它不是一个宏大叙事,不是一个万能平台,也不是一个恨不得把所有事情都包进来的系统。
它只是很明确地盯住一个问题:怎么让代码上下文这件事,变得更可信。
一些项目给过我启发,但我最后给自己的答案,不是把盘子继续做大,而是把范围收小,把边界讲清楚,把这里面的关键能力一点点看明白。
先别急着把它变成一个“什么都能做”的系统。
先继续研究一个“在关键问题上真的靠谱”的能力切口。
这就是我现在还想继续探索 ace-tool 的原因。
如果要我用一句话来概括 ace-tool,我现在会这么说:
它不是一个试图取代所有工具的工具,而是一层让 Agent 真正读懂代码结构的工程语义接口。
我不想让它看起来无所不能。
我更希望它在该它出手的时候,足够稳,足够准,足够诚实。
对我来说,这比“看起来很大”,更重要。
ace 工具还是持续开发验证中,后续成熟会考虑分享出来。
可以看下最终的效果:

文章的优势在于判断克制,没有把它包装成宏大产品,而是把关注点放在能力边界和工程语义本身。 如果后续继续打磨,可以补一两个真实项目中的观察片段,让“为什么这个探索值得继续”更具体、更有代入感。