Skip to content

Latest commit

 

History

History
1579 lines (1137 loc) · 79 KB

File metadata and controls

1579 lines (1137 loc) · 79 KB

Windows 使用教程

git clone 一路到能对话的完整步骤。每步都给了预期产出,不对就停下看第 6 节。

第一次用的人先看 windows-quickstart.md —— 那份一屏读完, 每条命令都给了 cmd 与 PowerShell 两种写法。本文是详版 + 排障手册,卡住了再回来查。

仓库里另有三份 Windows 文档,分工不同,别拿错

文档 是什么 什么时候看
windows-quickstart.md 一屏读完的首次上手(含 cmd/PS 双写) 你第一次装
本文 windows-usage.md 详版 + 30+ 条排障对照表 你卡住了 / 想知道为什么
windows-release.md 出包与发布 runbook 你要出一个可分发的安装包
windows-dev.md 逐条验收清单(124 勾) 你要验证这个端口有没有做对

诚实声明:Windows 端代码已完成,但尚未在真 Windows 机器上跑过一次。本文按代码实际行为编写,若你遇到与本文不符的情况,那大概率是真 bug,欢迎照第 6 节的排查方向记录下来。

⚠️ 先确认你在 PowerShell 里,不是 cmd

本文所有命令按 PowerShell 写。看提示符就能分辨:

提示符 是什么 能否照抄本文
PS D:\wraith> PowerShell
D:\wraith> cmd.exe ❌ 部分命令不存在

在 cmd 里敲 powershell 回车即可切换(目录不变)。

两者全部会咬人的差异(本文命令按 PowerShell 写;下面的关键步骤都另附了 cmd 写法):

用途 PowerShell cmd
环境变量取值 $env:LOCALAPPDATA %LOCALAPPDATA%
设临时环境变量 $env:FOO = "v" set FOO=v等号两边不要空格
设永久环境变量 [Environment]::SetEnvironmentVariable("FOO","v","User") setx FOO "v"
删目录 Remove-Item -Recurse -Force x rmdir /s /q x
切目录 Set-Location xcd x cd x
判断文件存在 Test-Path x dir x
找命令位置 Get-Command npx / where.exe npx where.exe npx
串联两条命令 a; b5.1 不支持 &&,7+ 支持) a && b
.ps1 .\x.ps1(被策略拦就用下面那句) powershell -ExecutionPolicy Bypass -File x.ps1
看 PATH $env:PATH -split ';' echo %PATH%
结束进程 Stop-Process -Name java -Force taskkill /IM java.exe /F

两条最容易静默走偏的

  1. 在 cmd 里跑带 $env: 的命令不会报错,而是把 $env:LOCALAPPDATA 当普通字符串传下去 —— 比如 npm config set cache "$env:LOCALAPPDATA\npm-cache" 会真的把缓存设到一个叫 $env:LOCALAPPDATA 的目录里。静默走偏,比报错难查。
  2. PowerShell 5.1(Windows 自带那个)里跑 a && b 会报 标记"&&"不是此版本中的有效语句分隔符。换成 a; b

0. 全程一眼

前置(JDK17/Maven[/Node])  →  git clone  →  (main 就是最新,不必切分支)     
                                              │
              ┌───────────────────────────────┼───────────────────────────────┐
        路线 A 开发态                    路线 B 装包                    路线 C 只用命令行
        (最快看到桌面)                 (要一个能分发的 exe)            (不需要 Node)
        dev-win.ps1                     mvn package                    mvn package
        npm install                     npm install                    java -jar …
        npm run dev                     npm run dist:win → 装          (第 8 节)
              └───────────────────────────────┼───────────────────────────────┘
                                              ↓
                                    配一个模型(第 2 节)
                                     三条路线共用同一份配置
                                              ↓
                                        发第一条消息
                                              ↓
                              wraith sandbox doctor  ← 建议早跑(第 6.5 节)
                              四条探针,确认沙箱真在拦

只想跑起来看看 → 路线 A。想要一个能给别人的安装包 → 路线 B。只在终端里用、不想装 Node → 路线 C(第 8 节)

想要 wraith / wraith -d 这两条短命令(而不是每次手打 java -jar … / npm run dev): 在仓库根跑一次 powershell -ExecutionPolicy Bypass -File scripts\windows\wraith-install.ps1, 然后新开一个终端。三条路线都适用,详见 §1 A4。 装完 wraith -h 能看到全部用法。

为什么建议早跑 doctor:沙箱起不来时 wraith 是 fail-open 的 —— 命令照常执行、不会报错,只是没有围栏。也就是说你不主动查,是不会知道的。 顶栏盾会变红,但那容易被忽略。


1. 从零到跑起来

1.1 前置

java -version    # 期望 17.x
mvn -v           # 能输出版本
node -v          # v18+
git --version

四项都要在 PATH 里。缺 JDK 17 就先装 JDK 17 —— 仓库按 Java 17 编译。

只走路线 B 装完之后用 App 的人不需要 Java(安装包捆绑了 JRE)。但构建这一步需要。

⚠️ Node 是个例外:它既是构建依赖,也可能是运行时依赖。 安装包捆绑 JRE,但不捆绑 Node。 只要你打算用 npx 起 MCP server,装好的 App 也需要系统里有 Node —— 详见第 6 节「加 MCP server 报 Cannot run program "npx"」。不用 MCP 则完全不需要。

另外两个可选外部命令:ollama / uvx

Windows 两个都不自带,安装包也不含。但它们各自只服务一小块功能 —— 不装照样能正常用 wraith, 所以先看清「不装会失去什么」,再决定要不要装:

命令 谁需要它 不装的后果 有没有替代
ollama 本机 embedding。用到的地方:/index 建代码索引、/search 语义检索、agent 的 search_code 工具、桌面「代码图谱」面板 建索引/检索时报连不上 11434内置工具里只有 search_code 一个受影响,读写文件、grep、跑命令、任务、记忆全都照常 :embedding 后端改成云端(openai / zhipu / glm),一行配置,完全不需要 ollama
uvx Python 生态的 MCP server。桌面「插件」推荐清单 10 项里有 3 项用它:Fetch、Git、Time 这 3 项起不来,报 Cannot run program "uvx" :另外 7 项走 npx,只用它们就完全不需要 uv

装法与分诊见第 6 节的 「代码索引报连不上 11434」与 「加 MCP server 报 Cannot run program "uvx"」。

这两个和 Node 的性质一样:运行时依赖,不是构建时依赖。缺它们不影响 mvn / npm run dev / 出包。

1.2 拉代码

git clone https://github.com/JavaLyHn/wraith.git
cd wraith

不需要切分支。 Windows 对等的全部代码(自绘窗控、dev-win.ps1、NSIS 打包配置、AppContainer 沙箱)已于 2026-08-05 合入 main —— clone 下来就是最新的。

本文早前的版本要求 git checkout feat/windows-parity-block1,那是合并之前的说法。那条分支仍然存在、且与 main 指向同一个提交,切过去不会错,只是没必要。

⚠️ 但**「代码合入」不等于「验证完成」**:AppContainer 沙箱、NSIS 安装包、桌宠 FFI 这几块只能在真 Windows 上验,尚未全部验完。本文按代码实际行为编写。

这里用的是 HTTPS,不是 SSH。 本仓库是公开的,HTTPS 拉取不需要任何认证配置。 若你改用 git@github.com:... 而报 ssh: connect to host github.com port 22: Connection refused, 那是 22 端口被网络挡了(公司网/校园网/部分 ISP 常见)。要么换回 HTTPS,要么让 SSH 走 443:

# %USERPROFILE%\.ssh\config
Host github.com
  HostName ssh.github.com
  Port 443
  User git

之后若要 push,HTTPS 配合 Git for Windows 自带的 Credential Manager 最省事 —— 首次推送会弹浏览器授权,之后自动记住。

确认一下:

dir desktop\scripts\dev-win.ps1   # 这个文件在,就说明代码是完整的

路线 A:开发态跑起来(最快)

A1. 备后端 jar

powershell -ExecutionPolicy Bypass -File desktop\scripts\dev-win.ps1

它做两件事:在仓库根跑 mvn -q clean package -DskipTests,然后把产物拷到 %USERPROFILE%\.wraith\wraith.jar(桌面 dev 态就是从这个固定位置起后端的)。

  • 结尾打印 dev-win: 已安装 -> C:\Users\<你>\.wraith\wraith.jar,并列出文件大小与时间戳

-ExecutionPolicy Bypass 是必须的,否则默认策略会拒绝执行未签名的 .ps1。 脚本取的是 target\wraith-*.jar最大的那个(shade 后的可执行包,original-* 不匹配这个通配)。

A2. 装前端依赖

cd desktop
npm install --legacy-peer-deps
  • 装完无 ERESOLVE 报错

--legacy-peer-deps 不能省@lobehub/icons@lobehub/ui 有 react 18 vs 19 的 peer 冲突,干净 checkout 上普通 npm install 会直接失败。

A3. 起

npm run dev
  • 主窗出现,无系统标题栏,右上角是自绘的 最小/最大/关闭 三键
  • 界面不报「后端未连接」

报后端未连接:dev 态主进程跑的是 spawn('java', ['-jar', '%USERPROFILE%\.wraith\wraith.jar', 'app-server']),走系统 PATHjava。GUI 应用不继承登录 shell 的 PATH —— 这是 Windows 上的经典坑。确认 java 在系统级 PATH 里,改完重启终端再 npm run dev

改完 Java 代码要重跑 A1(dev 态起的是 %USERPROFILE%\.wraith\wraith.jar,不是 target\ 里那个)。改前端代码则热更新,不用管。完整的「改了什么 → 重跑到哪一步」对照表见第 5 节。

A4. 装上 wraith 短命令

这一步严格说可跳过(java -jar … / npm run dev 一样能用),但跳过之后就没有 wraith 命令—— 直接敲会看到 无法将"wraith"项识别为 cmdlet、函数、脚本文件或可运行程序的名称。 这一条同时服务路线 A / B / C,建议装。

mac 上有 wraith(终端 CLI)和 wraith -d(桌面 dev)两条短命令。Windows 也有,装一次:

# 必须在仓库根跑(脚本靠自身位置反推仓库)
powershell -ExecutionPolicy Bypass -File scripts\windows\wraith-install.ps1

它做两件事:构建并安装 jar 到 %USERPROFILE%\.wraith\wraith.jar(内部复用 dev-win.ps1,不是另一套构建逻辑),然后把 scripts\windows 加进用户级 PATH(不需要管理员)。

必须新开一个终端,当前窗口读不到新 PATH。之后:

wraith              # 终端 CLI(交互式对话)
wraith -d           # 桌面端 dev
wraith -h           # 全部用法(不需要 jar 就能看)
wraith-install      # 改完 Java 后端后重新构建装 jar

wraith -c                    # 接着上一次会话
wraith -r                    # 列出历史会话挑一个恢复
wraith sandbox doctor        # 沙箱体检
  • 新终端里 wraith -h 打印用法(不打印 = PATH 没生效,见 §6「wraith 不是内部或外部命令」)
  • wraith-install 结尾打印 已安装 -> C:\Users\<你>\.wraith\wraith.jar

-d-h 是启动器截走的,其余参数原样透传给 Java CLI。 这样安全是因为 Java CLI 自己只认 -c/--continue-r/--resume,没有 -d 也没有 -h

装了短命令后,第 5 节那句「改完 Java 重跑 dev-win.ps1」就简化成一句 wraith-install

与 mac 版的一点差别:mac 那个脚本把仓库路径写死在里面(换台机器就废)。Windows 这版从脚本自身位置反推仓库根,仓库挪到哪都能用;真要把 wraith.cmd 复制到仓库外,设 WRAITH_REPO 指向仓库根即可。

跳到第 2 节配模型。


路线 B:出安装包并安装

# 仓库根
mvn clean package -DskipTests       # 产出 target\wraith-1.0-SNAPSHOT.jar
cd desktop
npm install --legacy-peer-deps
npm run dist:win                    # 产物:desktop\release\Wraith Setup <版本>.exe

出包后立刻验一件事

desktop\resources\runtime\bin\java.exe -version
  • 能跑,输出 17.x。报「不是有效的 Win32 应用程序」或文件不存在 = 打进去的是别的平台的 JRE,包是废的

必须在 Windows 机器上出 Windows 包。捆绑 JRE 由宿主 jlink 产出、node-pty 是原生模块,都不能交叉。在 mac 上跑 npm run dist:win 会被脚本硬拦下(退出码 1)。

双击 desktop\release\Wraith Setup <版本>.exe

  • SmartScreen 拦一下,报**「Windows 已保护你的电脑 / 未知发布者」——安装包未签名**(根治需 Authenticode 证书)。点**「更多信息」→「仍要运行」**。
  • 向导式安装,可改安装目录,会建桌面开始菜单快捷方式。
  • 从开始菜单启动。

装完之后不需要再装 Java(但 MCP 可能需要 Node)

安装包捆绑了 JREresources\runtime\bin\java.exe)和后端 jar。用装好的 App 的人不需要系统里有 JDK —— 前面那套 JDK/Maven 只是构建时要的。也因此路线 B 装完后不会遇到路线 A 那个 PATH 坑。

Node 不在捆绑之列。 装好的 App 里,除非你要加 npx 形式的 MCP server,否则用不到 Node;一旦要加,就得系统里有。判断方法和三条替代路线见第 6 节「加 MCP server 报 Cannot run program "npx"」。


2. 首次启动:配一个模型

启动后 wraith 还不能对话 —— 它不知道用哪个模型、拿什么密钥。

全新装机直接在应用里配就行:首页会显示一条「还没有配置模型 · 去配置」,点它直达 Provider 面板;填完保存即可用,不需要重启

历史说明(已修复):更早的版本存在一个首次运行死锁 —— 后端在没有任何 API Key 时 System.exit(1),而「Provider 配置」面板又要通过后端 RPC 写配置,于是「想配 key 得先有 key」,全新装机在应用内无路可走,控制台狂刷 app-server: 未找到可用 API Key + 满屏 Backend not connected

现在后端无模型也照常启动:配置类 RPC 全部可用,发起对话才会被拒绝并给出提示;配好 provider 后就地热装。若你仍看到上面那串报错,说明跑的是旧 jar —— 见第 5 节「代码更新后怎么重新跑」。

① 图形界面配(推荐)

  1. 左侧栏找到 配置 → Provider 配置
  2. 搜索或在列表里挑一个 provider(GLM / DeepSeek / Kimi / StepFun / 讯飞星辰 …),点 +配置
  3. 多数 provider 卡片右上角有 「获取密钥 →」 链接,直接跳该家控制台去申请
  4. API Key(必填)、模型Base URL(多数有默认值,不用改)
  5. 「测试连接」 —— 成功显示 ✓ 连接成功 · 模型名 · 延迟ms;失败显示 加后端原文错误
  6. 「保存」。回到列表后,若这张卡片上有 「设默认」 就点一下(已经是默认的卡片不显示这个按钮)

配置落到 %USERPROFILE%\.wraith\config.json密钥不会出现在日志或任何回包里,界面回读时只告诉你「已配置」,不回明文。

② 放一个 .env 到用户目录(不想开界面时用)

后端找 .env 的顺序是当前工作目录,然后是用户目录

File[] envFiles = { new File(".env"), new File(System.getProperty("user.home"), ".env") };

从开始菜单启动的 App,工作目录是安装目录不是仓库,所以仓库里那个 .env 它看不见。要走这条路,请放到:

%USERPROFILE%\.env

内容就是 KEY=VALUE,一行一条:

DEEPSEEK_API_KEY=你的key

可用的 key 名(挑你有的那家):GLM_API_KEYDEEPSEEK_API_KEYSTEP_API_KEYKIMI_API_KEYFREELLMAPI_API_KEYXFYUN_MAAS_API_KEY

cmd 里一条命令建好:

echo DEEPSEEK_API_KEY=你的key> "%USERPROFILE%\.env"
type "%USERPROFILE%\.env"

> 前面不要留空格 —— cmd 会把空格一起写进值里。写完 type 一下确认。

配好后重启 npm run dev。控制台不再出现「尚未配置任何模型」、首页也不再显示引导条,就说明装上了。

③ 环境变量(cmd 与 PowerShell 写法完全不同)

⚠ README 快速开始里写的是 export GLM_API_KEY=... —— 那是 bash 语法,在 PowerShell 和 cmd 里都不存在。Windows 上要这样写:

PowerShell

# 只对当前会话有效(关掉窗口就没了)
$env:GLM_API_KEY = "你的key"

# 永久写入当前用户(新开的进程才读得到,已开的 App 要重启)
[Environment]::SetEnvironmentVariable('GLM_API_KEY', '你的key', 'User')

cmd

REM 只对当前窗口有效。等号两边不要空格 —— 写成 set K = v 会连空格一起存进变量名
set GLM_API_KEY=你的key

REM 永久写入当前用户(新开的窗口才读得到)
setx GLM_API_KEY "你的key"

注意环境变量是进程启动时读的。从开始菜单启动的 App 不会看到你之后才设的变量 —— 设完要重启 App。这也是为什么推荐走 ① 图形界面:改完即时生效,不牵扯进程环境。


3. 发第一条消息

回到对话页,首页会给你四组入口:了解这个项目 / 改进代码 / 排查问题 / 写文档。点一组会展开三条具体建议,每条都是一句完整、当场能跑的话,点一下填进输入框,回车发送。

想直接打字也行 —— 那四组只是起点,不是限制。


4. 认识界面

左侧栏

顶部是项目会话列表;中间是工具,分三组:

里面有什么 干嘛的
配置 MCP、Provider 配置、技能 装东西、接东西
运行 自动化、IM 网关、后台任务 让它替你跑
观察 记忆、快照、安全、浏览器、代码检索 看它做了什么

最底下是账户行(头像 + 昵称),点进去是整套设置(我 / 界面 / 宠物 / 关于)。

「后台任务」在跑的时候,右边会显示正在运行的条数;工具组收起时这个数字会冒到「工具」标题上,不会因为收起就看不见。

面板里每条记录行尾的按钮按状态给:

状态 有什么键
运行中 / 排队中 ✕ 取消(此时不给删 —— worker 还在改你的文件,删了行它照样在跑,只是你看不见了)
失败 / 已取消 ⟲ 重试 + 🗑 删除
已完成 🗑 删除

重试 = 用同样的指令新建一条,并把原来那条删掉,列表里只留最新的。 (反过来说,如果重试提交本身失败了,原记录会原地不动 —— 否则你的指令就跟着一起没了。)

顶栏那个盾牌

右上角有个小盾,它同时表达两件事:有没有沙箱、以及网络出口开没开。三态:

图标 墨色 悬停文案 含义
打勾盾 浅墨 沙箱: AppContainer · 已断网 正常态。命令关在 AppContainer 里,断网 + 写围栏
半盾 沙箱: AppContainer · 已放行网络 你在安全面板打开了「命令沙箱联网」。文件系统仍被关着,只是网络出口开了
警告盾 沙箱未启用 AppContainer 没起来 —— 要处理的异常

盾会跟着面板里的开关实时变:拨「命令沙箱联网」,松手就能看见打勾盾变成橙色半盾。 (这在 2026-08-02 之前是坏的:盾只在开机时读过一次状态,且压根不看联网位, 所以拨开关顶栏纹丝不动。用户报的「不管有没有开启沙箱护盾始终不变」就是它。)

红盾时点盾牌进「安全」面板会显示具体缺哪一项,或者命令行跑 wraith sandbox doctor 逐项体检。详见 6.5 命令沙箱

沙箱没起来时命令照常执行(仍受命令黑名单和 HITL 审批保护),只是没有围栏——不会把你卡住。

顶栏右上角三个键

Windows 主窗是无边框的,最小化 / 最大化 / 关闭是 wraith 自绘的(位置和行为跟 Windows 一致,字形是 wraith 的单色墨,关闭键悬停变红)。双击顶栏空白处也能最大化 / 还原,拖顶栏空白处移动窗口。

mac 那种半透明磨砂侧栏在 Windows 上是实色,这是有意设计,不是缺样式。


5. 代码更新后怎么重新跑

git pull

然后按「改了什么」决定重跑到哪一步 —— 不是每次都要全套。最容易踩的是第一行:

改动落在 要做什么 不做会怎样
Java 后端src/main/java/**src/main/resources/** 重跑 dev-win.ps1(装了短命令则一句 wraith-install)+ 重启 App ⚠️ 改动完全不生效,且没有任何报错。dev 态起的是 %USERPROFILE%\.wraith\wraith.jar,不是 target\ 里那个 —— 光跑 mvn package 等于没改
渲染层desktop/src/renderer/** 什么都不用做 — 热更新,存盘即刷新
主进程 / preloaddesktop/src/main/**desktop/src/preload/** 完全重启 App(Ctrl+C 后重跑 npm run dev window.wraith.X is not a function —— preload 不热更新,这是陈旧进程,不是代码 bug
desktop/package.json 依赖变动 npm install --legacy-peer-deps 起不来或缺模块
已装的安装包(路线 B) 重新 npm run dist:win 再装一次 装好的 App 用的是打包时的 jar,git pull 对它没有任何影响

拿不准改了哪些,看一眼:

git log --oneline -10
git diff --stat HEAD@{1} HEAD      # 上一次 pull 到现在动了哪些文件

最常用的一条(改了 Java 之后)

# 仓库根
git pull
powershell -ExecutionPolicy Bypass -File desktop\scripts\dev-win.ps1
# 然后到跑着 npm run dev 的窗口 Ctrl+C,重新 npm run dev
cd desktop
npm run dev

确认新 jar 真的装上了 —— 时间戳应该是刚才:

dir "%USERPROFILE%\.wraith\wraith.jar"

这个坑值得单独记住dev-win.ps1 干的事是「mvn package + 把产物拷到 %USERPROFILE%\.wraith\wraith.jar」。桌面 dev 态的主进程固定从那个位置 spawn('java', ['-jar', ...])。所以只跑 mvn package 不拷贝,App 会继续用旧 jar —— 表现是你明明改了后端却毫无变化,或者调用新加的 RPC 报「method not found」。

全部推倒重来

改动很多、或者状态混乱到说不清时:

git pull
cd desktop
rmdir /s /q node_modules            # cmd;PowerShell 用 Remove-Item -Recurse -Force node_modules
npm install --legacy-peer-deps
cd ..
powershell -ExecutionPolicy Bypass -File desktop\scripts\dev-win.ps1
cd desktop
npm run dev

配置和会话都在 %USERPROFILE%\.wraith\ 里,不会被上面这套清掉。真想连配置一起重置才动那个目录。


6. 出问题时

症状 最可能的原因 怎么办
无法将"wraith"项识别为 cmdlet、函数、脚本文件或可运行程序的名称 没装短命令,或装了但没新开终端 见下方「wraith 不是内部或外部命令」
git clonessh: connect to host github.com port 22: Connection refused 用了 SSH 形式(git@github.com:),而 22 端口被网络挡了(公司网/校园网/部分 ISP 常见);且全新机器也还没配 SSH 密钥 本仓库是公开的,直接用 HTTPS:git clone https://github.com/JavaLyHn/wraith.git,零认证配置。非要用 SSH 就走 443 通道,见下
装的时候被 SmartScreen 拦 安装包未签名 「更多信息」→「仍要运行」
App 起来了但显示后端未连接 走的是开发态npm run dev),主进程 spawn('java', …) 找不到 java 确认 javaGUI 进程的 PATH 里 —— GUI 应用不继承登录 shell 的 PATH,这是 Windows 上的经典坑。装好的 App 用捆绑 JRE,不该出这个问题
控制台刷 app-server: 未找到可用 API Key + 满屏 Backend not connected 跑的是旧 jar。 这是已修复的首次运行死锁 —— 旧版后端没 key 就 System.exit(1),后面每个 IPC 都是连带反应 重跑 dev-win.ps1 再重启 App(第 5 节)。新版会打「尚未配置任何模型,已以「无模型」状态启动」并照常服务
改了 Java 却毫无变化 / 调新 RPC 报 method not found 只跑了 mvn package,没把 jar 拷到 %USERPROFILE%\.wraith\wraith.jar 重跑 dev-win.ps1 再重启 App —— 见第 5 节,这是本项目最容易踩的一个坑
window.wraith.X is not a function preload 不热更新,这是陈旧进程 完全重启 App(Ctrl+C 后重跑 npm run dev),不是代码 bug
首页显示「还没有配置模型」 正常的全新状态 点「去配置」填一个 API Key,保存即可用,不用重启
发消息报没有 API Key 配了但没生效 回第 2 节 ①;若卡片上有设默认就点一下
设了环境变量但 App 不认 环境变量是进程启动时读的 重启 App;或直接改用图形界面配
npm install ERESOLVE 失败 react peer 冲突 必须带 --legacy-peer-deps
加 MCP server 报 Cannot run program "npx" / CreateProcess error=2 两个原因共用同一句错:① 机器上没装 Node(Windows 不自带,安装包也不含);② Node 有,但 Windows 上 npx 实际是 npx.cmdCreateProcess 不做 PATHEXT 补全 where.exe npx 分诊:找不到 = ①,去装 Node 或改用 HTTP transport;列出两行 = ②,已修复,重跑 wraith-install 即可。见下方「加 MCP server 报 …」
起来第一行是 ?? 终端不支持 ANSI + 方向键/Tab 补全不管用 三个问题混在一句里:① ?? 是 GBK 表示不了 emoji;② 「不支持 ANSI」这句话本身是错的(下一行就是带颜色的);③ 真正的损失是 JLine 降级成 DumbTerminal 后没有 raw mode,行编辑全失灵 先跑 wraith terminal doctor(新增),它会打出 JLine 实际拿到什么终端、哪个 provider 失败、为什么失败。①② 已修;③ 看诊断里的 jni 失败原因。见下方「终端提示「不支持 ANSI」」
加 MCP server 报 Cannot run program "uvx" uvx 不属于 Node —— 它是 uv(Python 生态的包管理器)自带的命令,装 Node 不会带来它。推荐清单 10 项里只有 Fetch / Git / Time 这 3 项用它 where.exe uvx 分诊:找不到 = 装 uv(winget install --id=astral-sh.uv -e,或官方脚本),或干脆只用走 npx 的另外 7 项;能找到 = wraith 继承的是旧 PATH重启 wraith。见下方「加 MCP server 报 Cannot run program "uvx"
建代码索引 / 语义检索报 Failed to connect to localhost/[0:0:0:0:0:0:0:1]:11434 本机 embedding 后端(ollama)没装或没在跑。那串 IPv6 是障眼法 —— Java 先试的是 127.0.0.1,真正的意思是那个端口上没人监听 where.exe ollama 分诊:找不到 = 没装(内置工具里只有 search_code 依赖它,可以装、可以改用云端 embedding、也可以干脆不建索引);能找到 = 服务没起,从开始菜单启动 Ollama 或跑 ollama serve。见下方「代码索引报连不上 11434」
npm install 报错末尾有「Log files were not written ... _logs npm 缓存目录不可用,与项目无关。连日志都落不下就是这个病的指纹,不管上面报 EPERM 还是 ENOENT 见下方「npm 缓存目录不可用」——先 npm config get cache
EPERM ... mkdir '<某盘>\...\_cacache\...' 缓存目录存在但不可写。常见于把 npm 缓存搬到 Node 安装盘(如 E:\nodejs\node_cache),该目录归 Administrators 同上,把 cache 改到 %LOCALAPPDATA%
ENOENT ... mkdir '<项目路径>\$env:...\_cacache\tmp' 缓存路径不存在,且被拼在了项目目录后 → 存进 .npmrc 的是个相对路径 在 cmd 里跑了 PowerShell 写法 "$env:LOCALAPPDATA\..."。改用 "%LOCALAPPDATA%\...",并删掉误建的怪目录
npm warn cleanup ... rmdir 'node_modules\...' / npm warn tar TAR_ENTRY_ERROR ... 都是次生现象不是病因 —— 安装中途挂了,回滚删不掉半成品 / 解压到一半断了 别对着它排查。看 npm error 那几行的 path,解决后删干净 node_modules 重装
npm error path ...\node_modules\electron + RequestError: unable to verify the first certificate npm 包已下完,卡在 electron postinstall 下载 Electron 二进制(约 100MB,不走 registry,直连 GitHub Releases)。TLS 证书链验证失败,通常是杀软/企业网关拆 HTTPS 见下方「Electron 二进制下载失败」——先设 ELECTRON_MIRROR
每轮都刷 pre-turn 快照失败 / post-turn 快照失败,且重启也不好 Side-Git 里留了一把死锁(index.lock)。某个进程死在 git add 中途就会留下它 —— 而在修好之前没有恢复路径,之后每一轮、每一次重启都撞同一把锁 已修:超过 60 秒没人动过的锁会被自动清掉并重试。跑新 jar 即可,不必手动删。仍报错的话看提示里的 cause 链——那已经不是锁的问题了
快照提示被挤进 ▰▱▱… 1% 那一行,尾巴还缺一截 活动面板有自己的 250ms 重绘线程,提示以前直接写 stderr,撞进了它正在写的那行 已修:提示改走面板同一个出口,插在面板上方
「用应用打开」找不到编辑器 只按已知安装路径探测 见下方已知限制
文件操作偶发 AccessDeniedException 杀软 / 索引器短暂占用目标文件 已内置 5 次有界重试(20/40/60/80ms)。若仍失败请记下报错栈 —— 那说明占用超过 200ms,是需要调大退避的真实信号,不要当 flake 重跑了事

wraith 不是内部或外部命令

wraith : 无法将"wraith"项识别为 cmdlet、函数、脚本文件或可运行程序的名称。

wraith / wraith -d / wraith-install要装一次的短命令,不是 clone 下来就有。按顺序查:

① 装过没有?仓库根(不是 desktop\ 子目录)跑:

cd D:\wraith                # 仓库根
powershell -ExecutionPolicy Bypass -File scripts\windows\wraith-install.ps1

结尾应打印 已把 ...\scripts\windows 加入用户 PATH

② 新开终端了吗? —— 最常见的原因。PATH 是进程启动时读的,装完的那个窗口读不到。 关掉重开一个 PowerShell,再敲 wraith -h

③ PATH 到底进去没有? 新终端里:

PowerShell

$env:Path -split ';' | Select-String wraith
where.exe wraith

cmd

echo %PATH%
where.exe wraith

第一条应列出 ...\scripts\windows,第二条应指到 wraith.cmd。都空 = 装的那步没成功,看 ① 的输出有没有报错。

④ 不想装也行。 短命令只是省事,等价的长写法一直可用:

短命令 等价长写法
wraith java -jar %USERPROFILE%\.wraith\wraith.jar
wraith -d cd desktop + npm run dev
wraith-install powershell -ExecutionPolicy Bypass -File desktop\scripts\dev-win.ps1

wraith: 还没安装 jar 是另一回事——PATH 好了,但 %USERPROFILE%\.wraith\wraith.jar 不在。 跑一次 wraith-install 补上(它构建后端并装到那个位置)。

跑了 wraith-install 却还是报「还没安装 jar」 —— 那是脚本自己的 bug,不是你的操作问题, 见下一节。


短命令输出乱码 / wraith-install 静默空转(已修)

一句话指纹:中文提示变成 鑻ヨ繛 wraith-install 閮芥壘涓嶅埌;或者报一句 'app-server' 不是内部或外部命令 —— 一个你根本没敲过的子命令; 或者 wraith-install 看着「跑完了」(退出码 0、没有任何报错),但 jar 从来没出现。

根因cmd.exeOEM 码页(中文 Windows = GBK/936)逐字节解析 .cmd, 对双字节字符用的是「见到 lead byte 就盲目前进 2 字节」。UTF-8 的中文是三字节, 被错拆成 GBK 序列后行尾常剩下一个孤立 lead byte(0x81–0xFE), 它会把紧随其后的那一个字节吞掉。可被吞的范围里有两个要命的东西:

被吞的字节 后果
0x0A(换行) 相邻两行被并成一条命令
0x5E^,批处理转义符) ^( 变成裸 (,括号块提前闭合或永不闭合

实测(字节级模拟,已写成测试)

文件 物理行数 cmd.exe 眼里 后果
wraith-install.cmd 6 4 powershell -File wraith-install.ps1 整行被并进上一条 rem 注释 → 安装什么都没做,退出码还是 0
wraith.cmd 72 66 另有 42 个 ASCII 字节被吞,包含 :usage 段里 echo wraith app-server …^( 的那个 ^

所以症状链是闭合的:wraith-install 静默空转 → jar 从未构建 → wraith 报「还没安装 jar」, 而那句提示自己又是乱码。('app-server' 不是内部或外部命令 这一条落在被打乱的解析里哪一步, 只能在真 cmd.exe 上复现确认;能确定的是 app-server 这个词在整个启动器里只出现在 rem 注释和 :usage 两处,两处都被上表的破坏波及。)

修法(消灭整个类别,不是补一处转义):

  1. .cmd 只留纯 ASCII,所有中文(注释与用户可见文案)搬进 scripts\windows\wraith-msg.ps1 —— .ps1 带 UTF-8 BOM,PowerShell 会正确按 UTF-8 读(见下方「BOM」那一条)。
  2. .cmd 强制 CRLF.gitattributes-text 保证字节原样进出)。 CR 是挡在换行前面的「牺牲字节」:孤立 lead byte 会先吃掉它,换行因此存活。
  3. 去掉多行 (...) 括号块,改用 goto —— 括号块正是需要 ^ 转义的地方,而 ^ 会被吞。
  4. rem 注释里不再出现 | / & / 尖括号:rem 屏蔽管道与重定向 (rem note > f 会真的建出一个文件)。

怎么确认自己这份是修过的

# 应该没有任何输出(纯 ASCII);有输出说明是旧版
Select-String -Path scripts\windows\*.cmd -Pattern '[^\x00-\x7F]' -Encoding Byte
# cmd 里没有等价的一行写法,用 findstr 只能近似:
#   findstr /R /C:"[^ -~]" scripts\windows\*.cmd

约束由 WindowsLauncherScriptTest.cmd 纯 ASCII + CRLF + 委派契约)与 PowerShellBomTest.ps1 必须带 BOM)钉住,任何人往 .cmd 里加一句中文都会让测试变红。


npm 缓存目录不可用(EPERM / ENOENT)

一句话指纹:报错末尾出现

npm error Log files were not written due to an error writing to the directory: <某路径>\_logs

连日志都落不下,说明整个缓存目录用不了。不管上面报的是 EPERM 还是 ENOENT,都是同一类病,直接查 npm config get cache

两种变体:

报错 含义 典型成因
EPERM ... mkdir '<某盘>\...\_cacache\...' 目录存在但不可写 把 npm 缓存搬到了 Node 安装盘(如 E:\nodejs\node_cache),该目录归 Administrators,普通终端只能读
ENOENT ... mkdir '<项目路径>\$env:...\_cacache\tmp' 缓存路径根本不存在 —— 注意它被拼在了项目目录后面,说明存进去的是个相对路径 cmd 里执行了 PowerShell 写法 npm config set cache "$env:LOCALAPPDATA\npm-cache"。cmd 不展开 $env:,字面量被原样写进 .npmrc

别对着这两类噪音排查,它们都是安装中断后的次生现象:

  • npm warn cleanup ... EPERM ... rmdir node_modules\... —— npm 想回滚删半成品,删不动
  • npm warn tar TAR_ENTRY_ERROR ENOENT ... —— 解压到一半断了

真正的死因永远在 npm error 那几行的 path

修复(PowerShell)

# ① 看缓存指向哪
npm config get cache

# ② 改到用户目录(必定有写权限;写入 %USERPROFILE%\.npmrc,不需要管理员)
#    ⚠ 这一行**只能在 PowerShell 里跑**。cmd 里要写成:
#      npm config set cache "%LOCALAPPDATA%\npm-cache"
#    在 cmd 里照抄下面这句不会报错,而是真的建一个叫 $env:LOCALAPPDATA 的目录
npm config set cache "$env:LOCALAPPDATA\npm-cache"

# ③ ⚠ 必须验证 —— 输出要是以盘符开头的绝对路径
npm config get cache
#   ✅ C:\Users\<你>\AppData\Local\npm-cache
#   ❌ 含 $env: 或 %...%,或不以盘符开头 → 别往下走,回 ② 用对应 shell 的写法

# ④ 若之前误建过怪目录,删掉(它就在项目里,名字真的叫 $env:LOCALAPPDATA)
cd D:\wraith\desktop
Remove-Item -Recurse -Force '$env:LOCALAPPDATA' -ErrorAction SilentlyContinue

# ⑤ 清掉不一致的半成品
Remove-Item -Recurse -Force node_modules

# ⑥ 重装
npm install --legacy-peer-deps

④ 里的单引号不能少 —— PowerShell 双引号会把 $env:LOCALAPPDATA 展开,单引号才取字面量。

修复(cmd)

提示符是 D:\...> 而非 PS D:\...> 就用这套。注意 ② 用的是 %...% 不是 $env:

npm config get cache
npm config set cache "%LOCALAPPDATA%\npm-cache"
npm config get cache

cd /d D:\wraith\desktop
rmdir /s /q "$env:LOCALAPPDATA"
rmdir /s /q node_modules

npm install --legacy-peer-deps

加 MCP server 报 Cannot run program "npx"

典型报错:

连接失败: Cannot run program "npx" (in directory "C:\Users\你"):
CreateProcess error=2, 系统找不到指定的文件。

⚠️ 这一句错有两个完全不同的原因,先分诊再动手。

后端解析不到 npx 时会把原名原样交给操作系统,让它报自己的错——所以「机器上压根没有 Node」和「Node 有但 Windows 不补扩展名」报出来的是同一句话。 按错的那个原因去修,会一路走进死胡同。

一条命令就能分开:

where.exe npx
where.exe npx 的输出 说明 去看
信息: 用提供的模式无法找到文件。 机器上没有 Node 情况 A
列出 ...\npx...\npx.cmd 两行 Node 有,是扩展名补全的问题 情况 B

情况 A:机器上根本没有 Node(where.exe npx 找不到)

🔎 「我根本没加过 MCP server,为什么会报这个?」

因为有一份默认配置是自动创建的。交互式 CLI(wraith / java -jar …)首次启动时, 若 %USERPROFILE%\.wraith\mcp.json 不存在,会自动写入一份默认的 chrome-devtools 配置, 而它用的正是 npx

{ "mcpServers": { "chrome-devtools": {
    "command": "npx", "args": ["-y", "chrome-devtools-mcp@latest", "--isolated=true"] } } }

所以没装 Node 的机器,什么都没做就会看到这条错。 (桌面端自己不创建这份文件,但只要你跑过一次 CLI,它就在那儿了,桌面端也会读到。)

不想用浏览器 MCP 的话,关掉它最省事,三种方式任选:

方式 怎么做
桌面面板 「MCP」面板选中 chrome-devtools → 点**「停用」**
CLI /mcp disable chrome-devtools
改文件 %USERPROFILE%\.wraith\mcp.json 里那一项删掉,或整个换成 { "mcpServers": {} }

关掉不影响 wraith 的任何内置能力——38 个内置工具与 MCP 无关。

Windows 不自带 Node,也不自带 npx。 而且——

装了 wraith 安装包 ≠ 有 Node。 安装包捆绑的是 JRE(所以不用装 Java)和后端 jar,不含 Node。 第 1.1 节那句「路线 B 装完之后不需要 Java」说的只是 Java。 只要你要用 npx 起 MCP server,就得自己装 Node——这是运行时依赖,不是构建时依赖。

三条路,按省事程度排:

A1. 装 Node(最直接)

nodejs.org 下 LTS 安装包,一路下一步。装完新开一个终端(旧终端读不到新 PATH):

node -v      # 期望 v18+
where.exe npx    # 期望列出 npx 与 npx.cmd

然后回 MCP 面板重新连一次即可,wraith 侧不用改任何配置。

A2. 换成不需要 Node 的 MCP server

npx 只是 Node 生态 MCP server 的启动方式。别的形态不需要它:

server 形态 「命令(stdio)」填什么 需要什么
Python(uv 生态) uvx uv,不需要 Node
独立可执行文件 那个 .exe 的完整路径 什么都不需要
Node,但已全局安装 where.exe <命令> 查到的 .cmd 完整路径 仍需 Node

A3. 换用 HTTP 远程 server(本机什么运行时都不用装)

wraith 的 MCP 支持两种 transport,npx 那条只是其中之一:

  • stdio —— 把 server 当子进程拉起(需要本机有对应运行时)
  • Streamable HTTP —— 连一个远程 server(本机什么都不用装

⚠️ 桌面「MCP」面板目前只能加 stdio 的(表单里只有「命令(stdio)」,没有 URL 字段;而且保存时会主动清掉 url——后端要求 transport 二选一)。HTTP server 得手写配置文件

%USERPROFILE%\.wraith\mcp.json          用户级(所有项目)
<项目根>\.wraith\mcp.json                项目级
{
  "mcpServers": {
    "my-remote": {
      "url": "https://example.com/mcp",
      "headers": { "Authorization": "Bearer ${MY_TOKEN}" }
    }
  }
}

两个要点:

  • commandurl 只能有一个。 都写或都不写,启动时会直接报 MCP server 必须且只能配置 command 或 url
  • ${VAR} 按环境变量展开,密钥不必明文落盘(另支持 ${HOME}${PROJECT_DIR})。 但变量没设不是留空,是直接失败MCP 配置引用了未设置的环境变量: MY_TOKEN

改完重启后端才生效(见第 5 节)。

三条路都不想走也没关系:MCP 是可选能力。不加任何 MCP server,wraith 的 38 个内置工具(读写文件 / 执行命令 / 代码检索 / 联网 / 快照回滚等)照常可用。


情况 B:Node 装了、npx 在终端里也能敲,但后端起不来

原因是 Windows 与 Linux/macOS 的一个根本差异:

Linux / macOS Windows
npx 实际是什么 npx(带 shebang 的脚本) npx.cmd(批处理)
谁负责补扩展名 execvp 查 PATH,名字就叫 npx shellPATHEXT 补;CreateProcess 不管

Java 用 CreateProcess 直接拉起进程,中间没有 shell —— 于是「找 npx」在 Windows 上必然落空。注意错误码是 error=2(文件未找到),不是格式错误,这正说明卡在找不到而不是跑不动。

已修复:后端现在会按 PATH × PATHEXTnpx 解析成 npx.cmd 的完整路径再启动。拉最新代码并重跑 wraith-install(或 dev-win.ps1)即可 —— 改的是 Java,只 git pull 不生效,见第 5 节。

手动绕过(不想更新、或者用的是旧包):把「命令(stdio)」直接填成完整路径。

where.exe npx        # 找出真身,通常有 npx 和 npx.cmd 两行

把输出里 .cmd 结尾的那一行整条粘进「命令(stdio)」,参数不变:

命令(stdio)    C:\Program Files\nodejs\npx.cmd
参数           -y
               chrome-devtools-mcp@latest
               --isolated=true

同类问题也会出现在别的 npm 系命令上(pnpmyarnbunx…)—— 它们在 Windows 上一律是 .cmd。修复对它们同样生效。


情况 C:npx 能解析了,MCP server 还是起不来

chrome-devtools 为例(它是内建的那个,不需要你配就在)。原生 Windows 是官方支持的官方 troubleshooting 明确说 WSL 下 Chrome 反而起不来,建议用原生 Windows / PowerShell), 所以起不来一定有具体原因。三个常见的:

现象 原因 处理
MCP error -32000: Connection closed server 进程起来了又立刻死 看面板的**「日志」**页签,里面是 server 的 stderr 原文
加完之后一直「启动中…」,约一分钟后失败 首次运行 npx -y 要下载整个包,默认 60 秒初始化超时不够 见下方「调超时」
日志里报找不到 Chrome Chrome 没装,或装在非标准路径 装 Chrome;仍不行就按官方建议在参数里加一行 --executablePath=C:\Program Files\Google\Chrome\Application\chrome.exe

调超时(首次装包慢的话):

# PowerShell
$env:WRAITH_MCP_INITIALIZE_TIMEOUT_SECONDS = "180"
npm run dev
REM cmd
set WRAITH_MCP_INITIALIZE_TIMEOUT_SECONDS=180
npm run dev

也可以先在终端手动跑一次,把包预热到 npx 缓存里,之后就快了:

npx -y chrome-devtools-mcp@latest --version

官方给的两个 Windows 解法,wraith 已经自动做了第二个(用 npx 的绝对路径, 扩展名可能是 .cmd / .bat / .exe)。所以正常情况下你不需要把命令改成 cmd /c npx … 那种写法。

⚠️ 顺带一提,不建议手动改成 cmd /c —— 那样参数会经过 cmd 再解析一层, 而 MCP 配置可以来自项目里的 .wraith\mcp.json(也就是从别人仓库 clone 来的)。 参数里一个 & 就能变成命令注入。走绝对路径没有这一层。

工具数量对不对得上? 工具列表是 server 启动后自己报的(tools/list), 所以要么全有、要么一个没有,不存在少几个。两台机器数量不同只有一种可能: @latest 解析到了不同版本(各自 npx 缓存不同)。想完全对齐就把 @latest 换成固定版本号。


情况 D:能起来,但每次开机都要等很久

这是最常被当成 bug 的一类,其实全部时间都花在 wraith 之外。一次冷启动依次是:

npx 解析 npx.cmd 绝对路径     ← wraith 做的,毫秒级
  → npm 去 registry 问 chrome-devtools-mcp 的 latest 是哪个版本   ← 网络
  → 缓存里没有就下整个包(含 puppeteer-core,几十 MB)              ← 网络
  → 起 Node 进程 + 拉起一个全新的 Chrome(--isolated=true 每次新 profile)  ← 磁盘/CPU
  → MCP initialize 握手 + tools/list

@latest 意味着即使包已经在缓存里,npm 每次仍要去 registry 问一次「最新是谁」。 国内直连 registry.npmjs.org 的话,这一问经常就是十几秒起步。

按收益从大到小:

做法 命令 说明
① 换 npm 镜像 npm config set registry https://registry.npmmirror.com 国内收益最大,且对所有 npx 系 server 都生效
② 钉死版本 ~\.wraith\mcp.json 写同名条目,args 用 chrome-devtools-mcp@0.23.0 跳过 dist-tag 解析;顺带解决两台机器工具数不一致
③ 复用已开的 Chrome args 换成 --browser-url=http://127.0.0.1:9222--autoConnect 省掉「每次拉一个全新 Chrome」;代价是 Agent 会驱动你真实登录态的浏览器
④ 不需要浏览器就关掉 WRAITH_MCP_BUILTIN_BROWSER=off 启动瞬间干净

②③ 的写法(用户级 mcp.json 里的同名条目会完全覆盖内建项):

{
  "mcpServers": {
    "chrome-devtools": {
      "command": "npx",
      "args": ["-y", "chrome-devtools-mcp@0.23.0", "--browser-url=http://127.0.0.1:9222"]
    }
  }
}

启动慢不阻塞对话。 MCP server 在后台线程并行启动(最多 8 个并发), 每个 server 各自就绪、各自注册工具 —— 慢的那个只是自己慢, 不会拖住聊天、也不会拖住别的 server。面板上它停在「启动中」,好了自己会变。


终端提示「不支持 ANSI」/ 输入命令不管用 / emoji 变成 ??

一句话指纹wraith 起来后第一行是

?? 终端不支持 ANSI, inline 模式回退到 plain

紧接着却是带颜色的 WRAITH 大字和青色的 Model 行;而且方向键 / Tab 补全 / 历史翻不动。

⚠️ 这一句里其实混了三个不同的问题,别一起修。

现象 真实原因 是不是 bug
?? 开头 中文 Windows 控制台码页是 GBK/936,(U+26A0) 与变体选择符不在 GBK 里,各降一个 ? 是,已修(输出自动降级为 [!] 这类 ASCII)
「不支持 ANSI」 这句话本身是错的。 判据把「JLine 拿到了 DumbTerminal」当成了「终端不解释 ANSI」,而这两件事无关 是,已修(改判据 + 改措辞)
输入命令不管用 DumbTerminal 没有 raw mode → 行编辑、Tab 补全、历史、Ctrl-R 全部失灵。这才是真正的功能损失 根因在 JLine provider,见下
输入中文后回显成 ???(输入 nihao 正常) 同一个根因:DumbTerminal 读输入走的是控制台码页,中文被读坏。ASCII 正常、中文坏就是这个病的指纹 修好 jni provider 一并解决(原生终端用 ReadConsoleW 读宽字符,不经过码页)

为什么 Windows 上容易降级:JLine 4.0 的 provider 默认顺序是 ffm,jni,exec,而

provider 状况
ffm 依赖用的是 jline:4.0.0:jdk11 classifier,里头 impl/ffm 一个 class 都没有(实测;对照 jni 15 个、exec 6 个)→ 永远不可用,与运行时 JDK 版本无关。已在代码里显式关掉,不再产生噪音日志
exec 探测 TTY 要跑 test -t,而 Windows 没有 test.exe(实测报 Cannot run program "test"
jni 自带原生库(jlinenative.dll,x86/x64/arm64 都在 jar 里)→ Windows 上唯一的路

所以 jni 一失败就只剩 dumb。

已确证的一个 jni 失败原因:native access 没启用

用户实测的 doctor 报告里是这一行:

Unable to load jni provider: ... UnsupportedOperationException:
  Native access is not enabled for the current module: unnamed module @2d8e6db6

JLine 的 JniTerminalProvider 构造器里有个前置检查:反射调 Module.isNativeAccessEnabled(), 返回 false 就直接抛,于是 Windows 上唯一可用的 provider 加载不了。

那个方法是 JDK 22+ 才有的,但有些发行版把它回移到了更早版本。 JLine 的源码注释只提了 GraalVM,而用户实测那台是 java.vendor = Oracle Corporation / java.vm.name = Java HotSpot(TM) 64-Bit Server VM —— Oracle JDK 21 自己也回移了。所以「哪个发行版会回移」不可靠,只能实测 (这就是 wraith terminal doctor 必须打 java.vendor / java.vm.name 的理由)。

于是一台 JDK 21 会落进最难受的中间地带:

情况
Module.isNativeAccessEnabled() (GraalVM 回移)→ 检查会执行
jar manifest 的 Enable-Native-Access: ALL-UNNAMED 不认(那是 JDK 24+ 才读的)→ 检查结果是 false

结果就是「检查生效但授权手段不生效」。(对照:mac 上 JDK 26 走 java -jar 时 manifest 生效, isNativeAccessEnabled() 为 true,jni 正常 —— 这就是同一份代码在 mac 上没事的原因。)

修法:启动时加 --enable-native-access=ALL-UNNAMED

# 用短命令的话,重装一次就好(wraith.cmd 已会自动探测并加上)
powershell -ExecutionPolicy Bypass -File scripts\windows\wraith-install.ps1

# 手动跑 jar 时自己加
java --enable-native-access=ALL-UNNAMED -jar %USERPROFILE%\.wraith\wraith.jar

为什么不无条件加:普通 OpenJDK 21 不认这个选项,加了会 Unrecognized option 直接起不来。 所以 wraith.cmd探测一次(跑一次 java --enable-native-access=ALL-UNNAMED -version), 把答案缓存到 %USERPROFILE%\.wraith\java-flags.txt,之后启动零开销。 换过 JDK 就删掉那个文件(或重跑 wraith-install,它会自动清)。

改完再跑一次 wraith terminal doctornative access 一行应该变成 [ok] 已启用原生终端控制 也应该变成 [ok] 有 —— 那时方向键 / Tab 补全 / 历史就都回来了。

先跑诊断(新增子命令,对标 wraith sandbox doctor):

wraith terminal doctor

它会打出运行环境、相关环境变量、JLine 实际拿到的终端与 provider、四项能力判定,以及 JLine 内部日志 —— jni 到底为什么失败就在那几行里。示例(mac 上管道环境的输出):

── JLine 拿到的终端 ─────────────────────────────────
  实现类           org.jline.terminal.impl.DumbTerminal
  type             dumb
  provider 顺序    jni,exec

── 能力判定 ─────────────────────────────────────────
  原生终端控制     ❌ 无   ← 行编辑/补全/历史/方向键会失灵
  ANSI 转义序列    ✅ 有   ← dumb 但终端会解释 ANSI,颜色与面板照常
  inline 渲染器    ✅ 有   (false 时回退 PlainRenderer)
  常驻状态栏       ❌ 无   ← dumb 的尺寸不可信,scroll region 会画错位置,故关闭

此前这些信息完全拿不到:代码里写的是 TerminalBuilder...dumb(true),而 JLine 打降级日志的 条件是 if (!forceDumb && dumb == null) —— 显式传了 dumb(true) 就一行都不打。 现在构建期间会临时接住 org.jline 的日志再恢复。

逃生阀wraith terminal doctor 结尾也会列出来):

开关 作用
WRAITH_FORCE_ANSI=true 强制认定终端支持 ANSI。值必须是 true,写 1 不生效(走 Boolean.parseBoolean
WRAITH_RENDERER=plain 关掉 inline 渲染,最朴素最不容易出问题
WRAITH_NO_STATUSBAR=true 只关常驻状态栏
-Dorg.jline.terminal.providers=jni 手动指定 provider 顺序(设了就完全尊重,代码不再自动收窄)

dumb 下现在保留什么、放弃什么:认了 ANSI 就保留颜色、思考面板、diff、工具块折叠; 但不开常驻状态栏 —— DumbTerminal.getSize() 来自 env COLUMNS/LINES,没有就是 (80,24) 兜底, 按错的行数设 scroll region 会把状态栏画到屏幕中间或裁掉正文,那比没有状态栏糟得多。


每轮都报「快照失败」,重启也不好

一句话指纹:每次发消息都夹两行,且换终端、重启机器都一样

[!] pre-turn 快照失败:JGitInternalException: Exception caught during execution of add command
  ← LockFailedException: Cannot lock C:\Users\你\.wraith\snapshots\...\.git\index.

先解释快照是什么:wraith 每轮对话前后各存一张「Side-Git」快照,用的是一个完全独立的 git 仓库 —— gitDir%USERPROFILE%\.wraith\snapshots\<项目哈希>\,而 worktree 指向你的项目根。 所以它不碰你自己的 .git:不占你的 index、不产生你能看见的 commit、git status 里什么都不多。 /snapshot 看列表,/restore N 回滚到最近第 N 轮之前。

为什么会"全都"失败:写入线程是 daemon 线程,JVM 一退就没了,finally 里的解锁不会跑; 所以只要有一次进程死在 git add 中途(Ctrl+C、直接关窗口、任务管理器结束进程), index.lock 就留在那儿。而在修好之前没有任何恢复路径 —— 之后每一轮、每一次重启都撞它。

现象 真实原因 是不是 bug
一直失败,重启无效 残留的 index.lock 没人清 是,已修:超过 60 秒没人动过的锁会自动清掉并重试一次
正常退出后那一轮的收尾快照丢了 关服务时 shutdownNow() 把排队中的 post-turn 直接丢掉 是,已修:退出时最多等 3 秒让它写完
提示被挤进 ▰▱▱… 1% 那一行,尾巴缺一截 活动面板有自己的 250ms 重绘线程,提示以前直写 stderr 是,已修:改走面板同一个出口
报错第一行只有 Exception caught during execution of add command 那是 JGit 的顶层消息,什么信息都没有,真原因在 cause 里 是,已修(现在打完整 cause 链 + 可行动建议)

跑新 jar 就好,不必手动删文件。 若清完锁仍失败,提示会明确写「陈旧的锁已经自动清掉了」—— 那就说明问题不在锁上,看 cause 链原文。最常见的剩余原因是同一个项目上开着两个 wraith (比如桌面端和 CLI 同时跑),关掉一个即可。

关掉快照有三条路,管的时间长度不同(Windows 上尤其别用环境变量那条 —— 见下):

怎么关 管多久
wraith --no-snapshot 这一次
/snapshot off(或桌面端快照面板右上角的开关按钮) 以后(写进 %USERPROFILE%\.wraith\config.json
WRAITH_SNAPSHOT_ENABLED=false 这一次,且压过上面两者
:: cmd —— 推荐用参数,不用环境变量
wraith --no-snapshot

:: cmd 里设环境变量要分两步,而且只对这个窗口有效
set WRAITH_SNAPSHOT_ENABLED=false
wraith
# PowerShell —— 同样推荐参数
wraith --no-snapshot

# PowerShell 的环境变量写法(注意与 cmd 完全不同)
$env:WRAITH_SNAPSHOT_ENABLED = "false"; wraith

⚠️ set VAR=value wraith 在 cmd 里不是「带着变量跑一次」 —— 那是 POSIX shell 的写法。 cmd 会把整串当成变量值(WRAITH_SNAPSHOT_ENABLED 被设成 false wraith), 于是变量认不出来、命令也没跑。这类差异正是 --no-snapshot 存在的理由。

其它相关开关

开关 作用
WRAITH_SNAPSHOT_STALE_LOCK_SECONDS=<秒> 多久算「死锁」,默认 60。实测一次快照最慢约 8 秒,别调得比它小
WRAITH_SNAPSHOT_EXCLUDES=a,b 追加排除目录(默认已含 target / node_modules / dist / release 等)
/snapshot status 看快照目录、保留数、排除项、最近一张
/snapshot clean 清掉当前项目的整个快照目录

代码索引报连不上 11434 / 没有 ollama 命令

典型报错(面板或 CLI):

索引失败:embedding 后端探测失败:Failed to connect to localhost/[0:0:0:0:0:0:0:1]:11434

🔎 那串 [0:0:0:0:0:0:0:1]障眼法,不是原因。Java 会先试 127.0.0.1, 这串 IPv6 回环只是最后一个尝试过的地址。真正的意思是:那个端口上没有东西在监听。

先分诊 —— 「没装」和「装了没起」修法完全不同:

where.exe ollama
输出 说明 去看
信息: 用提供的模式无法找到文件。 机器上没有 ollama 情况 A
列出 ...\ollama.exe 装了,只是服务没在跑 情况 B

⚠️ 这一步不能跳。后端给的提示里有一句「或在命令行跑 ollama serve」, 那句话假设你已经装了 —— 没装的机器照着敲只会得到 'ollama' 不是内部或外部命令,白绕一圈。


情况 A:没装 ollama —— 先想清楚要不要装

wraith 只有一个内置工具(search_code)依赖它。不需要语义检索的话,跳到「A3 不装」。

A1. 装 ollama(要本机跑、离线可用、不花钱)

ollama.com/download/windows 为准,两种装法:

# ① 官网下 OllamaSetup.exe,双击一路下一步(装完托盘会出现图标,服务自动起)
# ② 或者用 winget
winget install --id Ollama.Ollama -e

装完新开一个终端(旧终端读不到新 PATH),然后拉一个 embedding 模型 —— 这一步不能省, 装了 ollama 不等于有模型:

ollama --version
ollama pull nomic-embed-text        # wraith 的默认模型
ollama list                         # 确认列出来了
模型 维度 说明
nomic-embed-text:latest 768 wraith 的默认值,快
bge-m3:latest 1024 中文明显更好,代价是慢约 2.5 倍。索引里混中文注释/文档就选它

⚠️ 换模型必须重建索引。 维度不一样(768 ↔ 1024),拿新模型的查询向量去搜旧索引 会直接报错;维度碰巧相同而模型不同则不报错,但相关度全无意义。 桌面「代码图谱」面板的「测试连接」会替你把这种冲突指出来。

验证服务活着:

curl http://127.0.0.1:11434/api/version     # 返回 JSON 版本号,如 {"version":"0.x.y"}

或者浏览器打开 根路径 http://127.0.0.1:11434/ —— 那个页面才是显示 Ollama is running 的地方 (/api/version 给的是 JSON,两者别混)。

A2. 不装 ollama,改用云端 embedding(最省事,不占本机资源)

桌面「代码图谱」面板 → embedding 后端表单,把 provider 换掉即可:

provider 默认模型 BASE URL 注意
openai text-embedding-3-small OpenAI 兼容后端的 baseUrl 通常要带 /v1(后端直接拼 /embeddings
zhipu / glm embedding-2 同上

填完点**「测试连接」**再建索引 —— 那个按钮会当场告诉你维度、耗时,以及和现有索引兼不兼容。

配错协议最典型的一条:provider 选 openai 却填了 ollama 的地址, 于是打到 /embeddings 而 ollama 只认 /api/embeddings,回一句光秃秃的 404 page not found。 后端会替你把这条 404 翻译成「路径不存在,检查 provider 与 baseUrl 是否配套」。

A3. 干脆不用语义检索

不建索引就不会触发 embedding。agent 仍然有 grep、读写文件、跑命令等全部其余工具, 只是问「这个功能在哪实现的」时它得靠 grep 而不是向量检索。


情况 B:装了 ollama,但服务没在跑

# 从开始菜单启动 Ollama(托盘出现图标即可),或者:
ollama serve

ollama serve 会占住那个终端窗口,别关。跑完用上面那条 curl 验一下。

端口不是 11434 的话(改过配置或被占用),把面板里的 BASE URL 一起改掉 —— 后端提示里的验证命令用的是你配置的那个端口,不是写死的 11434。


加 MCP server 报 Cannot run program "uvx"

典型报错:

连接失败: Cannot run program "uvx" (in directory "C:\Users\你"):
CreateProcess error=2, 系统找不到指定的文件。

可能还跟着一句:

[wraith] 在当前进程的 PATH 上没有找到 uvx(也试过 PATHEXT 里的 .cmd/.exe 等后缀)。
如果你确认已经装了它,最常见的原因是 wraith 启动时继承的是旧 PATH —— 重启 wraith 再试一次。

这和上面 npx 那节是同一类问题,但 uvx 不属于 Node。 它是 uv(Astral 出的 Python 包管理器)自带的命令 —— 装 Node 不会带来 uvx。

谁会触发它:桌面「插件」面板推荐清单里的 Fetch / Git / Time 这 3 项。 其余 7 项(Filesystem、Memory、Sequential Thinking、Playwright、GitHub…)走 npx,与 uv 无关。

先分诊:

where.exe uvx
输出 说明 怎么办
信息: 用提供的模式无法找到文件。 没装 uv 见下面 ① ②
列出 ...\uvx.exe 装了,但 wraith 继承的是旧 PATH 重启 wraith(App 或 CLI 都要重启,PATH 是进程启动时读的)

① 装 uv(三种任选,以 官方安装文档 为准)

# ① 官方安装脚本(不需要先有 Python)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

# ② winget
winget install --id=astral-sh.uv -e

# ③ 已经有 Python 的话
pip install uv

uvx 是 uv 自带的,装完就有。新开一个终端验证:

uv --version
where.exe uvx        # 期望列出 uvx.exe

然后重启 wraith(桌面 App 或 CLI)—— 已经在跑的进程读不到新 PATH。

② 不装 uv,只用 npx 那 7 项

推荐清单里 Fetch / Git / Time 之外的都不需要 uv。想要抓网页的能力, 内置工具本来就有网页抓取(不经过 MCP);想读 Git 仓库,agent 直接跑 git 命令即可。

一个 server 起不来不影响别的。 MCP server 在后台并行启动、各自注册工具, 起不来的那个只是自己在面板上标红,聊天和其余 server 照常。


Electron 二进制下载失败(证书 / 网络)

典型报错:

npm error path D:\wraith\desktop\node_modules\electron
npm error command ... node install.js
npm error RequestError: unable to verify the first certificate

注意这跟缓存那类病无关:npm 包其实已经下完了,卡的是 electron 的 postinstall —— 它要去下 Electron 运行时二进制(约 100MB),不走 npm registry,直连 GitHub Releases。所以 registry 通不代表这一步能通。

unable to verify the first certificate = TLS 证书链验不过,通常是杀软或企业网关在中间拆 HTTPS 塞了自己的根证书,而 Node 不认它。

① 换镜像(首选,国内还快得多)

set ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/
npm install --legacy-peer-deps

set 只对当前窗口有效;要永久生效用 setx需新开窗口):

setx ELECTRON_MIRROR "https://npmmirror.com/mirrors/electron/"

PowerShell 对应写法:$env:ELECTRON_MIRROR = "https://npmmirror.com/mirrors/electron/"

② 让 Node 认那张根证书(换镜像仍报同样错时)

说明拦截覆盖所有 HTTPS。先确认是谁在拦:

npm config get proxy
npm config get https-proxy
npm config get strict-ssl

拿到根证书(企业 IT 提供,或从浏览器证书管理器导出为 .pem)后:

set NODE_EXTRA_CA_CERTS=C:\path\to\root-ca.pem
npm install --legacy-peer-deps

③ 关闭 TLS 校验(最后手段,不推荐)

npm config set strict-ssl false
set NODE_TLS_REJECT_UNAUTHORIZED=0

⚠️ 这等于对所有下载不设防,装完请立刻 npm config set strict-ssl true 改回来。

顺带:出安装包时还会撞一次

npm run dist:win 阶段 electron-builder 要下 winCodeSign / nsis 等二进制,同样直连 GitHub,同样会被拦。建议现在一起设了:

setx ELECTRON_BUILDER_BINARIES_MIRROR "https://npmmirror.com/mirrors/electron-builder-binaries/"

node_modules 删不动

一般是有进程占着——关掉编辑器、关掉 cwd 在里面的终端。仍然删不掉就用 robocopy 镜像一个空目录(对付海量小文件和超长路径最快):

mkdir empty_tmp
robocopy empty_tmp node_modules /MIR
Remove-Item -Recurse -Force node_modules, empty_tmp
# cmd 里最后一行写成: rmdir /s /q node_modules empty_tmp
mkdir empty_tmp
robocopy empty_tmp node_modules /MIR
rmdir /s /q node_modules
rmdir /s /q empty_tmp

建议把仓库目录加进 Windows Defender 排除项(设置 → 隐私和安全性 → Windows 安全中心 → 病毒和威胁防护 → 管理设置 → 排除项)。node_modules 是几万个小文件,实时扫描既让安装慢好几倍,也是那些 EPERM rmdir 的常见元凶。

⚠️ 不要用「以管理员身份运行」来绕过。 那会在项目里留下一批 Administrator 所有的文件,之后普通身份的 npm install / 删除会持续撞同样的 EPERM,坑更深。


6.5 命令沙箱(AppContainer)

它是什么

agent 执行的每条命令会被关进一个 AppContainer——Windows 自带的进程级隔离,免管理员。两条围栏:

围栏 效果
断网 沙箱 profile 不带 internetClient 能力,内核直接拒绝 socket。面板上的「命令沙箱联网」开关就是切这个
写围栏 只有工作区和沙箱专用临时目录可写;.git 显式拒写(防止 agent 改你的提交历史)

这是 macOS Seatbelt 在 Windows 上的对等物,语义一致。

先体检

wraith sandbox doctor

它会真跑四条探针,不是只看配置

沙箱种类  : windows-appcontainer

AppContainer 前置条件
  ✔ 平台           Windows 11
  ✔ Windows 版本   10.0
  ✔ powershell.exe C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
  ✔ 发射器脚本      C:\Users\LyHn\.wraith\sandbox\appcontainer-run.ps1

探针(工作区 D:\wraith-test)
  ✔ stdio 管道               通过
  ✔ 工作区内可写                 通过
  ✔ 工作区外拒写(期望失败)           已被拦截(符合预期)
  ✔ 断网(期望失败)               已被拦截(符合预期)

后两条「期望失败」才是重点。 前两条只说明沙箱没碍事;只有后两条被拦住,才说明它真在拦。若它们显示「本应被拦截却成功了」,说明对应围栏没生效——请把整段输出发出来。

排查

现象 原因 处理
✘ stdio 管道 且提示「退出码 0 但没拿到输出」 管道未授权给 AppContainer(DACL 不够) 这是最可能翻车的一环,请反馈
✘ powershell.exe 被组策略移除/禁用 沙箱自动降级为无,命令照常跑
命令大面积失败、报找不到文件 工具链装在用户目录下(如 %APPDATA%\npm),AppContainer 读不到 见下方「手工授权工具链」
面板顶栏红盾 + 「沙箱未启用」 前置条件缺项 跑 doctor 看是哪一项

降级不阻断。 沙箱起不来时命令照常执行,只是没有围栏——面板会显示具体原因,顶栏盾变红。这是刻意的:一个「因为没授权 npm 缓存目录就默默掐掉 npm install」的沙箱,排查成本远高于它的安全收益。

手工授权工具链

C:\WindowsC:\Program Files 默认已对 AppContainer 开放读+执行,装在那儿的工具链开箱可用。装在用户目录下的需要手工加:

:: 先从 doctor 输出里拿到 sid=S-1-15-2-... 那一行
icacls "%APPDATA%\npm" /grant *<那个SID>:(OI)(CI)(RX)

撤销(重要)

在面板里关掉沙箱不会撤销已经授出去的 ACL。 想彻底还原:

:: 撤销工作区授权(<SID> 从 doctor 输出里取)
icacls "D:\wraith-test" /remove *<SID> /T
icacls "D:\wraith-test\.git" /remove:d *<SID> /T

:: 删掉沙箱临时目录
rd /s /q "%LOCALAPPDATA%\wraith\sandbox-temp"

profile 本身留在系统里不占资源,也不影响别的程序;真要删用 PowerShell 的 Remove-AppContainerProfile(需 -Name wraith-sandbox-nonet / wraith-sandbox-net)。


7. 已知不可用 / 降级

这些是当前明确不支持的,不用浪费时间排查:

  • Petdex 桌宠在线安装不可用 —— 2026-08-02 已修(PATH 按 ; 切、认 npx.cmd、批处理经 cmd.exe /c 起)。仍需机器上装有 Node/npx;where.exe npx 找不到的话面板会明确告诉你去哪找过了。
  • 桌宠跨虚拟桌面常驻 —— Windows 没有官方 API。
  • 桌宠点击不抢焦仅 x64 精确 —— 走 koffi FFI 给窗口加 WS_EX_NOACTIVATE;ia32 上自动降级为 focusable:false,FFI 失败也会降级,不会崩。
  • 编辑器探测范围有限 —— 只按已知安装路径找 VS Code / VS Code Insiders / Cursor / Sublime Text / Notepad++;自定义安装目录、注册表安装不覆盖。
  • 安装包未签名 —— 每次大版本首次运行都会触发 SmartScreen。
  • npx 形式的 MCP server 需要自己装 Node —— Windows 不自带,wraith 安装包也只捆绑 JRE 不捆绑 Node。不是 bug;替代路线(装 Node / 改用 HTTP transport)见第 6 节。
  • uvx 形式的 MCP server 需要自己装 uv —— ⚠️ uvx 不属于 Node 生态,装了 Node 也不会有它(它是 uv 自带的命令,Python 生态)。推荐清单里 Fetch / Git / Time 这 3 项用它,其余 7 项走 npx。装法与替代见第 6 节「加 MCP server 报 Cannot run program "uvx"」。
  • 本机语义检索需要自己装 ollama —— 不装则 /index / /search / search_code 不可用;内置工具里只有 search_code 一个受影响,其余照常。可以改用云端 embedding(openai / zhipu / glm)完全绕开。见第 6 节「代码索引报连不上 11434」。

8. 只想用命令行(路线 C)

CLI 与桌面 App 共用同一套 Java 内核:同一份配置、同一份会话历史、同一套工具、同一个后台任务队列。区别只在外壳。

只需要 JDK 17 + Maven,不需要 Node。

⚠️ 一个例外:内建的 chrome-devtools MCP server 用 npx 启动。 没装 Node 的话,启动时会看到 Cannot run program "npx" —— 这不影响 CLI 本身和 38 个内置工具, 关掉即可:环境变量 WRAITH_MCP_BUILTIN_BROWSER=off(永久),或 /mcp disable chrome-devtools(本次会话)。 详见第 6 节「加 MCP server 报 Cannot run program "npx"」。

8.1 装

git clone https://github.com/JavaLyHn/wraith.git
cd wraith
# 二选一 ——
# ① 装短命令(推荐):构建 + 装 jar + 把 wraith 挂上 PATH,一步到位
powershell -ExecutionPolicy Bypass -File scripts\windows\wraith-install.ps1
# ② 不装短命令:自己构建,之后每次手打 java -jar
mvn clean package -DskipTests

走 ① 的话必须新开一个终端,当前窗口读不到新 PATH。

  • 新终端里 wraith -h 打印用法
  • java -version 是 17+

CLI 也要切分支。 Java 内核确实跨平台,但有一处 Windows 专属修复只在这个分支上:AtomicFileMove 给 tmp→target 的原子改名加了有界重试(20/40/60/80ms),应对 Windows 上目标文件被杀软/索引器短暂占用时抛的 AccessDeniedException会话落盘、技能库、QQ 待发三处都走它。停在 main 上,这些写入在 Windows 会偶发失败。

8.2 配一个模型

配置与桌面 App 共享同一份 %USERPROFILE%\.wraith\config.json——在哪边配好,另一边都认。所以:

  • 已经在桌面 App 里配过 → 什么都不用做,直接跳到 8.3
  • 只用 CLI → 第 2 节的三种方式(.env / 环境变量 / 进 CLI 后 /config)都行

CLI 没配模型是硬失败,跟桌面不一样。桌面会以「无模型」状态起来并引导你去配; CLI 会直接退出:

❌ 错误: 未找到可用的 API Key
请在 .env 文件中添加 GLM_API_KEY、DEEPSEEK_API_KEY、…

这句话只提了 .env,但 config.json 同样有效(读取顺序是 config.json → 环境变量 → .env)。

8.3 起 + 冒烟验一遍

wraith
# 没装短命令就是:  java -jar target\wraith-1.0-SNAPSHOT.jar
  • 出现开场动画 + banner,底部是输入提示符
  • / 弹出命令列表(Tab 补全可用)
  • 发一句「你好」,有流式回复
  • 发「读一下 README.md 的前 20 行」→ 工具调用 → 弹 HITL 审批 → 批准后有内容
  • /model 显示当前模型
  • /context 显示 token 用量与上下文模式
  • /exit 能退出(/quit 同义)

会话自动落盘。退出后 wraith -c 接着上一次,wraith -r 列出历史挑一个。

8.4 ⚠ CLI 与桌面的一处安全差异

交互式 CLI 不套命令沙箱。 CommandSandbox 只在 app-server(桌面)/ IM 网关 / 定时任务 三条路径注入;CLI 的 ToolRegistry 沙箱是 null

也就是说在 CLI 里 agent 执行的命令:

桌面 CLI
AppContainer 围栏(断网 / 写限工作区 / .git 只读) 没有
命令黑名单(rd /s /q C:\format C: …)
HITL 审批弹窗
危险工具审计(~/.wraith/audit/

wraith sandbox doctor 体检的是沙箱本身能不能用(给桌面/网关/定时任务用的), 它报「就绪」不代表你正在 CLI 里跑的命令被关起来了。这是刻意的设计 (交互式终端里你本来就在自己的 shell 上下文里作业),但得知道。

8.5 不进对话的子命令

wraith sandbox doctor        # 沙箱体检(四条探针,见 §6.5)
wraith gateway bind <平台>   # 绑定 IM 账号(qq / feishu / wecom / weixin)
wraith app-server            # 桌面端用的 JSON-RPC 后端(一般不用手敲)
wraith wechat <...>          # 个人微信 iLink 通道
wraith serve --http          # Runtime HTTP API

⚠️ wraith wechat 与桌面里的微信网关不能同跑(同一个 iLink 通道)。

8.6 对话内命令一览

/ 加 Tab 就能补全,这里按用途列一遍(不是全部参数形态):

用途 命令
会话 /clear /compact /history clear /export /resume /cancel /exit(/quit)
模型与配置 /model /config /context(/ctx) /hitl on|off
记忆 /memory(/mem) list search <词> delete <id> pending approve <id> reject <id> clear/save [内容]
检索 /index /search <词> /graph
编排 /plan <目标> /team <目标> /skill /task
安全 /policy /audit
快照 /snapshot /restore
外部 /mcprestart/logs/disable/enable/resources/prompts/browser /wechat
工程 /init(生成项目记忆)

8.7 改了代码之后

改了什么 CLI 怎么重来
Java 后端 wraith-install(或 mvn clean package -DskipTests),然后重开 wraith
只改前端 与 CLI 无关

装了短命令后 wraith-install 一条搞定:它内部复用 dev-win.ps1, 构建产物同时供 CLI 和桌面 dev 使用(两者读的是同一个 %USERPROFILE%\.wraith\wraith.jar)。