RFC: NeoCode 命令行体验 (CLI UX) 重新设计
1. 目标问题 (Why)
随着 NeoCode 架构的快速演进,当前 CLI 命令树暴露出以下体验与规范问题:
- 概念外泄与认知负担:
gateway 与 daemon 两个底层系统概念直接暴露给普通用户,且 daemon 生命周期管理不直观(如残留旧进程需要手动 kill)。
- 缺乏 Provider 管理入口(已解决):自定义大模型通过外挂
providers/ 目录实现,过去用户必须手写 YAML,缩进错误即导致启动崩溃。
- 命令无统一规范:部分底层调试命令暴露在外,缺乏清晰的命名约定。
- 配置修改门槛高:用户修改超时等简单配置项需要手动编辑 YAML,容易格式错误。
2. 设计原则与命名规范
2.1 命名规范
采用务实混合模式,区分两类命令:
| 类型 |
模式 |
适用场景 |
示例 |
| 动作命令(顶级动词) |
<verb> <args> |
用户最频繁执行的单一动作 |
neocode、neocode shell、neocode use <provider>、neocode diag |
| 资源命令(名词组) |
<noun> <verb> <args> |
围绕某一资源的增删改查 |
neocode provider add、neocode model ls、neocode daemon status |
判断标准:如果该命令 90% 的使用场景就是做一件事,用动作命令;如果一个名词下有多个正交操作,用资源命令。
use 作为顶级动词而非 provider use 的理由:切换 provider 是用户每天可能执行的最频繁操作,额外嵌套一级没有信息增益——用户说"我要用 DeepSeek"自然就是 neocode use deepseek。
2.2 配置哲学
- 简单标量值(超时秒数、开关、路径)通过 CLI 修改,降低出错概率。
- 复杂嵌套结构(provider 定义、gateway 调优参数、tools 子配置)引导用户编辑 YAML。
- CLI 不提供
config list——全量查看去配置文件本身即可,CLI 只做单点读写。
3. 完整命令树
标记说明:✅ 已实现 | ⬜ 待实现 | 🔧 待调整
neocode ✅ 启动沉浸式 TUI 主页面
# --- 核心交互 ---
neocode shell ✅ 进入 AI 增强型 PTY 代理终端
neocode shell --init [shell] ✅ 输出 shell integration 初始化脚本
neocode diag ✅ 向当前 shell 发送一次手动诊断信令
neocode diag auto <on|off|status> ✅ 控制 / 查询自动诊断模式
neocode diag diagnose ✅ 显式触发一次手动诊断(与 diag 等价,保留作为语义别名)
# --- 提供商选择(高频动作命令) ---
neocode use <provider> ✅ 全局切换激活的 provider
neocode use <provider> --model <id> ✅ 切换 provider 并同时指定模型
# --- 模型管理 ---
neocode model ls ✅ 列出当前 provider 的可用模型
neocode model set <model-id> ✅ 在当前 provider 下切换模型
# --- 提供商管理 ---
neocode provider add <name> ✅ 挂载自定义 provider
--driver, --url, --api-key-env,
--discovery-endpoint
neocode provider ls ✅ 列出全部已挂载和内置的 provider
neocode provider rm <name> ✅ 删除自定义 provider
# --- 配置读写 ---
neocode config get <key> ⬜ 读取单个配置项的值
neocode config set <key> <value> ⬜ 修改单个标量配置项
# --- 系统服务 ---
neocode gateway 🔧 启动本地 gateway 进程(保留暴露,供调试)
neocode daemon serve ✅ 启动 HTTP 唤醒 daemon
neocode daemon install ✅ 安装 daemon 自启动
neocode daemon uninstall ✅ 卸载 daemon 自启动
neocode daemon status ✅ 查询 daemon 运行状态
neocode daemon encode run ✅ 生成可点击的 /run 唤醒链接
neocode daemon encode review ✅ 生成可点击的 /review 唤醒链接
# --- 版本与升级 ---
neocode version ✅ 输出版本号
neocode update ✅ 检查并升级到最新版本
# --- 数据迁移 ---
neocode migrate context-budget 🔧 迁移 context.auto_compact → context.budget
--dry-run, --config
4. 分模块设计细节
4.1 neocode config — 新命令 ⬜
适用范围:仅暴露 Config 结构体中的顶层标量字段。嵌套对象(runtime、context、tools、memo、gateway)引导用户编辑 ~/.neocode/config.yaml。
支持的可配置 key(对应 Config struct 的 YAML tag):
| CLI key |
YAML 路径 |
类型 |
说明 |
tool_timeout_sec |
tool_timeout_sec |
int |
工具调用超时秒数 |
generate_start_timeout_sec |
generate_start_timeout_sec |
int |
模型生成启动超时秒数 |
shell |
shell |
string |
默认 shell 路径 |
selected_provider |
selected_provider |
string |
当前激活的 provider(建议用 neocode use 代替) |
current_model |
current_model |
string |
当前激活的 model(建议用 neocode model set 代替) |
子命令:
neocode config get <key>
# 读取并输出单个配置值
# 示例:neocode config get tool_timeout_sec → "120"
neocode config set <key> <value>
# 修改单个配置值,写入前经过 ValidateSnapshot 校验
# 示例:neocode config set tool_timeout_sec 60
# 示例:neocode config set shell /usr/bin/zsh
错误处理:
- 不存在的 key → 提示可用 key 列表
- 类型不匹配 → 提示期望类型(如 "tool_timeout_sec 需要整数")
- 校验失败 → 透传
ValidateSnapshot 的错误信息,不写入
实现路径:internal/cli/config_commands.go,通过 config.Manager.Update() 执行变更。
4.2 neocode gateway — 调整策略 🔧
当前状态:通过 neocode gateway 暴露,同时有独立二进制 neocode-gateway(通过 NewGatewayStandaloneCommand)。
调整:保留为可见命令,不隐藏。理由:
- 高级用户和开发者需要显式控制 gateway 参数(
--log-level、--metrics-enabled、--acl-mode 等十余项 flags)
neocode-gateway 独立部署场景需要对应的 CLI 文档入口
- 30 秒空闲自动回收已由
gatewayIdleShutdownController 实现,无需隐藏命令来保证
4.3 neocode migrate — 调整策略 🔧
当前状态:neocode migrate context-budget 负责将旧 context.auto_compact schema 迁移到 context.budget,支持 --dry-run 预览和 --config 指定路径。
调整:保留为可见命令,不隐藏。理由:
--dry-run 让用户在迁移前预览变更,避免静默修改 config.yaml 导致的意外
- 迁移失败时备份文件(
MigrateContextBudgetConfigFile 自动创建 .bak)需要用户感知
- 静默迁移失败只会记日志,用户可能长时间不知道 config 未升级
4.4 neocode diag diagnose 去留
neocode diag 和 neocode diag diagnose 功能完全等价(都调用 runDiagDiagnoseCommand)。建议保留两者:diag 是快捷入口,diag diagnose 是显式语义别名。无需调整。
5. 用户场景故事
场景一:配置新的大模型供应商(✅ 已实现)
小明刚下载 NeoCode,想用公司内部署的 DeepSeek 模型。过去他必须手写 ~/.neocode/providers/deepseek/provider.yaml,缩进错误导致启动崩溃。
# 一行命令完成挂载,屏蔽底层 YAML
$ neocode provider add deepseek --driver openaicompat \
--url "https://api.deepseek.com/v1" \
--api-key-env DEEPSEEK_KEY
# 输出: ✅ 提供商 deepseek 添加成功,当前模型: deepseek-chat
# 切换为全局使用
$ neocode use deepseek
# 输出: ✅ 已全局切换到供应商: deepseek
场景二:查看和切换模型(✅ 已实现)
小红想看看当前 provider 有哪些可用模型,并切换到 Claude Sonnet。
$ neocode model ls
# 供应商: anthropic
# 当前模型: claude-haiku-4-5-20251001
# 可用模型:
# claude-haiku-4-5-20251001 (Claude Haiku 4.5)
# * claude-sonnet-4-6 (Claude Sonnet 4.6)
# claude-opus-4-7 (Claude Opus 4.7)
$ neocode model set claude-sonnet-4-6
# 输出: ✅ 已切换模型: claude-sonnet-4-6
场景三:解决版本更新后的环境冲突(✅ 已实现)
老李更新 NeoCode 后执行 neocode shell,终端疯狂报错 execute_system_tool failed。过去他要用 ps aux | grep neocode 配合 kill -9 手动清理旧 daemon 进程。
# 查看 daemon 状态
$ neocode daemon status
# {"status":"ok","listen_address":"127.0.0.1:18921","running":true,...}
# 卸载旧的 daemon 自启动
$ neocode daemon uninstall
# {"status":"ok"}
# 重新安装并启动
$ neocode daemon install
$ neocode daemon serve
场景四:修改工具超时(⬜ 待实现)
小张的网络环境不稳定,web_fetch 工具经常超时。他不想打开 vim 小心翼翼地改 YAML 缩进。
# 查看当前超时值
$ neocode config get tool_timeout_sec
# 120
# 调整到 180 秒
$ neocode config set tool_timeout_sec 180
# ✅ tool_timeout_sec 已更新为 180
场景五:生成可分享的唤醒链接(✅ 已实现)
运维小王想让 NeoCode review 一个日志文件,但不想教对方怎么进 TUI。他生成一个可点击链接发给同事。
$ neocode daemon encode review --path /var/log/app.log --workdir /home/ops
# http://neocode:18921/review?path=%2Fvar%2Flog%2Fapp.log&workdir=%2Fhome%2Fops
场景六:开发者调试 Gateway(🔧 已实现,保留暴露)
开发者小陈怀疑 gateway 的 IPC 连接数限制导致请求排队。他显式启动 gateway 并开启 metrics。
$ neocode gateway --log-level debug --metrics-enabled --ipc-max-connections 100
# neocode-gateway: starting gateway (log-level=debug)
# neocode-gateway: gateway ipc listen address: /tmp/neocode-gateway-xxx.sock
# neocode-gateway: gateway network listen address: 127.0.0.1:18920
6. 落地清单
| # |
任务 |
状态 |
涉及文件 |
| 1 |
provider add/ls/rm 命令 |
✅ 已实现 |
internal/cli/provider_commands.go |
| 2 |
use <provider> 命令 |
✅ 已实现 |
internal/cli/use_command.go |
| 3 |
model ls/set 命令 |
✅ 已实现 |
internal/cli/model_commands.go |
| 4 |
daemon serve/install/uninstall/status/encode |
✅ 已实现 |
internal/cli/daemon_commands.go |
| 5 |
shell / shell --init / diag / diag auto |
✅ 已实现 |
internal/cli/shell_diag_commands.go |
| 6 |
version / update |
✅ 已实现 |
internal/cli/version_command.go、update_command.go |
| 7 |
gateway 保留暴露(不隐藏) |
🔧 当前已暴露,无需改动 |
internal/cli/gateway_commands.go |
| 8 |
migrate 保留可见(不隐藏) |
🔧 当前已暴露,无需改动 |
internal/cli/migrate_command.go |
| 9 |
config get <key> |
⬜ 待实现 |
新建 internal/cli/config_commands.go |
| 10 |
config set <key> <value> |
⬜ 待实现 |
同上 |
7. 验收标准
- 现有命令行为不变:
neocode shell --init、neocode diag auto on/off 等已实现命令的回归测试通过。
- config get:
neocode config get tool_timeout_sec 输出当前整数值。
neocode config get no_such_key 输出友好错误并列出可用 key。
- config set:
neocode config set tool_timeout_sec 60 写入成功,再次 get 验证。
neocode config set tool_timeout_sec abc 被拒绝(类型校验)。
- 写入后的
config.yaml 保持 YAML 格式和注释不丢失。
- Provider 闭环:
neocode provider add → neocode provider ls → neocode use <name> → neocode model ls → neocode provider rm <name> 全链路可跑通。
- Daemon 闭环:
neocode daemon install → neocode daemon status → neocode daemon uninstall 链路正常。
8. 风险与回滚
- 风险:
config set 修改 config.yaml 时可能破坏 YAML 格式或丢失注释。
- 缓解策略:通过
config.Manager.Update() 执行写入,该路径已有 ValidateSnapshot 校验保护;写入前创建 .bak 备份(复用现有 migrate 的备份模式)。
- 回滚:若
config 命令引入问题,用户可直接编辑 YAML 文件作为后备路径。
RFC: NeoCode 命令行体验 (CLI UX) 重新设计
1. 目标问题 (Why)
随着 NeoCode 架构的快速演进,当前 CLI 命令树暴露出以下体验与规范问题:
gateway与daemon两个底层系统概念直接暴露给普通用户,且 daemon 生命周期管理不直观(如残留旧进程需要手动kill)。providers/目录实现,过去用户必须手写 YAML,缩进错误即导致启动崩溃。2. 设计原则与命名规范
2.1 命名规范
采用务实混合模式,区分两类命令:
<verb> <args>neocode、neocode shell、neocode use <provider>、neocode diag<noun> <verb> <args>neocode provider add、neocode model ls、neocode daemon status判断标准:如果该命令 90% 的使用场景就是做一件事,用动作命令;如果一个名词下有多个正交操作,用资源命令。
use作为顶级动词而非provider use的理由:切换 provider 是用户每天可能执行的最频繁操作,额外嵌套一级没有信息增益——用户说"我要用 DeepSeek"自然就是neocode use deepseek。2.2 配置哲学
config list——全量查看去配置文件本身即可,CLI 只做单点读写。3. 完整命令树
标记说明:✅ 已实现 | ⬜ 待实现 | 🔧 待调整
4. 分模块设计细节
4.1
neocode config— 新命令 ⬜适用范围:仅暴露
Config结构体中的顶层标量字段。嵌套对象(runtime、context、tools、memo、gateway)引导用户编辑~/.neocode/config.yaml。支持的可配置 key(对应
Configstruct 的 YAML tag):tool_timeout_sectool_timeout_secgenerate_start_timeout_secgenerate_start_timeout_secshellshellselected_providerselected_providerneocode use代替)current_modelcurrent_modelneocode model set代替)子命令:
错误处理:
ValidateSnapshot的错误信息,不写入实现路径:
internal/cli/config_commands.go,通过config.Manager.Update()执行变更。4.2
neocode gateway— 调整策略 🔧当前状态:通过
neocode gateway暴露,同时有独立二进制neocode-gateway(通过NewGatewayStandaloneCommand)。调整:保留为可见命令,不隐藏。理由:
--log-level、--metrics-enabled、--acl-mode等十余项 flags)neocode-gateway独立部署场景需要对应的 CLI 文档入口gatewayIdleShutdownController实现,无需隐藏命令来保证4.3
neocode migrate— 调整策略 🔧当前状态:
neocode migrate context-budget负责将旧context.auto_compactschema 迁移到context.budget,支持--dry-run预览和--config指定路径。调整:保留为可见命令,不隐藏。理由:
--dry-run让用户在迁移前预览变更,避免静默修改 config.yaml 导致的意外MigrateContextBudgetConfigFile自动创建.bak)需要用户感知4.4
neocode diag diagnose去留neocode diag和neocode diag diagnose功能完全等价(都调用runDiagDiagnoseCommand)。建议保留两者:diag是快捷入口,diag diagnose是显式语义别名。无需调整。5. 用户场景故事
场景一:配置新的大模型供应商(✅ 已实现)
场景二:查看和切换模型(✅ 已实现)
场景三:解决版本更新后的环境冲突(✅ 已实现)
场景四:修改工具超时(⬜ 待实现)
场景五:生成可分享的唤醒链接(✅ 已实现)
$ neocode daemon encode review --path /var/log/app.log --workdir /home/ops # http://neocode:18921/review?path=%2Fvar%2Flog%2Fapp.log&workdir=%2Fhome%2Fops场景六:开发者调试 Gateway(🔧 已实现,保留暴露)
6. 落地清单
provider add/ls/rm命令internal/cli/provider_commands.gouse <provider>命令internal/cli/use_command.gomodel ls/set命令internal/cli/model_commands.godaemon serve/install/uninstall/status/encodeinternal/cli/daemon_commands.goshell / shell --init / diag / diag autointernal/cli/shell_diag_commands.goversion / updateinternal/cli/version_command.go、update_command.gogateway保留暴露(不隐藏)internal/cli/gateway_commands.gomigrate保留可见(不隐藏)internal/cli/migrate_command.goconfig get <key>internal/cli/config_commands.goconfig set <key> <value>7. 验收标准
neocode shell --init、neocode diag auto on/off等已实现命令的回归测试通过。neocode config get tool_timeout_sec输出当前整数值。neocode config get no_such_key输出友好错误并列出可用 key。neocode config set tool_timeout_sec 60写入成功,再次get验证。neocode config set tool_timeout_sec abc被拒绝(类型校验)。config.yaml保持 YAML 格式和注释不丢失。neocode provider add→neocode provider ls→neocode use <name>→neocode model ls→neocode provider rm <name>全链路可跑通。neocode daemon install→neocode daemon status→neocode daemon uninstall链路正常。8. 风险与回滚
config set修改config.yaml时可能破坏 YAML 格式或丢失注释。config.Manager.Update()执行写入,该路径已有ValidateSnapshot校验保护;写入前创建.bak备份(复用现有 migrate 的备份模式)。config命令引入问题,用户可直接编辑 YAML 文件作为后备路径。