# Knowledge Shell Process And Worktree

> Covers Bash 前后台执行、stdin/终止、输出有界化、进程树与持久租约、Workspace 写沙箱，以及托管 Git worktree 的隔离和交付。 Navigate when: 排查命令超时/取消/残留进程、后台 Shell、输出截断、ACP terminal、审计沙箱、worktree 创建/恢复/应用/清理。 Excludes: 通用工具权限和 scheduler（见 ../tool-execution-pipeline/）、文件补丁事务（见 ../filesystem-search-and-atomic-patching/）。 Keywords: Bash, WriteStdin, KillShell, BackgroundShellManager, DurableProcessLeaseStore, OwnedProcessTree, WorkspaceWriteSandbox, WorktreeManager, foreground handoff.

- Skill: `echovic/knowledge-shell-process-and-worktree` (Agent Skill)
- Install (CLI): `npx skillmds@latest add echovic/knowledge-shell-process-and-worktree`
- Raw SKILL.md: https://api.skillmd.com/api/skills/echovic/knowledge-shell-process-and-worktree/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: echovic (https://skillmd.com/u/echovic)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/echovic/knowledge-shell-process-and-worktree

---


## Module Structure

该节点连接命令执行与 workspace 隔离。Bash 可走本地、ACP 或沙箱路径，并把长前台
命令原进程移交为后台任务；worktree 管理器则将 Session 映射到独立 Git 工作目录并
在交付前验证源工作区没有漂移。

### Directory Layout
- `packages/cli/src/tools/builtin/shell/` — Bash、后台管理、stdin、终止与输出捕获
- `packages/cli/src/context/storage/DurableForegroundProcess.ts` — 前台命令租约与 handoff
- `packages/cli/src/context/storage/DurableProcessLeaseStore.ts` — 可恢复的进程身份租约
- `packages/cli/src/utils/process/` — 启动闸门、进程组拥有权和跨平台终止
- `packages/cli/src/utils/shell/` — 命令归一化、只读审计和验证命令识别
- `packages/cli/src/worktree/WorktreeManager.ts` — worktree 生命周期、diff 制品和变更交付
- `packages/cli/src/tools/builtin/worktree/worktreeTools.ts` — Agent 可调用的进入/退出适配器

### Key Entry Points
- `bashTool` in `packages/cli/src/tools/builtin/shell/bash.ts` — 本地、ACP、后台与自动 handoff 分流
- `BackgroundShellManager` in `packages/cli/src/tools/builtin/shell/BackgroundShellManager.ts` — Session-owned Shell 生命周期
- `prepareForegroundProcess()` in `packages/cli/src/context/storage/DurableForegroundProcess.ts` — 先持久登记再释放命令启动闸门
- `WorktreeManager.enter()` / `apply()` / `exit()` in `packages/cli/src/worktree/WorktreeManager.ts` — 隔离、交付和离开工作树

## Gotchas
- Bash 明确是 `isRetrySafe=false`；即使抛出 `EBUSY/EAGAIN` 也不能自动重放，因为命令可能已经产生外部副作用 (`packages/cli/src/tools/builtin/shell/bash.ts`, `packages/cli/tests/unit/tooling/tools/builtin/bash.test.ts`)
- `Bash` 的 `isConcurrencySafe=false` 但显式 `parallelism='shared'`：独立命令可同批进入，仍受 execute bucket 限流；由于没有 `file_path`，通用 FileLockManager 不会替 Shell 串行工作区写入 (`packages/cli/src/tools/builtin/shell/bash.ts`, `packages/cli/src/tools/execution/ToolExecutor.ts`)
- ACP terminal 执行设置 `allowLocalFallback=false`；远端终端失败必须原样失败，不能在宿主机悄悄重跑同一命令 (`packages/cli/src/tools/builtin/shell/bash.ts`, `git:27f9df37`)
- `WriteStdin` 会产生外部可见输入且默认不可重放，最多接受 64 KiB；ACP 后台终端当前不支持 stdin 写入 (`packages/cli/src/tools/builtin/shell/writeStdin.ts`, `packages/cli/tests/unit/tooling/tools/builtin/write-stdin.test.ts`)
- 前台自动转后台复用原进程，不重启命令；只有存在 Session、超时大于 handoff budget、非只读审计代理且首个命令不是 `sleep` 时才有资格 (`packages/cli/src/tools/builtin/shell/ForegroundCommandHandoff.ts`, `packages/cli/src/tools/builtin/shell/bash.ts`)
- foreground → background 租约提交失败时，前台 owner 仍保持权威并继续等待；不能同时把两个 lease 当作有效所有者 (`packages/cli/src/context/storage/DurableForegroundProcess.ts`, `packages/cli/src/tools/builtin/shell/bash.ts`)
- 后台 Shell ID 绑定 Session；TaskOutput、WriteStdin、KillShell 用其他 Session ID 查询时都按不存在处理，不能跨会话接管 (`packages/cli/src/tools/builtin/shell/BackgroundShellManager.ts`, `packages/cli/src/tools/builtin/task/taskOutput.ts`)
- 本地前后台输出各流只保留最后 1 MiB，随后还会按命令类型二次投影；`stdout_total_bytes`/`omitted_bytes` 才能区分“命令没输出”和“早期输出已丢弃” (`packages/cli/src/tools/builtin/shell/BoundedOutputBuffer.ts`, `packages/cli/src/tools/builtin/shell/ShellOutputProjection.ts`)
- worktree 从 committed `HEAD` 创建，原工作区未提交改动不会复制；返回的 `sourceHadChanges` 是警告，不代表新 worktree 包含这些内容 (`packages/cli/src/worktree/WorktreeManager.ts`, `packages/cli/src/tools/builtin/worktree/worktreeTools.ts`)
- worktree 交付要求源仓库 HEAD 和创建时工作状态指纹都未变化；只检查 patch 可应用而忽略源状态会覆盖任务期间的用户改动 (`packages/cli/src/worktree/WorktreeManager.ts`)
- `ExitWorktree(action='remove')` 在无法验证状态或存在未提交文件/未合并 commit 时拒绝，只有用户明确允许 `discard_changes=true` 才强制删除 (`packages/cli/src/worktree/WorktreeManager.ts`, `packages/cli/src/tools/builtin/worktree/worktreeTools.ts`)
- stale worktree GC 只删除符合托管命名、足够旧、Git 身份一致且无脏文件/未推送 commit 的目录；异常目录和活跃 Session 均保留 (`packages/cli/src/worktree/WorktreeManager.ts`)

## Architecture
- 命令启动经过独立 Node admission gate：目标子进程仅在 lease 持久化后收到启动字节，owner 消失时 gate 负责终止进程组，关闭了“进程已启动但尚未登记”的崩溃窗口 (`packages/cli/src/utils/process/CommandAdmissionGate.ts`, `packages/cli/src/context/storage/DurableForegroundProcess.ts`)
- `DurableProcessLeaseStore` 同时记录 owner 与 root PID 的平台指纹；恢复时先识别活 owner，再验证 PID 未复用，POSIX leader 已退出但进程组仍活跃时单独清理 leaderless group (`packages/cli/src/context/storage/DurableProcessLeaseStore.ts`, `packages/cli/src/utils/process/ProcessIdentity.ts`)
- `BackgroundShellManager` 统一管理本地后台、自动 handoff 和 ACP 外部前台候选，默认最多 16 个全局活动进程、每 Session 4 个 (`packages/cli/src/tools/builtin/shell/BackgroundShellManager.ts`)
- worktree manager 以 Session keyed mutex 串行生命周期操作，目录位于按仓库路径哈希隔离的 managed root，分支名同时包含逻辑名称和 Session 哈希 (`packages/cli/src/worktree/WorktreeManager.ts`)
- 任务交付使用临时 Git index 收集 tracked/untracked 变更，生成 binary patch，先 `git apply --check` 再应用到源工作区，不通过 merge 或复制目录 (`packages/cli/src/worktree/WorktreeManager.ts`)

## Decisions
- managed worktree 同时服务显式 Enter/Exit 工具和子代理任务隔离；工具层只负责用户交互，实际恢复、差异和交付语义集中在 `WorktreeManager` (`packages/cli/src/tools/builtin/worktree/worktreeTools.ts`, `packages/cli/src/agent/subagents/SubagentWorktreeLifecycle.ts`, `git:c80db2c1`)
- 后台与前台命令都升级为持久 lease 和 owned process tree，以便 Session 恢复时回收 orphan，而不是只依赖当前 Node 子进程句柄 (`packages/cli/src/context/storage/DurableProcessLeaseStore.ts`, `git:c012135e`, `git:cbe0e8ed`)
- 输出限制分为 capture 上限和模型/UI projection 上限，既限制常驻内存又保留完整计数事实，避免单纯截断字符串后无法判断损失量 (`packages/cli/src/tools/builtin/shell/ShellOutputCapture.ts`, `packages/cli/src/tools/builtin/shell/OutputTruncator.ts`, `git:81a9acc9`)

## Patterns
- 本地 POSIX 子进程作为 detached group leader 启动，终止先发 `SIGTERM` 再在 grace period 后发 `SIGKILL`；Windows 使用 `taskkill /T` 并保留直接 child fallback (`packages/cli/src/utils/process/OwnedProcessTree.ts`)
- workspace-required 或只读审计 Bash 会先生成沙箱命令；cwd 在 lexical 与 realpath 两层都必须位于 workspace，沙箱启动失败按 permission denied fail closed (`packages/cli/src/tools/builtin/shell/WorkspaceWriteSandbox.ts`, `packages/cli/src/tools/builtin/shell/bash.ts`)
- 只读审计沙箱不继承任意进程环境、禁止网络和 workspace 写入，只允许专用临时目录写入及受信任 PATH 中的运行时；普通 worktree 沙箱允许 workspace 写入 (`packages/cli/src/tools/builtin/shell/WorkspaceWriteSandbox.ts`)
- SessionRuntime 启动时先回收 foreground/background orphan，关闭时主动 kill 本 Session 后台进程并释放 worktree 内存绑定 (`packages/cli/src/agent/runtime/SessionRuntime.ts`)

## Resource Bounds
- 后台与前台 capture 分别为 stdout/stderr 各 1 MiB，并最多保留 32 个 chunk；超大 chunk 从 UTF-8 边界保留尾部 (`packages/cli/src/tools/builtin/shell/BoundedOutputBuffer.ts`)
- worktree diff 最多 100 个文件、单文件 1 MiB、总计 2 MiB；真正交付的 binary patch 上限为 50 MiB，展示截断不改变交付内容 (`packages/cli/src/worktree/WorktreeManager.ts`)
- 后台容量耗尽返回 `RESOURCE_EXHAUSTED/background_shell_busy` 且可稍后重试，不会排队等待并额外占用内存 (`packages/cli/src/tools/builtin/shell/BackgroundShellManager.ts`, `packages/cli/src/tools/builtin/shell/bash.ts`)

