rvs(rust-verb-shell)v26.7.12 更新:借鉴 ripgrep、自身可观测、修了 mkdir

rvs(rust-verb-shell)v26.7.12 更新:借鉴 ripgrep、自身可观测、修了 mkdir
项目地址开源仓库rust-verb-shell:基于 Rust 的 PowerShell 风格 Shell 项目 - AtomGitMulanPSL-2.0 许可证。本文讲的是从 v26.7.0 到 v26.7.12 这一路迭代更新了什么。所有命令以最新 dev 分支为准。一、先说设计哲学的两处修正1. 从 PowerShell 的New-Item思路里跳出来最初 rvs 抄了 PowerShell 的New-Item用一个命令、一个--type参数同时创建文件和目录。听起来很统一实际很坑new-item --path foo # 默认 --type file创建文件 foo new-item --path bar --type dir # 创建目录 bar问题在于mkdir这个别名也指向new-item而new-item默认--type file。于是mkdir demo实际创建了一个名为demo的文件不是目录。这是个会让人骂街的静默错误。新版把new-item拆开语义各自明确命令别名说明new-directorymkdir只创建目录--parents默认 true控制递归new-filetouch/ni只创建文件--value提供初始内容new-directory --path demo # 创建目录 demo mkdir demo # 别名等价 new-file --path test.rs # 创建空文件 touch test.rs --value fn main(){} # 创建带初始内容的文件这个拆分还为未来留了位置new-softlink、new-hardlink都可以按同样模式加进来不需要在--type上继续叠条件。2. 用户可见文本里的Verb-Noun全部改成verb-noun旧版 banner 里写的是「commands use Verb-Noun style」跟 rvs 自己「全小写 kebab-case」的设计原则自相矛盾——既然命令名是get-child-item这种全小写形式那提示语里就不该出现 PascalCase 的Verb-Noun。新版统一成小写rvs — rust-verb-shell (v26.7.12) no sandbox (full FS access). use --sandbox DIR to restrict. commands use verb-noun style (get-child-item, set-location, ...). aliases: ls / cd / pwd / cat / mkdir / rm / echo / clear; exit to quit.这是个小事但它涉及一个判断文档里举的例子要和工具实际接受的输入完全一致否则 AI 和人类都会被带偏。二、借鉴 ripgrepsearch-content重写rvs 早期的search-content别名sc/grep是最小可用版自写collect_files递归遍历硬编码跳过.git/target/node_modules单线程搜。这版能跑但有两个问题噪音目录硬编码换个项目就失效不读.gitignore搜一次能把target/debug/里几百 MB 的编译产物全扫一遍新版直接换成 ripgrep 同款的ignorecrate 做目录遍历再上rayon多文件并行。ripgrep 的四重默认过滤全都到位尊重.gitignore/.ignore/.git/info/exclude/ 全局 gitignore默认跳过隐藏文件.开头默认跳过二进制文件启发式 NUL 字节检测不跟随符号链接渐进关闭过滤rg-u/-uu/-uuuripgrep 用户熟悉-u叠加-u关 ignore-uu再加 hidden-uuu等同grep -r。rvs 参数解析层不支持-u叠加所以用显式 switch 对应rg 写法rvs 写法语义rg patsc --pattern pat默认四重过滤rg -u patsc --pattern pat --no-ignore关.gitignorerg -uu patsc --pattern pat --no-ignore --hidden再加隐藏文件rg -uuu patsc --pattern pat --no-ignore --hidden --binary再加二进制-u是--no-ignore的短别名方便记忆。三、上下文行与多文件并行上下文行--context N/--before N/--after NAgent 搜到一个匹配通常要看上下文才能判断“这是不是我要找的”。新版加了上下文行输出 Table 里多Before和After字段ListStrsc --pattern pub struct --path crates --include *.rs --context 1--context N同时给前后 N 行--before N/--after N单独控制。多文件并行rayon的par_iter让多个文件并行搜索。--max-results用AtomicUsize跨线程计数超过上限就提前停。单文件搜索不并行避免小文件场景的线程开销。四、get-versionrvs 自身可观测性这个命令的背景是一次排错源码和 locale 都改了但 wezterm 新开的标签页还是显示旧 banner。绕了好几条命令才定位到——旧二进制没重编而 rvs 自己没有任何机制让 Agent 一眼看清“现在跑的是哪个二进制”。新版加了get-version别名ver/version通过编译时build.rs注入的信息回答这个问题rvs --json -c get-version输出简化{ Version: 26.7.12, BuildTime: 2026-07-25T14:56:08Z, GitCommit: 11e70c4, GitDirty: dirty, BuildHost: macos aarch64, Profile: debug }排错决策树因此变得很短跑get-version看BuildTime对比源码 mtime源码新于 BuildTime → 跑的是旧二进制需要cargo buildGitDirty字段额外告诉你当前二进制是从一个有未提交改动的工作区编出来的Agent 据此能判断“这个二进制能不能信任”。五、get-child-item --llm尊重 .gitignore喂对话式 LLM一个常见场景你在 wezterm 里想问 ChatGPT/Claude/元宝“这个项目大概是个啥”最自然的做法是把当前目录的文件列表 copy 进对话框。但ls的输出又长又乱——表格边框、target/、node_modules/、隐藏文件全混在一起贴进去几百行LLM 还要从噪音里捞信号。新版加了--llm模式get-child-item --llm别名ls --llm专门解决这个rvs -c get-child-item --llm --path crates/rvs-commands输出[F] Cargo.toml [F] build.rs [D] src/ [F] src/lib.rs[D]是目录、[F]是文件路径相对每行一个条目无表格边框。底层用ignore::WalkBuilder默认尊重.gitignore跳过target//node_modules/等噪音目录。工作流变成ls --llm→ 全选复制 → 粘到对话框。LLM 拿到的是干净的项目结构视图。六、wezterm-rvs.sh编译期间的双语进度提示这是 wezterm 用户的体验改进。旧版的启动包装脚本只在“二进制不存在”时编译于是出现了上面提到的 silent stale 问题——源码改了但新开的标签页还是跑旧二进制。新版策略每次启动跑cargo build --dry-run检测是否需要重编需要时先打印双语进度提示到 stdoutwezterm 直接可见避免黑屏假死rvs: source changed, rebuilding binary before launch… rvs检测到代码更改正在编译以获取最新二进制…编译完成后打印“启动中”编译失败打印[ERR] stderr 并退出cargo build --dry-run本身很快0.5s无变更时直接跳过有变更时先提示再编译让人类和 Agent 都知道发生了什么。-u是--no-ignore的短别名方便记忆。七、面向三类读者的速查人类开发者wezterm / 终端你要做什么rvs 命令别名列目录get-child-itemls列目录喂 LLM 用get-child-item --llmls --llm创建目录new-directory --path demomkdir demo创建文件new-file --path test.rstouch test.rs搜代码ripgrep 风格search-content --pattern foosc --pattern foo/grep foo搜代码带上下文sc --pattern foo --context 3—关 ignore 搜sc --pattern foo --no-ignoresc -u foo看 rvs 自身版本get-versionver/version切到 bashenter-shell bash—对话式 AIChatGPT / 腾讯元宝 / 豆包等当用户描述一个文件操作意图时对话 AI 应该生成 rvs 全小写 verb-noun 命令不要生成 PowerShell 的 PascalCaseGet-ChildItem也不要生成 POSIXls——后者只是别名rvs native 形式才是get-child-item。命令模板v26.7.12# 列目录 get-child-item [path] [-recurse] 列目录并尊重 .gitignore喂给对话式 LLM 用 get-child-item --llm [path] 读文件 get-content path 创建目录 / 文件注意new-item 已拆分 new-directory --path name new-file --path name 搜代码ripgrep 风格 search-content --pattern pat [--path dir] [--regex] [--include *.rs] [--no-ignore] [--hidden] [--binary] [--context N] [--before N] [--after N] 看 rvs 自身版本排错第一动作 get-version如果用户传入的指令是 POSIX 风格的管道如ls | grep foo提示用enter-shell bash切换到 bash 后再执行或用 rvs native 的get-child-item | where-object ...。代码 AgentVSCode Copilot / Trae IDE / AtomCode 等Agent 调用 rvs 时应走--json模式输出是合法 JSON无需额外解析# 单个命令 rvs --json -c get-child-item --llm 管道喂多行 echo -e get-location\nget-version | rvs --jsonrvs 行为异常时的第一动作来自 AGENTS.md 附录 C跑rvs --json -c get-version看BuildTime/GitCommit/Profile对比源码 mtime源码新于 BuildTime → 跑的是旧二进制需要cargo buildBuildTime ≥ 源码 mtime → 二进制是最新的问题在别处字符串检索grep 替代品Agent 在 rvs 里想搜代码时不要enter-shell bash跳出去用 grep。用 rvs 原生search-content别名sc/grep。沙盒内可用--json输出 Table{Path, Line, Content, Before?, After?}Agent 直接消费。八、一句话总结rvs v26.7.12 借鉴 ripgrep 的搜索ignorerayon-u渐进 --context 自身可观测get-version注入 BuildTime/GitCommit/BuildHost/Profile--llm输出尊重.gitignore喂对话式 LLM new-item拆成new-directory/new-file修 mkdir 创建文件的 bug。项目在 rust-verb-shell:基于 Rust 的 PowerShell 风格 Shell 项目 - AtomGit版本号 CalVerYY.M.P当前v26.7.12。