Archive note(2026-06-05,document-system-governance):本计划已移出
active/,归入deferred/——用户明确暂缓,未来可能重启。不是当前任务入口;当前工作入口见 exec-plans README,重启方式见 deferred/README.md。
⏸ 本轮重构暂缓(见 refactor-closeout.md "暂缓清单")— 终端会话层 / git 工作区状态层不在本轮 6 条主线内;保留作长期参考。
创建时间:2026-03-12 最后更新:2026-03-12 参考基线:Codex
main@917c2df(本地参考副本:/tmp/codex-main-latest)
| Area | 目标 | 状态 | 备注 |
|---|---|---|---|
| Terminal | 独立终端会话层 | 📋 待开始 | 参考 Codex command/exec 语义 |
| Git | 工作区 git 状态层 | 📋 待开始 | 先做只读,再做变更操作 |
| Approval | 终端 / git 统一审批 | 📋 待开始 | 复用现有 permission 机制 |
| UI | 底部终端面板 + repo 状态栏 | 📋 待开始 | 尽量不打断现有聊天主链路 |
- 让 CodePilot 拥有类似 Codex 的“可观察、可控制、可审批”的终端执行层,而不是只显示 Claude SDK 工具输出。
- 让 git 从“用户自己在外部终端运行命令”升级为应用内的一等工作区状态服务。
- 保持现有桌面聊天主链路稳定:
remote disabled = current desktop behavior unchanged。
- 第一阶段不做完整 IDE 式 Source Control 面板。
- 第一阶段不做复杂 git 流程 UI,如 rebase、cherry-pick、conflict editor。
- 第一阶段不重写现有 Claude Agent SDK 聊天链路。
- 第一阶段不把终端能力直接塞进 Electron
main/preload的零散 IPC。
- Electron 主进程已经会读取用户 login shell 环境,并构造扩展后的
PATH,再传给内部服务进程。 - Claude SDK 子进程也继承了工作目录、环境变量、权限模式和 Git Bash 探测逻辑。
- 聊天流里已经能显示
tool_use、tool_result、tool_progress,也已经有权限审批持久化与恢复。
- 还没有“独立终端会话”概念。前端目前只能消费聊天流中的工具事件,没有
start/write/resize/terminate这类终端控制面。 preload只暴露了openPath、目录选择、安装器和 bridge 状态,没有终端或 git IPC。- 数据层只有
chat_sessions.working_directory/sdk_session_id,没有 repo root、branch、HEAD、dirty、remote diff 等 git 元数据。 - git 相关逻辑仍以“Claude 工具可能调用 git”或“外部终端自己执行”为主,应用本身没有统一 git service。
Codex 的关键不是“会跑命令”,而是把命令执行抽象成独立协议:
command/exec有明确的processId、tty、streamStdin、streamStdoutStderr、timeoutMs、cwd、env、sandboxPolicy。- 跟随接口有
command/exec/write、command/exec/resize、command/exec/terminate。 - 终端输出不是一次性结果,而是流式 delta。
- 会话管理是连接级的,不是“临时跑一个 shell 命令然后丢掉”。
Codex 不只在启动时读取一次环境,而是有 shell_snapshot 机制,为每个 session 生成并校验 shell 快照文件,解决别名、导出变量、shell 初始化脚本差异等问题。
Codex 既有轻量 git 探测,也有专门的 git tooling:
- 轻量层负责 repo root、HEAD、branch、remote、dirty、recent commits、diff-to-remote。
- tooling 层负责 git 仓库校验、repo root 解析、路径归一化、命令错误上下文。
gitDiffToRemote是独立接口,不把“比较当前工作区和远端”塞到 UI 层临时拼接。
在现有 Next.js server 进程内新增一个独立的运行时层,建议放在:
src/lib/workspace-runtime/terminal-session-manager.tssrc/lib/workspace-runtime/git-service.tssrc/lib/workspace-runtime/approval-broker.ts
职责拆分:
TerminalSessionManager负责终端 session 生命周期、PTY / pipe 管理、输出流、stdin 写入、resize、terminate、超时和清理。GitService负责 repo 探测、repo root、branch、HEAD、dirty、remote URLs、recent commits、diff to remote。ApprovalBroker负责把“Claude 工具权限请求”和“应用内终端 / git 高风险操作”收口到一个审批模型。
不必照搬 Codex 的 JSON-RPC / WebSocket 形态,但建议尽量复用它的语义。
POST /api/terminal/sessions创建终端会话,参数包含cwd、shellProfile、envOverrides、tty、cols、rows。GET /api/terminal/sessions/:id/stream通过 SSE 推送 stdout / stderr / exit / error / metadata。POST /api/terminal/sessions/:id/write写入 stdin。POST /api/terminal/sessions/:id/resize调整 PTY 大小。POST /api/terminal/sessions/:id/terminate终止会话。
GET /api/git/status?cwd=...GET /api/git/diff-to-remote?cwd=...GET /api/git/commits?cwd=...&limit=...GET /api/git/branches?cwd=...
原则:
- Phase 1 只提供只读接口。
- 变更类接口如
stage、unstage、commit、checkout放到后续阶段。
- 底部抽屉式终端面板,默认折叠,不打断聊天。
- 同一工作目录允许多个终端 tab,但同一 chat session 默认绑定一个“主终端”。
- 前端建议使用
xterm.js+xterm-addon-fit。
- 会话头部显示 repo 状态:仓库名 / branch / dirty / ahead-behind。
- 聊天页侧边或 Inspector 区域增加 Git 卡片:
- 当前分支
- 最近提交
- 与远端 diff 摘要
- 未提交文件计数
- 当 Claude 触发 git 命令时,审批卡片展示 repo root、命令分类和风险等级。
- 当用户直接从终端面板触发高风险操作时,也走同一审批中心,而不是绕开现有 permission 体系。
目标:先把终端 / git 从“实现细节”提升为产品层能力。
任务:
- 定义
TerminalSession、TerminalEvent、GitWorkspaceState、GitDiffSummary类型。 - 抽出
workspace-runtime目录,不把逻辑继续堆到electron/main.ts或claude-client.ts。 - 约定审批模型:哪些终端命令 / git 操作要走审批,哪些在 Full Access 下可自动放行。
交付标准:
- 类型、API 契约、错误码和 UI 事件模型先固定下来。
目标:先拿到“像终端一样工作的终端”。
实现建议:
- 后端 MVP 使用
node-pty,挂在当前 Next.js server 进程中。 - 通过接口封装 PTY 实现,保留未来替换成 sidecar / Rust helper 的空间。
- 会话创建时继承当前 Electron 已构造好的环境,并保留
envOverrides能力。 - 支持:
- 创建 session
- 实时输出
- stdin 写入
- resize
- terminate
- idle / exit 清理
暂不做:
- 会话恢复
- 复杂 shell snapshot
- 多 Host / 远程共享终端
目标:先把 git 状态变成产品内可见上下文。
实现建议:
- 建一个
GitService,集中封装所有 git 命令,统一超时和错误处理。 - 参考 Codex 做法:
- repo root 检测
- HEAD / branch / remote URL
- dirty 状态
- recent commits
- diff to remote
- 所有 git 调用都设置短超时,避免大仓卡 UI。
建议新增缓存:
- 进程内 LRU 缓存,用于最近一次 git 状态读取。
- 如需持久化,只缓存快照,不缓存“事实真相”;真相仍以实时 git 命令为准。
目标:把终端和 git 变成聊天场景的原生上下文,而不是外挂面板。
任务:
- 每次 session 切换时同步当前
GitWorkspaceState。 - 在 Claude 权限请求里增强 git 命令展示:
- 命令分类(只读 / 写索引 / 写工作区 / 远端网络)
- 目标 repo
- 可能影响的路径
- 聊天页支持从消息上下文跳到对应终端输出或 git 状态卡片。
关键决定:
- Claude SDK 工具输出仍保留。
- 但“独立终端面板”不依赖 Claude 消息流才能工作。
目标:在只读稳定后,再开放少量高价值写操作。
优先顺序:
stage / unstagecommitcheckout existing branchcreate branch
继续后置:
- rebase
- merge conflict resolution
- interactive staging hunk editor
目标:解决“终端环境”和“Claude SDK 环境”长期不一致的问题。
建议:
- 先继续沿用当前 Electron
loadUserShellEnv()方案作为 MVP 基线。 - 待 Terminal MVP 稳定后,再引入类似 Codex 的 per-session shell snapshot:
- 生成 shell bootstrap 文件
- 校验可执行性
- 让终端与 Claude SDK 共用同一环境基线
这样可以避免一次性把复杂度全部压进首版。
- 不在 Electron
preload里继续堆大量终端 / git IPC;核心状态应留在 server 进程。 - 不直接把 git 逻辑散落到页面组件;必须集中到
GitService。 - 不让 Terminal MVP 依赖 Claude SDK;它应该可以单独工作。
- 传输层可以保留现有 HTTP + SSE 风格,但语义尽量对齐 Codex 的
command/exec。 - Windows 继续沿用现有
findGitBash()与 shell 兼容逻辑,不额外发明新约定。
规避:
- 放在隔离的 manager 抽象后面。
- 首版只做 macOS / Linux 稳定,Windows 作为兼容目标但不阻塞 Phase 1。
规避:
- 所有 git 调用统一超时。
- 使用只读快速命令优先,如
status --porcelain、rev-parse、remote -v。
规避:
- 首版承认现状,统一走 Electron 已加载的环境。
- 后续用 shell snapshot 收敛。
规避:
- 应用内终端 / git 高风险操作接入同一审批中心。
- 不做第二套“终端专用审批 UI”。
- Phase 0:先定契约和数据模型
- Phase 1:终端 MVP
- Phase 2:git read-only MVP
- Phase 3:聊天链路集成
- Phase 4:git 变更操作
- Phase 5:shell snapshot
electron/main.ts继续负责外层环境准备和 server 启动,但不承载终端会话细节。src/lib/claude-client.ts保留 Claude SDK 集成;后续只增强审批和 git 上下文展示。src/app/api/chat/permission/route.ts继续作为审批落点,后续扩展为终端 / git 共用审批入口。src/lib/db.ts后续需要补充 git 快照或终端审计相关表,但不建议把终端实时输出写进 DB。
如果继续推进,建议下一步直接做:
- Phase 0 的类型与 API 契约草案
- Terminal MVP 的 manager 骨架
- GitService 的只读接口骨架
这样能最快把“讨论”转成可跑的基础设施。