- Rust 46.6%
- Python 41.5%
- Shell 7%
- CSS 1.6%
- Nix 1.3%
- Other 2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
Documentation CI / Documentation check/build/publish (push) Successful in 35s
Remove runtime health-probe death latches, retain uncertain creations, and require confirmed cleanup outcomes. Make shutdown independent of acknowledgement delivery and serialize duplicate destruction through existing state. Add tracing diagnostics, stale-state UI handling, failure evidence retention, and recovery regressions. Verified scripts/check.sh, Nix build and flake check, packaged long-socket tests, and installed-package smoke tests. |
||
| .forgejo/workflows | ||
| apps/docs | ||
| assets | ||
| docs | ||
| examples | ||
| nix | ||
| patches | ||
| prototypes/rmux-listener-fd | ||
| scripts | ||
| src | ||
| tests | ||
| .envrc | ||
| .gitattributes | ||
| .gitignore | ||
| .yarnrc.yml | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CONTEXT.md | ||
| devenv.lock | ||
| devenv.nix | ||
| devenv.yaml | ||
| flake.lock | ||
| flake.nix | ||
| package.json | ||
| PLAN.md | ||
| README.md | ||
| yarn.lock | ||
Kuruwa
Kuruwa 为 agent 提供项目级的多权限执行环境与终端复用:人工启动一个主 daemon,按持久配置开放租户入口,让租户在获准的沙盒实例中运行终端,并可随时撤回访问或通过原生 RMUX attach 干预。
状态
M0–M6 MVP 已验收完成。 固定 RMUX 0.8.0 listener 适配、实例/终端闭环、租户授权与撤回、完整日常终端操作与宿主 attach、部署与完整用户流程均已实现。M6 的统一验收入口 scripts/check.sh 在干净 checkout 和原仓库复跑中均以 exit 0 结束并打印 CHECK_PASS(干净日志 /tmp/opencode/kuruwa-m6-clean.log,主 agent 复跑日志 /tmp/opencode/kuruwa-final-primary.log)。真实 kuruwa 支持实例所有权、单终端 grant、run/resume、send、screen/tail/transcript、cancel、gc、typed resize、宿主原生 attach 和本地 skill。
serve默认在项目根$PWD/.kuruwa后台启动;--foreground保持前台常驻,显式--config/--runtime仍兼容。- 首次
serve自动生成缺失的config.toml与init/脚本,不覆盖已有文件,不创建实例、终端或 grant。 - 客户端入口顺序为
--socket、KURUWA_SOCKET、<root>/admin.sock;普通命令不创建 root,也不自动启动服务。显式入口失效不回退。 - 连接哪个入口就使用哪个主体的授权;请求 JSON 不能自报身份或 endpoint/session。
- 管理入口唯一控制租户列表、grant/revoke 和 shutdown;原生 attach 还允许目标实例的 owner。
- 一个终端是实例内 RMUX session 的单 pane;命令任务与长期 shell 使用同一对象模型。
- 实例、终端和临时授权属于本次运行,不跨重启恢复。
- 已实现命令:
serve、shutdown、instance create/list/destroy、tenant list、grant、revoke、start、run、status、ls、send、screen、tail、transcript、resume、cancel、clean、gc、resize、attach、exec、skill、cli。 kuruwa exec --definition NAME -- PROGRAM ARG...不连接 daemon、不进入实例,直接把配置里的声明式 sandbox 策略用于本次进程,透传 stdin/stdout/stderr 与 argv;退出状态沿用 bubblewrap 执行边界(被信号终止的 payload 通常为128+signal),Kuruwa 自身不做额外转写。实现见下文。kuruwa cli提供真实 TTY 中的交互管理界面:实例/终端列表、纯文本预览与暂停、创建实例/终端、grant/revoke、确认后的 cancel/clean/destroy,以及 detach 后返回的原生 attach。身份与可操作对象由服务器按入口主体返回,界面不读取配置冒充授权。- M5 已实测完整流程:持久配置、bwrap/host 实例、grant/revoke、原生 PTY attach、强制销毁、cleanup、重启与实例 daemon 失效。部署和实测摘要见 部署与 M5 演练。
- 验收入口:
scripts/check.sh顺序运行固定 RMUX 构建/回归、cargo 格式/构建/单测/clippy、M2–M5 真实套件、exec/声明式 sandbox 行为套件、Task 2 项目根/后台 daemon 套件、Task 1 交互界面真实 PTY 套件和继承 FD 验收;M6 历史验收记录见 M6 交付验收。
# 一条完整验收入口;首次会构建固定 RMUX
scripts/check.sh
# 或分阶段运行:
scripts/build-rmux.sh
cargo build
python3 scripts/test-m2.py
python3 scripts/test-m3.py
python3 scripts/test-m3-blocked.py
python3 scripts/test-m3-write.py
python3 scripts/test-m4.py
python3 scripts/test-m5.py
python3 scripts/test-exec.py
python3 scripts/test-root.py
python3 scripts/test-tui.py
# 深路径(>108 字节)实例:对打包产物运行,见 docs/packaging.md
KURUWA_BIN="$(nix build .#kuruwa --no-link --print-out-paths)/bin/kuruwa" \
python3 scripts/test-long-socket.py
交互界面
kuruwa cli 需要交互式 TTY,不接受 --json,也不会自动启动后台服务:
kuruwa serve # 另一终端或先前启动
kuruwa cli # 使用默认 root 入口
kuruwa --socket /path/admin.sock cli
主要按键:Tab 切换 Instances/Terminals 焦点,j/k 或方向键选择,Space 暂停/恢复预览,i 创建实例,n 创建终端,g/r 授予/撤回租户,c/x/d 确认后 cancel/clean/destroy,Enter 原生 attach,? 帮助,q 退出。终端 argv 使用 JSON 数组(如 ["bash"]),不按 shell 字符串求值。原生 attach detach(C-b d)后返回界面并刷新。
空实例/空终端时欢迎页使用现有小号 kuruwa logo 和创建/帮助提示;日常顶栏只保留紧凑字标、身份、项目与项目根。品牌红橙黄只用于 logo、短装饰和边框;正文、root、快捷键、身份、确认对象与后果一律使用终端默认前景,身份/当前选择/确认提示用粗体或反显强调,不依赖浅灰或主题色;NO_COLOR 关闭颜色并保留单色 logo。帮助页按剩余空间选择中号/小号/文字字标,确保快捷键不被挤出。小于约 60x18 时会提示放大,q/? 仍可用。终端彩色资产只解析成 Ratatui styled spans,不把原始控制序列回放到 alternate screen。顶层 kuruwa --help 仅在 TTY 且非 JSON 时显示品牌 banner;serve 首次交互初始化显示一次小号 logo,--foreground、--json、非 TTY 管道以及 screen/tail/transcript 保持无装饰输出。
完整按键、确认框、暂停与权限撤回行为见 交互管理界面。
本地 exec 与声明式 sandbox
定义可以用 [definitions.sandbox] 声明原生 bubblewrap 参数和可信 Bash hooks,替代旧的 init argv(两者必须二选一)。kuruwa exec 用同一份配置直接运行一条命令:
# examples/kuruwa-sandbox.toml 的 sandbox 定义
kuruwa exec --definition sandbox --config examples/kuruwa-sandbox.toml -- printf 'inside\n'
# 省略 --config 时读取 <KURUWA_ROOT>/config.toml(缺省 $PWD/.kuruwa),且从不创建它
kuruwa exec --definition sandbox --config examples/kuruwa-sandbox.toml -- sh -c 'ps -o pid,comm -p $$'
echo input | kuruwa exec --definition sandbox --config examples/kuruwa-sandbox.toml -- cat # stdin 原样传递
kuruwa exec --definition sandbox --config examples/kuruwa-sandbox.toml -- sh -c 'exit 7'; echo $? # 7
exec 不连接 daemon、不创建实例、不经过 PTY 或 transcript,也不创建项目根/配置文件;只接受 [definitions.sandbox] 定义,旧 init 定义会明确报错。运行后 Kuruwa 进程被 runner 与 bwrap 替换:cwd、argv(含空格和空字符串)与 stdin/stdout/stderr 原样传递,Kuruwa 自身不做额外状态转写,退出状态由 bubblewrap 执行边界给出——被信号终止的 payload 通常为 128+signal(SIGTERM → 143),普通退出 143 与它不可区分。
[[definitions]]
name = "sandbox"
# 可选:把 Ctrl+B 原样交给终端并隐藏 RMUX 状态栏(Harness Hub 需要)
# terminal_passthrough = true
[definitions.sandbox]
args = ["--die-with-parent", "--ro-bind", "/", "/", "--proc", "/proc", "--dev", "/dev"]
hooks = ["sandbox-hooks/instance-work-dir.sh"]
args是原生 bwrap 参数(不含 bwrap 程序本身),hooks是可信 Bash 文件,按顺序source;任一 hook 失败会阻止后续 hook 与 bwrap。- 两者只支持严格的
${NAME}替换(值来自启动进程的环境);$NAME、${NAME:-x}、命令替换一律拒绝,未设置变量报错且不回显值,空字符串 argv 元素保留。 - hook 相对路径相对配置文件目录解析,不依赖进程 cwd;hook 追加在静态
args之后,所以先--bind、后隐藏路径。 - bwrap 与 bash 分别由
KURUWA_BWRAP_BIN/KURUWA_BASH_BIN解析(Nix 包设置默认值),与KURUWA_RMUX_BIN规则一致。 - 同一策略用于
instance create时,runner 最终执行既有的KURUWA_RMUX_BIN --__internal-daemon ... --listener-fd ...,listener FD 继承契约不变。 - 定义级
terminal_passthrough = true会在实例固定的remain-on-exit/exit-empty之后追加prefix None、prefix2 None、status off;缺省false保持原交互行为,不会全局关闭 prefix。
Nix 包
仓库提供面向 x86_64 Linux 的 Nix flake,把产品 CLI、补丁版 RMUX 后端、示例定义和安装配置交付为一个可直接运行的包。flake 输入与 devenv.lock 使用同一组固定 revision,因此发布包与开发环境不会使用两套依赖。
nix build .#kuruwa
nix run .#kuruwa -- --help
# 如果 flake 文件尚未被 Git 跟踪,使用工作区路径而不是暂存文件:
nix build path:$PWD#kuruwa
构建完成后可以把 result/bin 加入当前 shell 的 PATH;安装产物、配置复制方式、bwrap 内命令的绝对路径要求和打包烟测见 Nix 打包。
export PATH="$(readlink -f result)/bin:$PATH"
cd /path/to/project
kuruwa serve # 默认 $PWD/.kuruwa,后台启动并自动初始化
kuruwa serve --foreground # 前台常驻
kuruwa --json shutdown # 通过默认 root 入口关闭
包内 share/kuruwa/kuruwa.toml 仍可作为显式配置使用:复制到任意目录后通过
kuruwa serve --config <file> --runtime <dir> 启动,或使用默认生成的配置。
bin/kuruwa 默认使用包内补丁版 RMUX 0.8.0 和包内 bash/coreutils/bubblewrap;显式设置的 KURUWA_RMUX_BIN 仍然优先。
文档
- 施工计划:阶段、工作项与退出条件。
- 最小接口契约:CLI 命令、配置、初始化环境、权限矩阵与纸面演练。
- 交互管理界面:
kuruwa cli的布局、固定按键、表单、确认、预览/暂停和 attach 行为。 - 部署与 M5 演练:构建、配置、启动、租户入口、弱隔离和完整流程实测摘要。
- M6 交付验收:一条命令、环境前提、M1–M6 证据、干净 checkout 与主 agent 复跑结果、限制汇总。
- 第一版设计:对象模型、入口、初始化与生命周期。
- Nix 打包:flake 输入、包内布局、安装配置、bwrap 命令路径和打包烟测。
- 领域词汇表:主 daemon、沙盒实例、终端等术语。
- RMUX 监听 FD 原型:可丢弃的技术验证及其限制。
当前已验证的基础
RMUX 0.8.0 的监听 FD 交接已在 Linux/bwrap 原型中验证:外侧预绑定 listener,经可信初始化程序传入最终环境,由 RMUX 导入后服务;终端不继承内部通信 FD,原生 attach、实际退出状态与清理均有实测。该原型不是生产代码,也不证明任意 UID、namespace 或初始化程序组合都可用。