跳转至

托管工作树

托管工作树为代理任务提供独立的 Git 分支和检出,而不在源仓库中放置临时目录。OpenClaw 会在共享状态数据库中记录它们,并在移除前对其已跟踪内容以及未被忽略的未跟踪内容进行快照。

沙箱会话

沙箱项目会话使用私有的仅源码 Git 检出来执行, 而托管工作树仍是已接受变更的规范所有者。 Docker 和 Podman 支持此本地投影。主机仓库的共享 Git 元数据和忽略文件配置不会挂载或复制到其中。 参见 Workspace access 了解写入策略、协调和冲突恢复。

投影绑定和待处理协调日志是增量 SQLite 状态。它们不会更改数据库版本。降级前,请让待处理 工作区操作完成。旧版本不会协调这些投影; 它们会保持其增量状态和私有文件完整。返回支持 版本以恢复待处理变更,而不是删除投影目录。

选择工作树的存储位置

默认情况下,OpenClaw 将托管检出于 <openclaw-state-dir>/worktrees 下存储。在 openclaw.json 中设置全局 worktreeRoot 选项以使用其他文件夹或磁盘:

{
  worktreeRoot: "/mnt/workspaces/openclaw-worktrees",
}

在 Gateway 主机上使用绝对路径,使用 ~ 表示 Gateway 用户的主目录,或使用以 ~/ 开头的路径表示其中的文件夹。相对路径会被拒绝。Gateway 用户必须能够创建并写入该目录。

此设置适用于所有托管工作树,包括会话、手动和 Workboard 工作树;没有按代理覆盖。它仅更改检出存储。共享状态数据库、已配置忽略文件的快照、分配限制和清理生命周期仍与同一 OpenClaw 状态目录关联。

更改 worktreeRoot 会影响新分配。现有已注册工作树会保留其记录的路径以供复用和清理,已移除的工作树会恢复到其原始路径。当此设置更改时,OpenClaw 不会移动现有检出或快照。在不再需要这些工作树之前,请保持其原始存储可用。

在默认的状态所有工作树目录之外,清理仅作用于已注册工作树和加速模板。它会保留自定义位置中无关的未注册文件夹。

参见 Configuration reference 了解该选项的默认值和范围。

文件系统加速

OpenClaw 在受支持时会自动为新托管工作树使用文件系统加速。Linux 使用原生 Btrfs 快照,无需 btrfs 命令。macOS 使用原生 APFS 目录克隆,保留独立的文件内容、可执行模式和符号链接。Windows 使用 ReFS 块克隆,包括在 Dev Drive 卷上。OpenClaw 将模板保留在与新检出相同的可写文件系统上;源仓库可以位于另一个文件系统上。具有检出过滤器、稀疏检出、按工作树配置或外部属性的 Git 配置使用普通 Git 检出。

若要退出,请设置:

{
  worktreeAcceleration: false,
}

省略该选项或将其设置为 true 会启用自动选择。将其设置为 false 会为新工作树使用普通 Git 检出和文件复制。现有工作树保留其内容和生命周期。NTFS、ext4、HFS+ 和其他不受支持的文件系统使用普通 Git 路径。不可用的原生绑定或失败的克隆也会回退到 Git;APFS 和 ReFS 文件数据克隆绝不会在加速路径中静默替换为普通文件复制。

APFS 和 Btrfs 操作使用隔离的原生辅助程序,不会更改 Gateway 进程的文件系统配置。Gateway 和这些辅助程序保留 fs-safe 的 auto 原生默认值。显式设置 FS_SAFE_NATIVE_MODE=off 或 OPENCLAW_FS_SAFE_NATIVE_MODE=off 也会禁用这些辅助程序。只读元数据工作器可以在取消时停止;恢复会等待写入辅助程序退出后再接触其目标。

在 Windows 上,将 worktreeRoot 指向 ReFS 卷上的目录,例如 D:\worktrees。ReFS 提供文件块克隆,而不是可写目录快照:OpenClaw 创建目录树并克隆每个文件的数据。完整簇可以共享存储;部分文件尾部和文件系统元数据仍会占用空间。Gateway 需要普通文件访问权限,而不是管理员访问权限,即可在现有卷上克隆工作树。

OpenClaw 为每个仓库和目的地根目录维护一个可复用的仅源码模板。当请求的提交或检出策略更改时,它会重建模板,清理会退役七天未使用的模板。Git 继续拥有工作树注册、索引和分支;文件系统后端提供共享文件内容。

没有文件数据的新检出,包括空会话工作区,使用普通 Git 检出,无需准备或克隆模板。

如果模板清理无法获取其分配租约或读取其缓存,OpenClaw 会记录警告并继续普通工作树和快照清理。稍后的清理过程会重试模板退役。

模板仅包含检出的源码。.worktreeinclude 配置和 .openclaw/worktree-setup.sh 仍会为每个新工作树单独运行,使用其现有权限。依赖项和设置输出不会通过模板共享。写时复制快照在文件更改前共享源存储;其实际节省取决于仓库和后续写入。

第一个加速工作树包含通过 Git 准备模板的成本。后续 APFS 工作树通过一次原生操作克隆整个目录。OpenClaw 在更新 Git 的缓存文件元数据之前,以有界原生批次读取共享数据流标识,避免对已证明未更改的文件重新读取内容。Git 元数据准备计入时间戳安全延迟,因此在克隆的时间戳边界之后完成它不会增加另一次等待。Git 仍会验证生成的索引并检测后续编辑;不受支持的索引格式和未验证文件会接受普通 Git 验证。

Apple 不鼓励通过 clonefile 进行通用目录克隆,但未公布完整理由。一个已验证的限制是,目录克隆不会将目标位置的继承 ACL 权限应用到后代。当目标父目录包含可继承 ACL 条目、模板根目录带有 ACL,或 ACL 检查失败时,OpenClaw 会使用常规 Git checkout。它会在克隆前后再次检查,以捕获准备期间发生的策略变更。仅目标父目录上的不可继承 ACL 不会禁用加速。权限继承由 Git 负责;OpenClaw 不会在克隆后重写 ACL。

快速路径仅限于 OpenClaw 的私有仅源模板;请勿在模板缓存中自定义 ACL。取消操作会等待已启动的原生克隆完成,然后恢复流程才能触及目标位置。

对于包含大量小文件的仓库,ReFS 克隆可能比原生 Git checkout 耗时更长,因为每个文件都需要独立元数据,并且 Git 会刷新其索引。如果 checkout 延迟比源存储节省更重要,请使用 worktreeAcceleration: false。

仓库源配置

完整源仍然是默认选项。在创建新工作树时,要选择仓库拥有的稀疏源配置:

openclaw worktrees create /path/to/repo --name gateway-task --source-profile gateway
openclaw worktrees create /path/to/repo --name combined-task --source-profile gateway --source-profile tooling

在 .openclaw/worktree-profiles/<name> 中跟踪纯 UTF-8 cone 目录列表。名称使用小写字母、数字和连字符(最多 64 个字符,以字母或数字开头)。每个非空行指定一个受跟踪的仓库相对目录;请勿使用注释、通配符、绝对路径或父目录遍历。所选列表按排序后的并集组合。Git cone 模式还会保留根目录和祖先目录中的文件。OpenClaw 会包含定义目录,以便选择结果仍可检查。

定义从不可变的 checkout 提交读取,而不是未提交的源文件。默认远程重试会从其回退提交重新加载定义。选择过程在忽略文件配置和 setup 之前完成。它不会请求依赖安装或构建,并且现有仓库 setup 脚本保留其独立策略。配置不能重新缩小已复用或已恢复的工作树;请选择一个新名称。

现有 --profile 选项仍用于选择运行时状态;--source-profile 仅用于选择仓库源:

openclaw --profile work worktrees create /path/to/repo --name task --source-profile gateway

在原生工作或全仓库检查之前,请有意展开:

git -C /path/to/worktree sparse-checkout disable

如果注册后稀疏物化失败,请保留部分 checkout 和 Git 注册信息以便恢复。使用相同名称重试不会缩小该部分状态;在选择新的工作树名称之前,请先检查它。

所选配置目前使用常规 Git checkout。Git 在设置稀疏规则时会启用按工作树共享的配置,因此该仓库后续的完整 checkout 也会使用 Git 回退,包括在原生完整展开之后。现有 checkout 保留其自身的源和索引。

然后运行单独请求的依赖/构建准备。PR 全仓库门禁仍需要完整源。稀疏 checkout 改变的是源物化,而不是共享 Git 对象或历史;它不是浅克隆。

布局和名称

每个工作树位于:

<worktreeRoot>/<repo-fingerprint>/<name>

仓库指纹是对规范 git common 目录和 origin URL 进行 SHA-256 哈希后的前 16 个十六进制字符。提供的名称必须匹配 [a-z0-9][a-z0-9-]{0,63}。如果没有提供名称,OpenClaw 会生成可读的甲壳类主题名称,例如 brisk-lobster。如果推断出的名称已被任何已注册工作树(包括调用者自身已删除的 checkout)、本地分支或未管理路径占用,则会添加数字后缀,例如 brisk-lobster-2;只有提供的名称才会复用或恢复调用者的现有记录。

OpenClaw 在请求的 base ref 处创建分支 openclaw/<name>。如果没有 base ref,它会 fetch origin,在可用时使用远程默认分支,并在仓库离线或没有可用远程时回退到本地 HEAD,包括指向已删除分支的过期 origin/HEAD。显式请求的 base 必须解析为提交;OpenClaw 永远不会用另一个 base 替代它。Git 首先注册该分支而不物化文件,保留其正常的上游跟踪规则。然后 OpenClaw 捕获该分支的提交,并将其用于大小估算、源模板和 checkout。之后对源 ref 的更改无法切换正在写入的文件,也无法复用较小提交的配额。

创建或快照恢复期间的 Git 工作树注册和源物化各自具有五分钟超时,包括从本地 HEAD 进行的创建重试。为大小估算获取缺失对象使用相同的五分钟预算。其他受管理工作树的 Git 命令保持两分钟超时,但已接受的 checkout 删除除外,它会等待完成。单独的 .openclaw/worktree-setup.sh 步骤也保留其自身的两分钟超时。

容量和磁盘空间

OpenClaw 将每个状态目录中的 100 个活动受管理工作树作为清理目标,而不是准入上限。仅凭数量永远不会阻止创建或快照恢复;可用磁盘空间仍然限制新分配。创建永远不会驱逐另一个会话以腾出空间。手动和受保护的工作树可能使总数高于清理目标。

在分配 checkout 之前,OpenClaw 会检查其目标位置、Git 元数据、源 checkout 和状态卷。它在每个卷上保留固定的 4 GiB 操作预留,再加上预估 Git checkout 和已配置文件大小的两倍。经过验证的可复用源模板会用克隆元数据和 Git 索引写入的估算值替代完整 Git checkout 配额。Btrfs 快照共享目录元数据;APFS 和 ReFS 克隆按受跟踪条目预算元数据,并包含 ReFS 卷分配大小。冷模板和每次原生 Git 回退都会在分配前再次要求完整 checkout 配额。已配置文件保留其独立的完整副本配额。可执行 setup 脚本需要额外空间,等于 4 GiB 或当前源 checkout 占用(不含 Git 元数据)中的较大者。空间会在配置/setup 之前和 setup 之后再次检查。无法获取容量读数时,分配会停止并返回可操作的错误。

对于部分克隆,OpenClaw 会先清点缺失对象,再估算检出大小,并从该克隆的 promisor 远程一次性批量获取它们。批量请求只请求缺失对象,不会把共享提交视为其内容已在本地可用的证明。大小清点不会触发按对象延迟获取。支持部分克隆,但对于注册表管理的项目,建议使用完整克隆,以便检出和恢复不依赖于缺失的远程对象。如果对象缺失且没有 promisor 远程,请在重试前获取或修复该克隆。Git 超时会报告其预算,并建议检查远程可达性、仓库锁和部分克隆行为。

瞬时获取失败(包括对象传输不完整)会在原始获取超时内等待一秒后重试一次。取消和过期的工作区权限会停止恢复;第二次失败会显示 Git 错误。参见重试策略。

Git 工作进程在保持活动状态期间会复用一组有界的成功提交大小估算。每次分配时都会检查对象可用性和空闲磁盘空间。Git 替换引用会使受影响的尺寸估算不可复用,工作进程关闭时会丢弃它们。

创建、恢复、删除、孤儿清理和快照过期会在同一状态目录下的仓库和进程之间共享一个分配租约。这可防止清理删除未完成的检出或正在恢复的快照。请求最多等待该租约 10 分钟,以便缓慢的检出或清理工作完成后再报告争用。调用方取消和整体请求限制可以更早停止等待。上述单独的 Git 超时和设置超时仍然适用。同一卷上的开销会累加。这些检查是保守估算,而不是磁盘配额:其他 OpenClaw 状态目录、shell 命令、部署工具以及任意设置/构建输出仍可能占用空间。复用现有有效检出不会分配另一个检出。直接通过 Git 创建的工作树不在受管理的清理生命周期内。

Git 清点和目录大小计算运行在有界后台工作进程上。分支和检出上下文读取使用专用工作进程,与差异和快照处理分离。Gateway 保留对 Git 子进程、取消、分配租约和注册表写入的所有权。取消操作会等待其子进程和临时索引清理稳定后再释放该所有权。仍在另一个写入者后面等待的引用变更可以在不等待该写入者的情况下取消;已经在运行的变更会在取消返回前完成其清理。准备阶段可以取消;一旦破坏性检出删除开始,它会在取消返回前完成,以便部分检出不会在重试时替换完整的恢复快照。

快照会复用其操作的路径清点,并在构建其临时索引时固定源 HEAD。发布会在等待其他引用变更后原子地验证 HEAD。如果 HEAD 在准备期间发生变化,清理会保留检出并要求你重试。由于忽略规则和源索引可能独立变化,会在捕获时再次检查已预置文件的成员资格。将清点工作移到工作进程不会允许并发分配,也不会削弱快照保护。

快照删除使用更小的 128 MiB 预留加上估算的快照写入量,因此低于操作预留时仍可能进行安全清理。如果快照无法容纳,删除会保留检出并要求你先释放空间。

预置被忽略的文件

在源仓库根目录添加 .worktreeinclude,以将选定的被忽略且未跟踪的文件复制到新工作树中。该文件使用 gitignore 模式语法,每行一个模式,并支持 # 注释:

.env.local
fixtures/generated/**

只有被 git 报告为既被忽略又未跟踪的文件才符合条件。已跟踪文件已经通过 git 存在,此步骤永远不会复制它们。OpenClaw 不会覆盖或更改已存在的目标文件,不会跟随符号链接目录,并保留复制文件的模式。它只记录实际创建的路径,因此后续清单编辑不会使这些文件从清理保护中消失。

运行仓库设置

Git 源物化会保留子模块未填充状态,这与原生工作树创建一致,即使启用了 submodule.recurse。仓库设置脚本可以初始化其所需的子模块。

如果源仓库中存在 .openclaw/worktree-setup.sh 且可执行,OpenClaw 会以新工作树作为当前目录运行它。该脚本会收到:

OPENCLAW_SOURCE_TREE_PATH=<source checkout>
OPENCLAW_WORKTREE_PATH=<managed worktree>

非零退出码会中止创建,并删除新工作树和分支。这是一个仓库本地约定;OpenClaw 没有对应的配置键。

设置失败会报告退出码或终止信号,或 120 秒后的实际超时,并附带最近输出的有界摘录,而不是完整设置日志。如果设置超时,请检查 .openclaw/worktree-setup.sh 及其依赖项,查看是否存在缓慢下载、不可用服务或等待交互式输入的命令。

会话工作树

对于没有源仓库的全新隔离会话,调用 sessions.create 并设置 worktree: true 和 worktreeSource: "empty"。这不会复制代理工作区或任何选定文件夹。它不能与 cwd、项目或仓库选择、外部目录、execNode 或 worktreeBaseRef 组合使用。Control UI 在配对设备和云目标上为新建工作区使用此模式。

每个全新会话都有自己由 OpenClaw 拥有的后备仓库,位于 <openclaw-state-dir>/worktree-sources/empty 下,因此 Git 远程和历史记录在会话之间保持隔离。现有的受管理工作树注册表拥有分配、快照、恢复和清理;无需数据库迁移。只要活动工作树或保留快照引用后备源,它就保持可用,并在其最终过期快照被收集后删除。内部仍需要 Git。现有安装仅对新的显式空工作区请求采用此模式;现有会话及其快照保留其原始源。

如果 worktree 准备在首次模型回复之前失败,会话会记录失败原因。Control UI 会将其与失败的会话一起显示,并在聊天中显示,同时转录会保留失败通知。命令失败会标识该命令及其退出或超时原因,因此 Git 设置超时可与模型提供商超时区分开来。

通过 worktree 会话从由 Git 支持的文件夹启动隔离聊天:在 Control UI 的新会话页面上,使用 Place 选择器选择 Gateway 源文件夹,然后选择 Worktree(可附带可选的基础分支和 worktree 名称)。选择已配对的设备或云配置文件并选中 Gateway 文件夹时,会使用此托管 worktree 路径;远程放置绝不会浏览或绑定任意节点工作目录。如果省略名称,OpenClaw 会从显式会话标签或从第一条消息生成的简洁标题中推导该名称,然后回退到甲壳类主题名称。当活动代理工作区由 Git 支持时,iOS 会从聊天操作公开相同选项,Android 会在“新建聊天”旁边公开该选项。

从 Gateway 文件夹启动的远程会话会保留一个持久的托管 worktree 镜像,用于工作区协调、恢复和发布。相同的磁盘空间检查也适用于此镜像。若要无需 Gateway 检出即可启动,请改为选择一个 GitHub 仓库和远程目标:仓库云会话 会在节点上获取,并在 Gateway 上保留已接受的检查点。它们的检查点与托管 worktree 快照具有不同的生命周期。

Control UI 仅在确认存在至少包含一个提交的可用 Git 检出,或所选远程 Git 仓库等待克隆时,才提供 Worktree。普通文件夹和没有提交的新初始化仓库可以直接在 Gateway 上运行。如果 Git 检查失败,只要文件夹可访问,仍会保留直接执行可用;仅有 .git 条目或已保存项目本身不会启用隔离。如果你已经选择了 Worktree,而后续检查失败,该选择仍会保持可见,并且启动会被阻止。清除 Worktree 以直接运行,或重新选择该文件夹以再次检查。

base-ref 字段会建议最多 100 个本地 ref 和 100 个远程 ref,外加默认分支和当前分支。当前分支来自所选检出,包括链接的 worktree;分离检出没有当前分支。分支发现会直接读取该检出,而不会清点同级 worktree。重复查找会复用未更改的 ref 清单,同时在每次请求时验证检出;当松散 ref、打包 ref、标签和所选 HEAD 发生变化时,会使清单失效。即使未被建议,你也可以输入任意分支或提交。如果无法加载分支建议,Control UI 会说明你可以手动输入 ref;已验证的 Git 检出仍可用于 worktree。所选 ref 在创建会话之前仍必须解析为提交。

组 新会话默认值 会以与自定义文件夹相同的方式检查代理工作区。如果验证失败,请在保存组默认值之前重试。记住的云目标不会阻止在普通文件夹中创建新的本地草稿;短暂的 Git 检查失败会保留已保存的目标,供下次访问使用。

Place 选择器的 Projects 部分可以从已注册的项目 ID 启动相同的 worktree 流程。Gateway 会解析记录的检出路径,因此该路径在 operator.write 下仍然可用;选择任意主机文件夹仍需要 operator.admin。

当代理发现当前任务之外的已确认后续工作时,也可以调用 suggest_task。Control UI 和 Gateway 支持的 TUI 提供 在新会话中启动。这会直接在建议的文件夹中启动任务,无需创建 worktree 或要求 Git。新会话会被指示说明需求,并在稍后创建或切换到 worktree 之前询问用户。关闭建议不会启动任何内容。建议及其 ID 是临时的,不会在 Gateway 重启后保留。

在 Control UI 中,在新会话中启动 旁边的箭头提供两个额外操作:在新 worktree 中启动 会从建议的 Git 检出一个创建隔离会话,在此会话中启动 会将任务发送到当前对话。如果当前会话正在运行,任务将遵循其正常的引导行为。创建 worktree 需要可用的 Git 检出;启动失败会显示错误,并保留建议以便重试。

关闭建议任务卡片会立即将其移除,同时 Control UI 会将关闭操作发送到 Gateway。其他卡片和输入框仍可使用。如果请求失败,卡片会带错误返回,以便你重试;切换聊天不会将旧卡片带入新对话。

主要操作和 Gateway 支持的 TUI 会发送带有 mode: "local" 的 taskSuggestions.accept。Control UI 菜单会为这些选择发送显式的 worktree 或 session 模式。RPC 客户端也保留 cloud 模式。对于使用原始 worktree 操作的调用方,省略模式仍表示 worktree;Control UI 和 TUI 从不省略它。

OpenClaw 仅将这些工具暴露给具有可操作 Gateway UI 的 operator 会话。通道会话和本地/嵌入式 TUI 会话不会收到它们,因为这些界面没有可移植的带类型任务操作契约。

由此生成的托管 worktree 由会话拥有,该会话中的每次代理运行都会使用其检出。当工作区是仓库子目录时,worktree 会锚定在仓库根目录,并且会话从其中的匹配子目录运行。会话 worktree 创建使用该方法的 operator.write 范围。仓库检出/ref 钩子和文件系统监视器始终禁用。.openclaw/worktree-setup.sh 步骤仅对 operator.admin 调用方运行;重试会评估当前调用方的范围,而不是保留原始调用方的权限。.worktreeinclude 配置仍适用于每个调用方。删除会话会尝试对其托管 worktree 进行快照并移除,包括脏 worktree 和包含未推送提交的分支。每小时清理还会在 7 天空闲后对会话 worktree 进行快照,将最近的会话活动视为 worktree 活动。已移除的 worktree 仍可从其快照恢复,如下所述。

归档会话时,会先提交其归档状态,然后对托管检出进行快照并移除,同时保留对话和工作树绑定。如果元数据写入失败,检出将保持不变。如果清理无法安全完成,会话仍保持归档状态,其文件继续保留,错误信息会说明清理待处理。重复归档会重试清理;每小时一次的垃圾回收也会重试任何仍然存在的检出。自动会话归档使用相同的元数据优先顺序。

取消归档,或经授权的人类消息重新打开已归档会话时,会在接受工作之前恢复原始分支 HEAD 以及已保存的脏文件和未跟踪文件。恢复失败会使会话保持归档状态。如果原始仓库或其快照缺失,或 30 天快照保留期已过,请恢复原始仓库/快照或启动新任务;OpenClaw 不会用空检出替代已保存的工作。

sessions.create 可以包含绝对 cwd,以便直接在另一个 Gateway 文件夹中运行,或与 worktree: true 一起选择源检出。具有 operator.write 权限的连接可以使用包含在任一已配置代理工作区中的 Gateway cwd;realpath 包含检查可防止符号链接逃逸该边界。这些工作区之外的 Gateway 路径需要 operator.admin。普通 worktree 聊天创建仍然是 operator.write,并锚定到已配置的工作区。对于 Gateway 源,新建会话会将已完成的工作树会话分派到配对设备或云配置文件,而不是将配对节点的工作目录传递给创建过程。单独的 repository: { url, ref? } 创建输入会启动一个远程所有的仓库会话,不需要 Gateway 路径或 worktree: true。

sessions.create 还接受 worktreeBaseRef 和 worktreeName 与 worktree: true 一起使用,以选择基础 ref 和工作树名称(分支变为 openclaw/<name>);两者仍属于 operator.write 权限范围。如果省略 worktreeName,会话标签或生成的首条消息标题会提供可读的分支名称;如果命名失败或超过 30 秒等待时间,则使用两个词的甲壳类主题回退名称。原始首条消息文本绝不会用作分支名称回退。稍后到达的标题会更新会话,但不会重命名其现有分支。对于带有初始消息或任务的新会话,创建会在工作树准备完成之前返回已接纳的会话和 run。聊天界面会显示已提交的消息以及命名、检出和设置进度;失败信息保持可见,并可在同一会话中重试。代理只会在最终确定的工作树绑定之后启动。没有初始轮次的创建仍会等待准备完成,并在创建结果中返回工作树。绑定的检出会以 worktree: { id, branch, repoRoot } 的形式持久化在会话行上,因此会话列表可以显示其检出和分支。当会话删除无法完成该清理时,worktreePreserved 会标识需要关注的活动工作树记录,并报告一个有界原因:所有者不匹配、活动使用或竞争清理、外部 Git 锁、快照失败,或其他清理失败。这些原因描述的是清理和所有权状况,而不表示检出是否有未提交更改或未推送的提交。

显式会话基础必须解析为一个提交。本地 ref 在会话保存前检查;远程项目 ref 在克隆后检查。缺失的远程 ref 会从记录的项目 URL 刷新,并且仅在 Gateway 管理的克隆中重试,绝不会在操作员注册的检出中重试。一旦接受,该提交会在设置失败和重试期间保持固定,同时原始 ref 仍作为发布元数据保留。无效的显式 ref 绝不会静默切换为仓库默认值。托管克隆刷新使用隔离的 Git 仓库进行网络传输,因此检出本地的 URL 重写和钩子无法在 fetch 期间重定向或执行。

对于同一代理的 sessions_spawn 且带有 worktree: true,省略 cwd 会使用父级的活动托管仓库或其直接选定的已注册项目。子级会获得自己的托管工作树。显式源选择优先;其他派生操作使用目标代理工作区。仅有父级工作目录本身并不能授权在该工作区之外的继承。

父级会话及其托管工作树或已注册项目绑定必须保持有效,直到子级被接受。已接受的子级会话会在父级归档、替换或工作树更改后保留其保存的仓库选择。重试仍必须针对当前子级会话获得授权,并使用当前调用者的设置权限。

排查创建问题

如果创建报告 git checkout has no commits,请在源仓库中创建初始提交,然后重试。仅运行 git init 不会为新工作树提供提交。

如果 新建会话 报告 git worktree add failed,请阅读终止原因和 Git 错误信息的最后几行。Preparing worktree 和 Updating files 是进度信息,不是失败原因。错误信息会折叠回车符进度重绘,并限制诊断尾部的长度,使其不会淹没横幅。

timed out after 300 seconds 表示工作树检出达到了其五分钟限制。其他 Git 命令在达到两分钟限制时报告 timed out after 120 seconds。请检查 Gateway 主机上的仓库访问权限和可用磁盘空间。仅凭信号或非零退出状态并不能确定超时;请使用附带的 fatal: 或 error: 详细信息进行调查。输出限制错误表示命令超过了其输出捕获限制。

在再次尝试创建之前,请检查 git -C <repo-root> worktree list 和 git -C <repo-root> branch --list 'openclaw/*' 以了解部分状态。失败的创建并不保证其检出和分支已被移除。不要在不检查检出或分支是否包含你需要的工作的情况下删除它们。

如果检出的 .git 链接指向缺失的管理文件,OpenClaw 会保留其文件并拒绝重用它。请先恢复原始仓库元数据,再从该仓库使用 git worktree repair。具有相同远程 URL 的不同克隆无法恢复缺失的索引或未推送的历史;请在验证原始元数据之前,不要替换链接或重建索引。

快照、清理和恢复

移除会先创建一个包含已跟踪文件以及未被忽略的未跟踪文件的合成提交,然后将其固定到 refs/openclaw/snapshots/<id>。主机预置的忽略文件不会进入 Git 快照或仓库对象数据库。OpenClaw 仅将其实际预置的忽略文件存储在分块的共享状态数据库行中;记录的路径集仍具有权威性,即使 .worktreeinclude 之后更改或消失。恢复会从不可变快照中读取这些字节,并重新应用其完整模式。自动清理会在记录路径无法安全快照时保留活动工作树。如果快照创建失败,除非 --force 明确允许丢失快照,否则移除会停止。

沙箱创建的忽略文件(包括符号链接)以及已被协调接受的空目录,仍由现有投影所有者保管。在移除之前,OpenClaw 会在其待处理结果回执和私有恢复引用中保留它们缺失的快照增量。恢复会在另一个回合同步工作区之前重放该回执。这不会强制将忽略路径发布,也不会导入无关的被忽略主机文件。回执遵循相同的快照保留期,未接受的私有编辑会推迟清理。旧版预置文件台账仍仅包含常规文件。旧版本可以恢复该台账和 Git 快照,但不会应用投影回执;请返回支持该功能的版本以恢复已接受的来宾数据。

普通移除是归档式的:在成功快照后,它使用 Git 的强制检出移除,以便稍后恢复脏文件。CLI 的 --force 选项允许丢失快照;省略它不会选择非强制 Git 移除。当删除必须为非强制时,使用 openclaw worktrees remove <id> --if-lossless。这与运行结束清理使用相同的所有者,保留脏或未发布的工作,并且从不以强制方式重试 Git 拒绝。它不能与 --force 组合使用。

移除要求 HEAD 保持在记录的受管分支上。切换分支或分离 HEAD 会保留检出和记录的分支。分支删除针对已完成的快照使用原生 git branch -d,因此已推进到该快照之外的分支尖端仍保持完整。如果没有快照,分支将保持保留。移除仅删除其自身的 Git 工作树注册,并且从不运行仓库范围的 git worktree prune。

嵌套 Git 仓库和链接工作树是独立的所有权边界。即使嵌套链接工作树共享其 Git 公共目录,自动清理也会保留外层工作树。嵌套的 OpenClaw 受管工作树仅通过其自身的受管工作树记录进行清理。

OpenClaw 应用以下清理规则:

  • 在运行结束时,只有当 git status --porcelain 为空,并且 git log HEAD --not --remotes --oneline 未找到未推送的提交时,它才会不使用 Git 强制移除工作树。它还会检查捕获的内容中是否有被索引标志隐藏的编辑。否则,它会保留检出并记录原因。
  • 每小时清理会对空闲超过 7 天的未锁定 Workboard 和会话拥有的工作树进行快照并移除,即使它们处于脏状态。第一次自动扫描在 Gateway 启动一小时后运行,并且慢速扫描会在下一次扫描开始前完成。所有者已归档或不存在的工作树会话工作树,无需等待 7 天即可在下次扫描中符合条件。所有者查找失败会保留检出。运行 openclaw worktrees gc 可立即清理。
  • 清理还会移除超出默认目标 100 的、最近最少活动的符合条件的运行拥有的工作树。手动工作树永远不会被自动移除,受保护的工作树可以使总数超过目标,直到它们被释放或显式清理。
  • 快照记录在 30 天内保持可恢复。之后清理会删除快照引用和注册表行。
  • 活动的 OpenClaw 进程锁以及任何外部或无法识别的 git 工作树锁都会保护工作树免于垃圾回收。

每次收集都会在请求 Git 清单之前检查注册表资格、已记住的处置、所有者活动和运行租约。它串行地对候选项进行分类,并在空闲检查和限制检查之间共享每个仓库的一个初步锁和分支清单。已知的预置台账使用文件系统检查,无需 Git 设置。移除会重新读取当前锁和 HEAD,并在更改检出之前验证工作树的活动在其分配租约下未发生变化;初步清单从不授权移除或过期锁恢复。如果清理无法获取租约,它会保留孤立候选项和过期快照,留待后续扫描。

每小时清理会将嵌套仓库、分支移动和 Git 不可用等处置记录在工作树记录上,而不是重复它们的 Git 清单。它会在首次推迟时记录保留的检出路径。受管活动,或记录的仓库、所有者或快照发生变化,会使处置失效。在外部修复文件或 Git 元数据后,运行 openclaw worktrees gc 可立即重新检查被推迟的检出;显式移除和恢复也会保留其正常检查。被推迟的工作树仍计入清理限制。可空的派生状态列会在数据库准入时添加,且不更改模式版本;旧版本会忽略这些处置并恢复其先前的检查行为。检出或快照保留期均无变化。

列表和清理只有在记录的检出路径、活动和仓库标识仍与先前检查匹配时,才会将缺失的检出标记为已移除。如果恢复或仓库修复在该检查期间完成,则会保留较新的活动记录。

清理会将 HEAD 已分离或已切换离开其注册分支的检出保留为 branch-moved。如果链接检出的 Git 元数据目录已消失,但其源仓库仍可用,清理会退役孤立记录,同时保留检出文件和正常的快照保留期。这些处置不会导致 openclaw worktrees gc 失败;真正的检查或清理失败仍会返回非零退出状态。摘要和 JSON 输出包括每个保护原因的孤立退役计数和总计,即使个别详细信息被截断。

权限被拒绝的检查(EACCES 或 EPERM)会保留检出为 unreadable,并在其清理详情中包含问题路径,同时在摘要中记录一个保护计数,而不是每次扫描都发出警告。如果已注册路径无法解析,孤儿删除也会等待。修复 Gateway 用户的访问权限;下一次扫描会重新检查权限并恢复符合条件的清理。

带有本地工作区投影的缺失检出或 gitdir 仍会注册为 local-workspace-projection。仅投影文件可能仍需恢复;清理会推迟退役,直到投影所有者释放托管,包括在后续保留检查期间。

在没有快照的情况下退役的孤儿不再出现在 worktrees list 中,也无法使用 worktrees restore。GC 会验证已记录的仓库身份,并在 retiredCheckoutPaths 中报告所有受保护的检出路径以供手动恢复,独立于有界的问题详情。这些情况属于延迟清理:CLI 退出码为 0,Gateway 现有的延迟清理响应包含所有恢复详情,且不改变其成功响应契约。文本摘要也会保留每个恢复路径。保留这些文件和保留的源分支;将工作恢复到另一个检出中,而不是删除或覆盖受保护的文件。退役不会重建缺失的 Git 元数据,也不会创建替代快照。

运行结束清理会将其结果记录到工作树记录中:无损移除、因检出繁忙、脏、未推送或存在预置文件漂移而保留,或带有错误原因的失败。使用 openclaw worktrees list --json 或 worktrees.list 检查已记录的结果。

如果检出删除失败或被中断,OpenClaw 会在 refs/openclaw/removals/<id> 保留已完成的捕获。后续移除会拒绝用可能部分检出的文件替换该捕获。保留剩余文件、已记录分支、快照 refs 和共享状态数据库以供恢复。在尝试清理前,检查原始移除错误和 Git 工作树注册;不要反复强制移除或修剪注册。正常完成的移除、成功恢复或快照过期会清除此恢复 ref。检出移除后的失败可能导致其分支被保留,并且需要操作员对账,恢复才能重新创建该分支。

对于被中断的 普通干净快照 移除,请使用确切的待处理提交:

openclaw worktrees recover-removal <id> --snapshot <pending-commit> --json

恢复会保留原始捕获,验证保留的索引和所有剩余文件,仅修复该检出缺失的 Git 链接,并仅重新创建缺失的捕获文件,而不覆盖现有路径。随后,原生非强制 Git 移除会完成检出和分支清理。这可能临时需要为缺失文件提供磁盘空间。快照仍可用于恢复;此命令不会退役快照,也不会运行仓库范围的修复/修剪。

在恢复前停止外部编辑器、终端和其他非受管写入者。受管消费者在最终确定前保持排除;同步字节/模式检查允许原生删除,而无需中间异步检查。

已更改文件、外部路径、活动消费者、已更改的 refs/注册表所有权、缺失的原始元数据,以及与捕获不同的索引会停止恢复。脏捕获、预置的忽略文件、投影工作区和精确状态退役保留其现有恢复所有者。保留这些来源以供检查;此命令不会将它们重新解释为干净移除。被中断的恢复可以在其阻塞项解决后,使用相同 ID 和快照重复执行。一旦检出删除被允许,它会在没有普通 Git 命令截止时间的情况下被等待完成,以便超时不会再次中断删除。

恢复会在原始快照前提交处重新创建 openclaw/<name>,在可用时复用其干净源模板。Git 会将保存的差异作为未暂存修改和未跟踪文件应用,而不会用快照内容替换模板。如果没有可复用模板,Git 会直接物化快照。磁盘准入包括为更改和新增文件以及克隆元数据预留的空间,或对于普通检出为完整快照预留的空间。如果快照更改了 .gitattributes,或其差异超过有界清单大小,Git 会以完整复制空间额度重新物化所有快照文件。这会将快照的换行符和过滤器应用到未更改的 blob。合成快照不会进入分支历史;其 ref 仍作为来源记录保留。

位于浅历史边界的分支仍可以快照和恢复。如果后续深度受限的 fetch 使快照提交本身变为浅提交,Git 可能无法再解析其父提交。恢复随后会保留快照,并报告仓库和快照提交,同时给出 git fetch --unshallow 指引。OpenClaw 不会自动加深:origin 可能不包含本地快照,因此即使 fetch 成功也无法保证恢复。如果 fetch 后快照仍为浅提交,请在重试前从原始仓库恢复其父提交。

提前退役已移除的快照

仅当已移除的快照与保留的本地分支或远程跟踪提交冗余时,才使用 openclaw worktrees retire-snapshot。此本地 CLI 操作需要确切的工作树 ID、快照 ref 和提交、已记录的 removedAt 毫秒值,以及保留的源 ref 和提交。在调用前,从已移除记录和仓库中读取这些身份:

openclaw worktrees retire-snapshot <id> \
  --expected-ref refs/openclaw/snapshots/<id> --expected-oid <snapshot-commit> \
  --removed-at <milliseconds> \
  --retained-ref refs/heads/<retained-branch> --retained-oid <source-commit> --json

退役仅适用于普通快照,不适用于精确状态恢复快照或其保留的检出。它要求源树相同,并保留快照父历史。它会拒绝活动或重新出现的检出、Git 注册、已更改身份、待处理移除、运行/移除消费者、未知或非空的预置文件清单,或任何保留的本地工作区投影。Git 相等性不能证明已接受的忽略投影数据是冗余的。它使用现有分配租约和投影所有者,然后原子地验证保留的 ref,并仅删除预期的快照 ref。它不会创建备份、删除保留的源或 PR 结果 refs、运行全局垃圾回收,或报告回收的磁盘字节数。ref 退役后,Git 对象存储仍可能保持共享。

成功的 JSON 结果是 { "retired": true, "id": "<id>" };被移除的注册表条目随后不存在且无法恢复。拒绝不是清理成功。如果在 ref 退役后发生中断,在进一步清理之前检查剩余记录和投影保管状态;此命令不会从缺失的 ref 推断安全退役。此操作仅限 CLI,不是 Gateway 或 Control UI 操作。

精确状态分离退役

普通移除、强制移除和 --if-lossless 仍然会拒绝 detached HEAD。若要退役一个有意处于 detached 状态的受管 checkout,且不改变其记录的分支或暂存状态,请使用显式的 owner 围栏请求:

openclaw worktrees remove <id> --exact-state /path/to/retirement.json --json
openclaw worktrees restore <id> --json

该请求包含来自 worktrees list --json 的当前注册表 owner 和生命周期时间戳、detached HEAD 提交、记录分支的提交,以及原始 Git index 字节的 SHA-256。例如:

{
  "ownerKind": "session",
  "ownerId": "example-session",
  "createdAt": 1800000000000,
  "lastActiveAt": 1800000000001,
  "head": "1111111111111111111111111111111111111111",
  "branchHead": "2222222222222222222222222222222222222222",
  "indexSha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}

使用实际观察到的值,而不是示例值。对于没有 owner ID 的手动记录,省略 ownerId。此选项不能与 --force 或 --if-lossless 组合使用。活动运行租约、外部 Git 锁、owner/生命周期变化,或 HEAD、分支、index 或已捕获文件的变化都会保留该 checkout。它不会授权移除其他会话的活动工作。

版本化快照会保留 detached 提交和独立的记录分支尖端、原始 index 字节和 split-index 依赖,以及仅由 staging、cache-tree 或 resolve-undo 状态引用的对象。它会保存原始 tracked 和非忽略 untracked 字节、符号链接、权限模式位和修改时间。此快照中的忽略文件选择保持不变:只有原生 provisioned-file 账本和 staged-input 契约会保留符合条件的忽略文件。仅对象恢复不会重现文件系统标识,例如 inode 号或变更时间。记录分支保持在其原始提交。

精确退役是归档,而不是立即磁盘回收。 它通过原生 Git 将原始 checkout 移动到私有恢复名称,并移除活动 managed-worktree 绑定。原始 checkout 及其原生注册与不可变快照一样,保留在相同的 30 天恢复保留期内。结果包含 recoveryPath 和 recoveryRetainedUntil。这会保留来自已持有工作目录或打开文件描述符的进程的写入;仅 Git index/ref 锁并不能使删除这些字节变得安全。恢复路径不是活动工作区。快照过期会删除此保留的 checkout,因此不要继续在那里工作,也不要将其视为永久存储。

精确状态退役要求完整的非 sparse checkout,并具备 Git file refs 和受支持的 Git index 扩展。在归档最终确定之前,它会持有原生 Git index 和 ref 锁,同时重新验证其 index、refs、文件和权限。如果原始路径仍然可用,验证失败会将完整 checkout 移回。两个移动操作都不会覆盖重新创建的源路径。

Restore 通常会将保留的原始 checkout 移回,保留其 index、元数据、忽略缓存,甚至捕获后通过旧句柄做出的 workfile 写入。如果其 HEAD 或 index 已变化,restore 会拒绝并保留两个恢复源。如果保留的 checkout 及其注册都不可用,restore 会改为直接从 Git 对象物化不可变快照,而不经过 filters、行尾转换或工作树编码。该回退只恢复快照中符合条件的忽略文件,而不是无关缓存。两条路径都会恢复 detached HEAD,而不替换记录分支。如果 restore 在其原生移动后被中断,请重试 restore:它只识别位于活动路径上的已捕获原始目录实例,并且从不采用重新创建的替换目录。

仅对象恢复也会为新分配的目录实例保留一个版本化原生 Git 恢复回执。它会原子地发布完整文件和原始 index,同时原生 Git 锁在注册表最终确定期间排除 staging 和 HEAD 写入者。中断后重试同一 restore 命令;它只恢复该回执拥有的目录,并保留已更改或替换的源。发布精确 index 是恢复提交点:在该点之后的重试会保留后续 workfile 编辑,并且只完成注册表清理。成功最终确定后会清除回执。在快照过期被中断后的重试可以完成已过期的注册表条目,而无需猜测未知保留目录的身份。

快照使用 refs/openclaw/snapshots/exact-v1/<id> 和现有的 30 天保留 owner。请将仓库对象、保留的恢复 checkout 和共享状态数据库放在一起。使用支持此选项的运行时;旧版 restore 实现无法保留额外的 index 状态。普通快照保持其现有行为。

如果原生归档移动完成但注册表最终确定被中断,请使用原始请求进行调和并恢复:

openclaw worktrees restore <id> --recover-exact-state /path/to/retirement.json --json

恢复需要匹配的已完成捕获以及未变化的 owner 和记录分支。在注册表仍显示活动行时,恢复会持有现有的移除声明,拒绝活动运行和新运行准入,直到其稳定。重试会识别已移回的已捕获原始目录;它从不采用未知占用路径。不一致的源/注册会保留所有恢复材料并拒绝覆盖它。列表和垃圾回收不会从缺失的原始路径推断已完成退役。请保留未完成的源和恢复以供检查;不要强制再次移除、重置 index、重新附加 HEAD 或修剪注册。

命令行界面

openclaw worktrees list [--json]
openclaw worktrees create <repo-root> [--name <name>] [--base-ref <ref>] [--source-profile <name>]... [--json]
openclaw worktrees remove <id> [--force | --if-lossless | --exact-state <file>] [--json]
openclaw worktrees restore <id> [--recover-exact-state <file>] [--json]
openclaw worktrees gc [--json]

Settings 下的 Control UI Worktrees 页面提供相同的操作,并额外支持带基础分支选择器的创建操作;它会显示每个 worktree 的属主(manual、Workboard 或带聊天链接的所属会话),并在移除操作报告快照失败时提供强制重试。

将 Base branch 留空会获取并使用远程默认分支。分支建议不会选择基础分支;选择或输入分支或提交时,将直接使用该确切 ref,而不会执行获取。清空该字段将恢复自动选择。获取会更新远程跟踪 ref,而不会更新源检出的本地 main;当远程默认分支不可用时,上文所述的本地 HEAD 回退仍然适用。

--if-lossless --json 返回 removed 以及记录的 cleanup 结果。被保留的检出会返回 removed: false;这不算成功删除。显式的 --if-lossless 选项仅限 CLI 使用;Gateway 的移除操作保留其归档行为和结果格式。

Gateway 方法

方法 用途
worktrees.list 列出活动且可恢复的 worktree 记录。
worktrees.branches 列出仓库的本地和远程分支,供基础 ref 选择器使用。
worktrees.create 创建或复用指定的受管 worktree。
worktrees.remove 对 worktree 执行快照并移除。强制移除会报告 snapshotError。
worktrees.restore 从快照中恢复已移除的 worktree。
worktrees.gc 立即执行空闲、孤立和保留期清理。

worktrees.list 需要 operator.read。worktrees.create 和 worktrees.branches 对于已配置的 agent 工作区和已注册的项目需要 operator.write;任意主机路径仍然需要 operator.admin。所有创建操作都会禁用仓库的 Git hooks;写作用域的创建还会跳过 .openclaw/worktree-setup.sh。移除、恢复和垃圾回收 worktree 仍仅限管理员操作。分支列表只读取现有 refs,从不获取;远程独有的分支会以远程限定形式(origin/feature-a)返回,因此返回的每个名称都能解析为基础 ref。New Session 也可以通过此方法请求类型化的仓库状态;普通目录或不可用的检出不会返回分支,而不会强制 UI 从错误字符串推断 Git 能力。

Workboard 工作区

随附的 Workboard 插件 可以将卡片工作区物化为受管 worktree:

{
  "kind": "worktree",
  "path": "/absolute/path/to/source-checkout",
  "branch": "main"
}

path 标识源 git 检出。branch 为可选,并作为基础 ref。对于完整宿主机(full-host)调用方,Workboard 创建或复用 wb-<card-id>,以受管检出作为子代理的工作目录来运行子代理,并将解析后的路径和分支写回卡片。Gateway 客户端需要 operator.admin 才能进行完整宿主机物化。运行结束时,Workboard 仅在可证明无损时才移除检出;未提交的更改或未推送的提交仍然保留。

对于工作区绑定(workspace-bound)调用方,path 和仓库根必须与目标 agent 工作区完全匹配。此时 Workboard 直接在该目录中运行,并记录目录工作区,而不是在宿主机上物化受管 worktree。目标必须为同一工作区使用可写的、非共享的 Docker 沙箱;其运行中容器的哈希必须与请求的挂载和策略匹配,并且不得暴露提升执行、宿主机控制、宿主机级会话、持久化宿主机/节点执行,或未分类的插件和 MCP 工具。如果目标策略或运行中容器的范围更大,调度将使卡片保持未认领状态,并报告不兼容状态。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw