Files
Hermit/docs/README-windows.md
T
WHC 2a43ae6622
ci / linux (clang) (push) Canceled after 0s
ci / linux (gcc) (push) Canceled after 0s
ci / sanitizers (push) Canceled after 0s
ci / musl (push) Canceled after 0s
ci / macos (push) Canceled after 0s
Windows: official port -- UCRT static build, UTF-8 throughout, Low IL sandbox, ncurses TUI, installer; v0.6.0
Build
  * cross build switches to pkgsCross.ucrt64 (shell-win.nix); curl (Schannel),
    winpthreads and ncurses 6.6 are linked statically, so the release is
    cst-agent.exe + busybox.exe (busybox-w32 Unicode) with no extra DLLs
  * windres embeds a manifest with activeCodePage=UTF-8 and a version resource
  * ncurses 6.6 Windows console driver patches (mouse button state, A_DIM,
    wide-char declarations): scripts/patches/
  * scripts/bootstrap_msys2.sh builds the same release natively in MSYS2
    UCRT64; PR #1's MINGW64 notes now point there
  * vendor/tre-regex (musl's TRE) provides <regex.h> on MinGW

UTF-8
  * paths cross the system call boundary as UTF-16 (*W APIs); console code
    pages set to 65001 and restored on exit; files are read and written in
    binary mode
  * child output that is not valid UTF-8 is decoded from the console, OEM or
    ANSI system code page
  * read_file hides CR; edit_file, apply_patch and write_file keep CRLF line
    endings and a UTF-8 BOM

OS layer and processes
  * os_dir_* and cst_fnmatch replace the POSIX-only directory walks in
    subagent, plugins, skills, undo and fs_tools; realpath / path_under and
    symlink rejection work on Windows
  * every child goes through CreateProcessW with its own environment block
    inside a Job Object, so timeouts and Esc end the whole process tree

Sandbox (auto mode, "auto · lowil")
  * run_shell runs with a restricted Low integrity token; the workspace gets
    an inheritable Low label once, the sandbox TEMP is labeled Low, and the
    credentials file gets a no-read-up label
  * drive roots, the profile and system folders are never labeled
  * network commands still ask, since Low IL does not block the network;
    Access denied and MSYS2's 0xc0000142 offer a rerun outside the sandbox
  * /sandbox lists labeled folders, /sandbox reset-labels restores them

TUI
  * raster console fonts are switched to Consolas / NSimSun while running
  * the home logo falls back to text when the console font lacks U+2580
  * mouse drag copy goes to the Windows clipboard

Distribution
  * scripts/install_windows.ps1 installs a Gitea release into
    %LOCALAPPDATA%\Programs\cst-agent and adds it to the user PATH;
    cst-agent-update.cmd reruns it; scripts/release_windows.sh uploads the
    zip with the token taken from the environment
  * scripts/run_windows.bat is gone; docs/README-windows.md is rewritten

Tests
  * new test_lowil, test_win_utf8 and test_os_dir; tests made portable
    (cst_test_util.h)
  * scripts/win_test.sh and scripts/winvm/ run the suite on English and
    Chinese Windows Server VMs as Administrator, a standard user and a
    Chinese user name: 29/29 on all six
2026-10-06 23:08:14 +08:00

8.4 KiB
Raw Blame History

CST-Agent on Windows

原生 Windows 版:一个静态链接的 cst-agent.exe(UCRT,内嵌 UTF-8 清单)加一个 busybox.exe(busybox-w32 Unicode 版)作为 shell,不依赖其他 DLL,也不需要管理员权限。

安装

在 PowerShell 里(Windows PowerShell 5.1 或 PowerShell 7 都行):

irm https://git.whcself.xyz/WHC/CST-agent/raw/branch/main/scripts/install_windows.ps1 | iex

脚本从 Gitea Release 下载 cst-agent-VERSION-windows-x86_64.zip,校验 .sha256, 装到 %LOCALAPPDATA%\Programs\cst-agent,并把这个目录加进用户 PATH。装完新开一个终端:

cd C:\code\my-project
cst-agent

首次启动会让你选 provider 并输入 API key(遮罩输入,按 provider 保存)。

以后升级:

cst-agent-update                 :: 最新版
cst-agent-update -Version 0.6.0  :: 指定版本

正在运行的 cst-agent.exe 不会挡住升级:旧文件会先改名为 .old,下次升级时删掉。

安装脚本的参数(下载后用 powershell -ExecutionPolicy Bypass -File install_windows.ps1 ... 运行):

参数 环境变量 作用
-Version 0.6.0 CST_VERSION 指定版本,默认最新
-Prefix D:\tools\cst CST_PREFIX 安装目录
-Zip FILE 用本地 zip,不联网
-NoPath 不改用户 PATH
CST_GITEA / CST_REPO 换 Gitea 服务器或仓库(默认 WHC/CST-agent)

不想用脚本的话,把 zip 解压到任意目录直接运行 cst-agent.exe 也可以。

系统要求

  • Windows 10 1903(build 18362)及以上、Windows 11、Windows Server 2022 / 2025。 更老的系统不认清单里的 activeCodePage=UTF-8,安装脚本会直接拒绝。
  • x86_64。Windows 10 1903 起系统自带 UCRT,无需另装运行库。
  • 终端:Windows Terminal 或传统控制台(conhost)都行。

发行包内容

windows-x86_64/
  cst-agent.exe          # 静态链接:curl(Schannel)、ncurses 6.6、winpthreads
  busybox.exe            # busybox-w32 Unicode 版,run_shell 用它的 sh
  LICENSE.busybox
  README.md              # 本文件
  VERSION
  cst-agent-update.cmd   # 调用旁边的 install_windows.ps1 升级本目录
  install_windows.ps1

文件位置

内容 位置
API key(每个 provider 一个) %APPDATA%\cst-agent\credentials,只有当前用户可读,并带“禁止向上读”标签(沙箱内读不到)
上次的 provider、模型、推理强度、确认模式 %APPDATA%\cst-agent\settings.json
沙箱打过标签的目录 %APPDATA%\cst-agent\sandbox-labels
会话、撤销快照、导出 <工作区>\.agent\

设置了绝对路径的 XDG_CONFIG_HOME 时用 %XDG_CONFIG_HOME%\cst-agent。

编码:全部 UTF-8

  • exe 内嵌 activeCodePage=UTF-8 清单:进程的 ANSI 代码页就是 65001,命令行参数、 环境变量、文件名都以 UTF-8 进出;内部所有路径在系统调用边界转成 UTF-16(*W API)。
  • 控制台输入输出代码页在启动时设为 65001,退出时恢复。
  • 文件按字节读写,不做换行转换。read_file 给模型看的是去掉 \r 的文本;edit_file、 apply_patch、write_file 会保持原文件的 CRLF 换行和 UTF-8 BOM。
  • 子进程输出:先按 UTF-8 解码;不是合法 UTF-8 时依次尝试控制台代码页、系统 OEM / ANSI 代码页(比如中文系统的 936),转成 UTF-8 再交给模型。
  • 中文用户名、中文工作区路径(C:\Users\测试\项目)都已在中英文系统上测过。

终端界面(TUI)

用的是打过补丁的 ncurses 6.6 Windows 控制台驱动(补丁在 scripts/patches/ncurses-6.6-win32-console.patch):

  • 中文按两列宽显示,光标位置正确;粘贴多行不会直接发送。
  • 鼠标:点击、拖选复制(写入 Windows 剪贴板)、滚轮滚动;/mouse 关闭。
  • /copy 和拖选复制走 Win32 剪贴板 API,不依赖终端的 OSC 52。
  • 控制台是点阵字体时(显示不了中文,会变成 ?),启动时自动换成同字号的 Consolas (中文系统换成新宋体),退出时换回去。
  • 传统控制台不做字形回退:当前字体缺 logo 用的方块字符时(比如中文系统默认的新宋体), 首页改用文字 logo。

Shell 沙箱:Low 完整性级别

auto 确认模式下,run_shell 在 Low 完整性级别的受限令牌里运行(界面显示 auto · lowil):

  • 子进程的令牌去掉了管理员组和特权,完整性级别为 Low(S-1-16-4096),放进 Job Object, 超时或按 Esc 时整个进程树一起结束。
  • Low 进程只能写标为 Low 的位置。第一次在某个工作区跑沙箱命令时,CST-Agent 给工作区 加上可继承的 Low 标签(S:(ML;OICI;NW;;;LW)),并在输出里提示一次; 记录写进 sandbox-labels。沙箱的临时目录是 %TEMP%\cst-agent-sandbox(同样标为 Low), 子进程的 TEMP / TMP 指向这里。
  • 不会给盘符根目录、用户目录本身、%APPDATA%、%LOCALAPPDATA%、%TEMP% 本身, 以及 Windows、Program Files、ProgramData 下面的目录打标签:在这些地方启动时,命令不会运行, 界面会问是否在沙箱外重跑。请在项目目录里启动。
  • /sandbox 列出打过标签的目录;/sandbox reset-labels 恢复它们原来的标签。
  • 沙箱里可以读、执行用户能访问的文件(凭据文件除外),不限制联网。所以像联网的命令 (curl、wget、ssh、git clone/fetch/pull/push、npm install、pip install、 winget install、Invoke-WebRequest 等)在 auto 模式下仍然会弹窗确认。
  • 命令像是被拦了(Access is denied、拒绝访问、Permission denied 等)时,会问 “Rerun outside the sandbox?”:y 在沙箱外重跑一次,p 保存命令前缀规则并重跑,n 保留结果。
  • MSYS2 / Cygwin 的程序(包括 Git for Windows 自带的 usr\bin 工具)在 Low 级别下无法初始化 (0xc0000142),同样会触发上面的重跑询问。Git for Windows 的 git.exe 本身不受影响。
  • CST_SANDBOX=off 关闭沙箱(auto 退回只读白名单规则);CST_SANDBOX=lowil 只用 Low IL。

它防的是误操作写坏工作区以外的文件,不是对抗恶意程序的安全边界。

从源码构建

两种方式产物一样:dist/windows-x86_64/ 和 dist/cst-agent-VERSION-windows-x86_64.zip。 第三方依赖(curl、ncurses、busybox-w32)都按固定版本从源码编译、静态链接。

在 Linux 上交叉编译

git clone https://git.whcself.xyz/WHC/CST-agent.git
cd CST-agent
scripts/bootstrap_windows.sh

NixOS / 有 Nix 时自动进 shell-win.nix(pkgsCross.ucrt64);否则需要 UCRT 版的 x86_64-w64-mingw32-gcc(带 winpthreads)、cmake、ninja、git、perl。

在 Windows 上用 MSYS2 原生编译

装好 MSYS2 后,打开 MSYS2 UCRT64 终端(不是 MINGW64: MINGW64 链接 msvcrt,UTF-8 清单不起作用):

pacman -S --needed git
git clone https://git.whcself.xyz/WHC/CST-agent.git
cd CST-agent
scripts/bootstrap_msys2.sh

脚本会用 pacman 装 UCRT64 的 gcc / cmake / ninja,编译依赖和 cst-agent.exe,跑 ctest (CST_SKIP_TESTS=1 跳过),再打包。

测试

scripts/win_test.sh 在本机 QEMU 里的 Windows Server 虚拟机(英文 / 中文系统,管理员 / 普通用户 / 中文用户名)上交叉编译后跑全部测试;虚拟机的创建和控制见 scripts/winvm/。

发布

GITEA_TOKEN=... scripts/release_windows.sh --build

创建(或复用)vVERSION Release,上传 zip 和 .sha256。token 只从环境变量读取,经 stdin 交给 curl,不会出现在命令行参数、磁盘或输出里。

已知限制

  • 英文等非中文系统的传统控制台默认用 Consolas,它没有中文字形,中文会显示成方框(列宽仍然正确)。 用 Windows Terminal,或在控制台“属性 → 字体”里选新宋体等中文字体即可。
  • 传统控制台里输入表情符号(BMP 以外的字符)可能显示不对;中文输入没问题。
  • 通过 SSH / ConPTY 远程运行时,鼠标事件不会转发过来,键盘操作不受影响。
  • 很大的工作区第一次打标签要等一会儿(标签要继承到每个文件)。
  • 只有 x86_64 发行包。