探索陌生代码
agent 读陌生代码烧 token 的速度飞快:为了“建立全局感”倾倒整个文件,为找一个类型的定义 反复重读,为搞清一个 40 行函数的所作所为塞进日志体量的上下文。CtxCtl 把流程倒过来—— 先拿地图,只读你需要的地盘。以下命令全部只读且无状态;不索引、不缓存。
outline 每个符号打一行——种类、名称、行区间、签名——外加 token 节省统计。这是对任何受支持
文件最便宜的定向扫描:
ctxctl outline src/server.rs# src/server.rs [12 symbols, ~2.1 KB -> ~410 tokens, saved ~80%] fn handle_request L:42-58 pub async fn handle_request(&self, id: u64) struct RequestHandler L:12-40 pub struct RequestHandler { const MAX_RETRIES L:60 const MAX_RETRIES: u32 = 3;仅凭这一步,agent 不读文件就已经掌握它的形状。超大文件的符号列表超过阈值(默认 50)后会折叠成
一行 ... [N symbols omitted] 标记;表头始终保留总数。想要极简输出可加 --no-doc
去掉文档注释。
用 –signature 和 –compact 收窄
Section titled “用 –signature 和 –compact 收窄”大纲点出了感兴趣的符号之后,往往还不需要立刻读完整函数体:
# 只要声明行ctxctl symbol src/server.rs --name handle_request --signature
# 签名 + 函数体的折叠标记ctxctl symbol src/server.rs --name handle_request --compact--compact 返回 AST 剪枝视图:签名(python 还带装饰器)、一条 // ... [N lines omitted]
折叠标记(python 为 # …),以及存在时的裸收尾行。它字节稳定且重新解析不会报错,
下游工具照常消费。
这两个开关回答 agent 最常见的问题——“这个函数收什么、返回什么?”——代价只是完整读取的零头。
需要时才读函数体
Section titled “需要时才读函数体”要真正的实现时,不带附加参数的 symbol 会从原始源码返回该符号的逐字切片:
ctxctl symbol src/server.rs --name handle_request# handle_request src/server.rs:42-58 (58 tokens, saved ~85%)pub async fn handle_request(&self, id: u64) -> Result<String, Error> { let row = self.db.get(id).await?; Ok(row.to_string())}切片原样保留注释、格式和缩进——它是源码,不是摘要。几个有用的精调:
--kind <k>收窄同名匹配(方法对局部变量)。出现重名时,除非收窄,否则源码顺序第一个胜出。--lines 3-10在符号内部再取子区间,定位到精确行后使用。- 退出码 4 表示未找到符号——多半是拼写错误或文件不对,而不是功能缺失。
对于落在任何单个符号之外的区间——模块级文档块、配置表——用 read,它完全不需要 AST:
ctxctl read src/server.rs --lines 100-150ctxctl read src/server.rs --lines 100-150,200-210 # 多个区间,逗号分隔开区间会钳制到文件末尾(--lines 10-)。退出码 2 表示区间无效或越界。
用 deps 追导入关系
Section titled “用 deps 追导入关系”跨文件跳转之前,先看看这个文件依赖什么。deps 列出每个导入的目标、种类与行号:
ctxctl deps src/main.rs# src/main.rs [3 imports, ~512 B -> ~64 tokens, saved ~88%]external serde L:1local crate::lib L:2local / external 的区分直接告诉 agent 哪些跳转留在仓库内(值得跟一个 outline),
哪些跨进第三方依赖(通常根本不值得读)。
非代码文件同样适用
Section titled “非代码文件同样适用”同一套工作流覆盖的不止源码——符号引擎为标记与样式语言也提供了后端:
- Markdown: 每个 ATX/setext 标题都是符号,且标题的切片覆盖整个小节——因此
symbol README.md --name Install返回的正是那一节。 - CSS/SCSS: 规则集是符号(选择器列表即名称),嵌套的
@media块也包含在内。 - HTML: 带
id属性的元素可以用该 id 寻址。
agent 探索文档密集型仓库时,享受同样的“先大纲后切片”纪律,无需任何特殊处理。
一次完整的便宜探索长这样:
ctxctl outline src/server.rs # mapctxctl deps src/server.rs # what it hangs offctxctl symbol src/server.rs --name handle_request --compact # shape of the targetctxctl symbol src/server.rs --name handle_request # body, verbatimctxctl read src/server.rs --lines 100-110 # anything outside symbols每一步的输出都指向下一步的决策点,而每一步都远小于整个文件。想让命令输出同样变小,见 压缩命令输出;“切片而非摘要”背后的理由在设计原则。