适用版本:ChengOS v0.1.0+ | 最后核对:2026-08-12 | 来源:
crates/cheng-cli/src/config.rs、crates/cheng-cli/src/main.rs、crates/cheng-cli/src/auth、crates/cheng-local-executor
cheng CLI 不必与 ChengOS 服务器跑在同一台机器上。一旦不在同一台,有一个问题决定了其余一切:工作流读文件时,读的是谁的磁盘?
两种工作区模式
| 模式 | 文件工具在哪运行 | 看到的是 |
|---|---|---|
server_local |
API 主机上 | 服务器的文件系统 |
client_local |
本 CLI 进程内 | 你的目录 |
client_local 正是让远程服务器能服务本地工作的关键:服务器负责编排,你的机器负责执行,你的文件从不离开本机。
默认值是替你选好的
如果你不指定模式,CLI 会依据服务器 URL 的主机名推导:
localhost | 127.0.0.1 | ::1 → server_local
其他任何主机 → client_local
这个默认几乎总是对的。共享你文件系统的本地服务器就该直接用它;远程服务器显然做不到。
按会话覆盖用 --workspace-mode server_local|client_local,永久覆盖用配置文件里的 workspace_mode。不支持的取值会被直接拒绝,而不是悄悄回落。
cheng back 永远是 client_local,并且刻意不提供 --workspace-mode 标志,哪怕服务器就在 localhost:产品承诺是,被选中的那个 CLI 进程拥有并服务它的启动目录。
连接
cheng chat --server https://chengos.example.com
优先级从高到低:命令行标志 → 环境变量 → 配置文件 → 内置默认值。环境变量是 CHENG_SERVER_URL 和 CHENG_TOKEN;默认服务器是 http://localhost:3000。
配置文件位于 $CHENG_CONFIG 或 ~/.config/cheng/config.json:
{
"server_url": "https://chengos.example.com",
"token_file": "~/.config/cheng/token",
"default_workspace": "Default Workspace",
"default_workflow": "main_chat",
"request_timeout_secs": 30,
"auth_storage": "auto",
"workspace_mode": "client_local",
"workspace_tools": { "shell_enabled": true, "git_enabled": true }
}
凭证
Bearer 令牌绝不回显、绝不写入 REPL 历史、绝不写入项目文件。持久化它是一次显式选择,做在用户级配置文件里——更好的做法是用 token_file,指向一个文件,其去空白后的内容就是令牌。
存储策略(auth_storage 或 --auth-storage):
| 策略 | 凭证存放方式 |
|---|---|
auto(默认) |
操作系统钥匙串;失败时在 TTY 下询问,非交互环境则报错 |
keyring |
强制使用系统凭证服务 |
host-bound |
用主机/用户派生密钥加密的 AES-256-GCM 文件——透明,无需主密码 |
encrypted-file |
用主密码加密的 AES-256-GCM 文件 |
file |
明文文件——必须显式开启 |
none |
仅内存;退出即丢失 |
在无头机器上,host-bound 是务实之选:静态加密、不需要钥匙串守护进程、脚本里也不弹密码。
注意 auto 在没有 TTY 时是报错而不是降级。没有钥匙串的 CI 作业会响亮地失败,而不是悄悄写下一个明文令牌。
凭证是按服务器分域的,因此一台机器可以同时持有多个 ChengOS 服务器的凭证,切换 --server 就同时切换了身份。
client-local 模式下的本地工具
在 client_local 模式下,CLI 通过 cheng-local-executor 自行执行工作区工具——那也是其他本地客户端使用的同一套执行外壳,因此文件与进程语义不会在它们之间漂移。
workspace_tools 配置段控制允许什么:
| 设置 | 默认 | 含义 |
|---|---|---|
shell_enabled |
开 | 允许 shell 命令 |
shell_allow_shell_string |
关 | 允许裸 sh -c 字符串——高风险 |
shell_default_timeout_ms / shell_max_timeout_ms |
命令超时 | |
shell_env_allowlist |
空 | 命令可额外设置的环境变量 |
shell_deny_patterns |
空 | 额外的命令禁用子串,纵深防御 |
git_enabled |
开 | Git 操作 |
tests_enabled |
开 | 测试运行器 |
markdown_enabled |
开 | Markdown 工具 |
preview_enabled |
开 | 预览 |
code_index_enabled |
开 | 代码索引 |
shell_allow_shell_string 默认关闭,是因为裸 shell 字符串会瓦解参数级策略:一旦命令变成一整个不透明字符串,就只剩禁用子串这一道防线了。只有当你确实需要管道之类的 shell 特性时才打开它。
只读会话是把 CLI 指向一个你不想被改动的目录时最安全的做法:
cheng chat --read-only --cwd ~/projects/my-repo
跨设备的会话
cheng sessions # 服务器上你的 CLI 会话
cheng chat --resume <session-id> # 重新加入某个会话
cheng history # 持久会话,含已暂停的工作
cheng chat --resume-conversation <uuid>
会话存在服务器上,因此在笔记本上开的会话,在台式机上也能列出来。--resume-conversation 用于旧的 CLI 会话已过期但对话仍在的情况;它与 --resume、--workspace、--workflow 互斥,因为那些参数会与该对话自身的绑定相矛盾。
恢复一个 client-local 会话时,CLI 会检查存储的根目录标签是否与你当前目录一致——恢复的会话应当服务它此前服务的那棵目录树。超过服务端显示上限的标签会被截断存储并以省略号开头,比较时会考虑这一点。
后台代理
cheng back # 把当前目录作为 client-local 工作区提供出去
cheng ps [-a] # 列出后台代理
cheng logs <pid|session> # 它的日志在哪
cheng stop|restart|rm <id>
cheng prune # 清理已停止和过期的元数据
cheng back 以无头方式运行,把当前目录服务给 Web 界面:你在浏览器里继续干活,而文件留在你的机器上。--status、--stop 和 --logs 作用于当前目录所记录的那个代理,通常比去查 pid 更省事。
一套可用的远程配置
// ~/.config/cheng/config.json
{
"server_url": "https://chengos.example.com",
"auth_storage": "host-bound",
"workspace_mode": "client_local",
"default_workspace": "Default Workspace",
"default_workflow": "main_chat",
"workspace_tools": {
"shell_enabled": true,
"shell_allow_shell_string": false,
"git_enabled": true,
"tests_enabled": true
}
}
然后在任意项目目录里 cheng chat,即可连上远程服务器,同时在本地执行文件与 shell 工作。
排查
| 现象 | 原因 |
|---|---|
| 文件工具看到的文件不对 | 工作区模式选错了——对照上面的自动选择规则 |
| CI 中鉴权失败 | 没有 TTY 时 auto 会报错;改用 host-bound 或 CHENG_TOKEN |
| shell 命令被拒 | shell_enabled 关着、命中了禁用子串,或会话是 --read-only |
--resume 被拒绝 |
存储的根目录与你当前目录不一致 |
cheng --version 与服务器不同 |
它报告的是 ChengOS 发行版本;不一致就说明确实是不同的构建 |

暂无评论内容