会话
会话就是一个正在运行的工作区:它的 Ubuntu 虚拟机已启动、终端标签页处于活动状态、代理正在工作。本章涵盖从点击启动到关闭窗口之间发生的一切——会话窗口的布局、标签页与 git 工作树、嵌入式浏览器窗格与文件窗格、在 Mac 与虚拟机之间移动文件与剪贴板内容、检查点,以及会话结束时你所拥有的各种选择。
与关闭窗口即销毁会话的姊妹产品 Bromure 网页浏览器不同,Bromure Agentic Coding 的工作区在设计上是持久化的。虚拟机的系统磁盘和主目录会在会话之间保留;只有刻意的操作(重置为基础镜像…、清除主目录…、删除工作区)或安全擦除才会销毁数据。关闭会话仅仅决定虚拟机接下来做什么:保持运行、挂起或关机。
会话的工作原理
每个工作区都精确对应一个虚拟机。虚拟机从每个工作区独立的系统磁盘(disk.img)启动——这是共享 Ubuntu 基础镜像的 APFS 写时复制克隆,在首次启动时瞬间创建,此后每次启动都会重用。你在虚拟机内安装的任何东西(sudo apt install、语言工具链、系统配置)都会在会话之间保留。主目录 /home/ubuntu 单独存储——对于现代工作区,它位于私有的稀疏 ext4 磁盘镜像上——即使完全重置系统磁盘也能保留下来。有关存储模型的深入介绍,请参阅概念。
在虚拟机内部,所有终端都属于同一个 tmux 会话。tmux 是真实来源:每个 UI 标签页都是一个 tmux 窗口,宿主机将客户机的标签页清单镜像到侧边栏。这种设计意味着 UI 可以自由分离和重新连接——会话可以在后台无界面持续运行、弹出到自己的窗口,或者从另一台 Mac 镜像(参阅远程访问),而不会打扰代理的工作。
注意: 工作区虚拟机不是从池中预热的。每个虚拟机都从自己的磁盘冷启动(或从挂起快照恢复)。只有代理浏览器窗格背后的辅助虚拟机才使用预热池。
启动会话
你可以从多个位置启动已停止的工作区:
- 在侧边栏中选择工作区并点击启动(如果已挂起则点击恢复)——可以在舞台的启动卡片上,也可以在虚拟机仪表板中操作。
- 点击工作区侧边栏行上的 ⋯ 并选择启动。
- 点击终端网格中属于某个关闭工作区的占位单元格。
启动的内容
- 首次启动——应用使用 APFS 写时复制克隆将基础镜像克隆到工作区的
disk.img中。克隆是瞬时的,且前期不占用磁盘空间;只有在客户机写入时才会分配块。主目录镜像以及每次启动的共享(元数据共享和发件箱)会被创建,虚拟机以 4 个 vCPU(固定)和工作区设置中配置的 RAM 启动。 - 后续启动——重用现有的系统磁盘和主目录,因此虚拟机内安装的所有东西都还在。
- 已挂起的工作区——不进行冷启动,而是恢复保存的 RAM 快照(
vm.state),会话精确地从上次停止的地方恢复,其标签栏从保存的标签快照中重建。恢复几乎是瞬时的。
默认情况下,虚拟机加入 Bromure 的共享 NAT 交换机:每个工作区虚拟机(以及代理浏览器虚拟机)共享一个私有子网,获得稳定的 DHCP 地址,并且可以互相访问——因此浏览器窗格可以通过虚拟机的 IP 加载代理启动的开发服务器。工作区设置中提供每个工作区独立的桥接模式。有关内存和网络选项,请参阅设置 — 通用。
启动画面
在虚拟机启动时,一个动画式的“潜入”覆盖层会覆盖终端区域——工作区名称叠加在扫描进度条上,可选带有状态行。它仅在启动耗时超过 0.4 秒时出现,并在客户机报告其第一份标签清单的那一刻淡出。在主目录存储迁移期间,覆盖层会改为显示确定性进度(例如“MOVING HOME — 42% OF 7.9 GB”)。
如果 30 秒内没有出现终端,覆盖层会切换为 DIVE FAILED 面板——“«name» never returned a terminal after 30 seconds. The VM may be stuck, or the base image may be damaged.”——并带有两个按钮:
- 继续等待——重新启动看门狗并让启动继续进行。
- 重置基础镜像…——针对共享镜像本身损坏的情况,启动基础镜像重建。
如果启动反复失败,请参阅故障排除。
启动时的提示
启动之前可能会出现以下某个提示:
| 提示 | 出现时机 | 选择 |
|---|---|---|
| 基础镜像漂移 | 自本工作区的磁盘克隆以来,共享基础镜像已被重建 | 重置并启动(从新基础镜像重新克隆;主目录不受影响)/ 按原样启动 / 取消 |
| 已被入侵的工作区 | 之前的某个会话被标记为存在凭据外泄 | 在启动前确认擦除磁盘、主目录、RAM 快照和每次启动的共享;设置、令牌和 SSH 密钥会保留。参阅凭据。 |
| 主目录存储升级 | 工作区仍使用旧版共享文件夹主目录 | 立即升级(在本次启动期间迁移到 ext4 主目录镜像)/ 暂不(下次启动时再次询问) |
| 模型仍在下载 | 所需的本地模型尚未下载完成 | 启动被拒绝并附带说明。参阅本地模型。 |
| 磁盘已满 | 宿主机卷可用空间不足 1 GB | 启动被拒绝并给出明确错误,而不是在会话中途卡死。 |
会话窗口
所有会话都存在于一个共享的窗口中,标题为 Bromure(默认 1320 × 860 点)。它采用 Mail.app 风格的分栏:左侧是可调整大小的侧边栏,列出每个工作区;右侧是单一的舞台,显示所选工作区的终端。标题栏透明并与工具栏统一;点击其空白区域可以像浏览器那样拖动窗口。
上方的截图显示了选中一个关闭工作区时的窗口:左侧是 WORKSPACES 侧边栏(带有固定的 Grid 节点、两个显示 Off 状态的工作区、一个 AUTOMATIONS 部分,以及用于创建工作区的黑色 + 按钮),舞台显示该工作区的虚拟机仪表板——CPU、内存、vCPU、磁盘和运行时间的统计卡片、一个 CONFIGURATION 摘要,以及一个启动按钮。
工作区侧边栏
侧边栏是一个源列表,每个工作区占一行——无论是否正在运行。每行显示工作区名称、其强调色瓷贴,以及一个运行状态徽标:
| 徽标 | 状态标签 | 含义 |
|---|---|---|
| 绿点 | — | 运行中 |
| 橙色,脉动 | Starting… | 正在启动 |
| 黄点 | Suspended | RAM 快照已保存到磁盘 |
| 灰点 | Off | 已关机 |
红色感叹号三角形标记表示已被入侵的工作区。运行中的工作区会在其下方嵌套显示其终端标签页(按工作树树形顺序),加上一个常驻的 Docker 节点,并显示悬停控件:弹出、关闭(×)以及用于新建标签页的 +。每行上的 ⋯ 菜单提供与状态相关的生命周期操作:启动 / 恢复 / 关机 / 挂起 / 重启、将工作树添加到网格(仅限运行中)、编辑…、复制、重置磁盘,以及删除工作区。
注意: 关机和重启会请求确认,因为它们会停止正在运行的进程。挂起则不会——它是完全可恢复的。
拖动侧边栏与舞台之间的分隔条可以调整其大小(默认宽度 220 点)。拖到大约 100 点以下会使侧边栏吸附为 44 点的图标栏;拖回超过该点则展开。⌃⌘S 可切换侧边栏的折叠状态。在折叠的图标栏中,容器标签页被隐藏,工具提示会携带工作区和标签页的上下文。
舞台
舞台显示所选标签页的终端。它也可以被全幅覆盖层界面覆盖:
- 虚拟机仪表板——点击侧边栏中工作区的名称(见下文)。
- 终端网格——点击固定的 Grid 节点(参阅终端网格)。
- Docker 仪表板——点击运行中工作区下的 Docker 节点,以管理容器和镜像。
- 自动化编辑器——从 AUTOMATIONS 部分进入(参阅自动化与 CLI)。
舞台的右边缘内还有另外两个分栏:代理浏览器窗格(⌃⌘B)和文件浏览器窗格(⌃⌘E)。
虚拟机仪表板
点击工作区的名称(而不是它的某个标签页)会在舞台上叠加显示其仪表板,适用于任何运行状态。对于运行中的虚拟机,它显示实时指标:带有迷你图的 CPU、已分配内存中的已用量、带有平均负载的 vCPU、磁盘使用量(取自客户机自身的 df,比宿主机侧的克隆大小更真实)、运行时间,以及一个监听端口卡片,将客户机对外可达的套接字列为 <VM-IP>:<port> 端点,并支持一键复制。可能是 HTTP 的服务还会获得一个地球图标按钮,可以通过 Cloudflare 快速隧道将该单个服务暴露到互联网上(一次性许可对话框会解释下载和条款)。对于已挂起或关闭的工作区,仪表板则改为显示机器规格和配置。
操作栏在运行时提供新建终端、挂起、重启和关机,否则提供启动 / 恢复。一个 CONFIGURATION 卡片总结了每个工具的身份验证模式、护栏、提示注入扫描以及共享文件夹。
注意: 指标大约每 1.5 秒从客户机刷新一次。启动后立即显示的零值意味着客户机代理尚未报告。
标题栏控件
当所选工作区正在运行时,每个所选虚拟机的控件簇位于工具栏的尾端:
| 控件 | 作用 |
|---|---|
| IP 药丸 | 以等宽字体显示虚拟机的 IP 地址。点击即可复制——它会闪现已复制。工具提示:VM IP — click to copy。 |
| 流式点 | 当会话元数据正在发送到 bromure.io 时显示的脉动红点(已注册的 Mac、非私有工作区)。参阅企业版。 |
| 引擎徽标 | 本地推理状态:引擎预热时显示旋转图标,就绪时显示绿色 cpu 图标,失败时显示橙色。参阅本地模型。 |
| Fusion 闪电 | 为此工作区切换 Fusion。启用时为黄色(Fusion engaged — click to disengage)。在至少两个提供商拥有可用凭据之前,它被禁用并带有工具提示 Enable at least two models to use Fusion。 |
| 浏览文件 | 打开每个工作区的文件浏览器窗口(参阅移动文件与剪贴板)。 |
| 重启虚拟机 | 重启客户机。 |
| 检查追踪 (⇧⌘I) | 打开追踪检查器。 |
| 编辑工作区 | 打开工作区编辑器。 |
| 弹出到独立窗口 | 将工作区移动到自己的窗口中(见下文)。 |
| 显示或隐藏代理浏览器 (⌃⌘B) | 切换浏览器窗格(地球图标)。 |
| 显示或隐藏仓库文件 (⌃⌘E) | 切换文件浏览器窗格。 |
弹出与重新停靠
任何运行中的工作区都可以从统一窗口弹出到自己的单虚拟机窗口中:点击其侧边栏行或工具栏上的弹出图标。它的标签页会变成该窗口标题栏中的胶囊药丸条,窗格保持其虚拟机和标签页状态——只有承载窗口发生变化。弹出的窗口带有相同的工具栏控件,加上一个重新停靠按钮(将此虚拟机移回主窗口)和一个共享文件夹弹出框,列出已挂载的宿主机文件夹(点击某行即可在访达中打开它)。点击重新停靠按钮可将工作区折回统一窗口。
使用标签页
每个标签页都是工作区虚拟机单个 tmux 会话内的一个 tmux 窗口。tmux 是权威来源:客户机大约每 0.7 秒发布一次其窗口清单,宿主机将其镜像到侧边栏行(以及弹出窗口的药丸条)中。诸如重命名之类的标签页变更会在大约 40 毫秒内被捕获。
- 新建标签页——按 ⌘T,或点击工作区侧边栏行上的 +。
- 关闭标签页——按 ⌘W,或悬停在标签页行上并点击其 ×。关闭最后一个标签页会结束会话,并通过与关闭窗口相同的关闭操作流程处理。
- 切换标签页——按 ⌘1 到 ⌘9。所选工作区的前九行旁边会出现小的组合键标签;编号遵循侧边栏可见的树形顺序(不包括容器标签页)。
标签页标签显示前台程序(claude、codex、shell 等);工作树标签页显示更友好的显示名称,例如“Website refactoring (claude)”。通过将 shell 附加到 Docker 容器中打开的标签页会嵌套在 Docker 节点下的该容器中,而不是在顶层。
注意: 标签页关闭后,tmux 窗口索引可能会出现间隙;UI 会处理这种映射,⌘数字组合键始终遵循你在侧边栏中看到的内容。
代理状态点
每个标签页的图标都带有一个彩色状态点,用于跟踪其中运行的代理:
| 点 | 含义 |
|---|---|
| 橙色,脉动 | 代理正在工作 |
| 绿色 | 代理已完成 |
| 红色 | 代理需要你的输入 |
对于 Claude Code,状态由每个窗口的钩子驱动;对于其他代理,则由流量代理服务器驱动,因此这些状态点无需在虚拟机内进行任何配置即可工作。
Git 工作树
git 工作树是同一个仓库的第二个工作副本:另一个分支被检出到它自己的目录中,共享仓库的历史记录,但拥有自己的文件和自己的索引。Git 支持同时存在多个工作树,因此可以并行处理多个分支,而无需暂存更改、重新克隆或就地切换分支。
Bromure 在此基础上构建了并行的代理工作线。任何工作目录位于 git 仓库内的终端标签页都可以派生出一个带有自己嵌套代理标签页的工作树——一个代理在 wt/website-refactoring 上重构站点,另一个代理在 wt/login-fix 上追查错误,每个都在自己的检出中,互不干扰对方未提交的文件。当一条工作线准备就绪时,你可以将其分支合并回去(或从中打开拉取请求)并丢弃该工作树。这是将一项任务同时分派给多个代理并在终端网格中观察它们的自然方式。
创建工作树
右键点击侧边栏中的任意标签页行以打开其上下文菜单。有两项始终存在:
- 新建工作树…——打开下文描述的对话框。当标签页的工作目录不是 git 仓库时,该项会显示但被禁用,标记为 新建工作树… (Not in a git repo),因此菜单永远不会静默为空。工作树标签页本身就是一个检出,因此它也提供新建工作树…——这就是从工作树派生工作树的方式。
- 新建自动化…——用标签页的目录预填充自动化编辑器(参阅自动化)。
新建工作树对话框——“Creates a git worktree branched from this tab's current commit and opens a nested agent in it.”——收集三样东西:
| 字段 | 用途 |
|---|---|
| 任务名称 | 一个简短的人类可读标签,例如 Website refactoring。它会被 slug 化为分支名称并显示在标签页上。 |
| 工具弹出菜单 | 在新检出中启动的代理——claude、codex 或 grok。默认为工作区配置的代理。 |
| 初始提示(可选) | 代理启动时交给它的第一条消息,这样工作树就可以无人值守地开始工作。留空则以空闲状态打开代理。 |
点击创建(或取消)。Bromure 会添加一个从标签页当前提交派生的 git 工作树,分支名为 wt/<slug>——slug 是任务名称的小写形式,其中连续的其他字符会被折叠为单个短横线,并上限为 40 个字符;如果某个名称对应的分支已存在,则会加上 -2、-3 等后缀。然后会在新检出中打开一个嵌套代理标签页,标记以任务名称和工具,例如“Website refactoring (claude)”。
注意: 如果无法确定标签页的工作目录,会弹出一个警告——“This tab's working directory isn't available yet”——说明该工作区很可能运行的是较旧的虚拟机内代理,并建议重启它(关机,然后启动),以便它启用工作树支持。
工作树标签页如何嵌套
工作树标签页嵌套在它们派生自的标签页下方,缩进并以一个小的分支字形作为前缀,因此嵌套的子代理读起来像分支而不是普通标签页。由于工作树本身也可以被派生,嵌套是一棵树:支持从工作树派生工作树,缩进在每一层向内推进,最深可达 6 层。附加终端标签页和运行中的 Merge → … 标签页也以同样的方式嵌套在其工作树下。这仅仅是一种显示顺序——每个标签页仍然是普通的 tmux 窗口,⌘数字组合键遵循可见的树形顺序。
要并排观察多个工作树代理,请使用工作区 ⋯ 菜单中的将工作树添加到网格,它会一次性将该工作区的每个工作树标签页添加到终端网格中。
工作树操作
右键点击工作树标签页可查看专门针对它的操作——合并…、附加终端,以及(在分隔线下方的)丢弃工作树。
合并… — 将分支合并回去。 该对话框在一个检出到目标位置的新标签页中运行合并;只有工作树分支上已提交的工作才会被合并。它的目标选择器会遍历祖先链——直接父工作树,然后是该工作树的父级,依此类推直到仓库根(“«branch» (repo root)”)。直接父级是安全的默认选项并已为你选中;选择更高层级的任何项都会被标记为 «label» ⚠︎ skips intermediates,因为那些中间工作树将永远收不到该更改。选择一个目标并点击合并。
- 冲突会自行解决。 如果合并发生冲突,编码代理会就地在合并标签页中启动以自动解决它。如果它在冲突未解决的情况下停止,合并标签页会在其自己的右键菜单中提供让代理解决冲突以再次尝试。
- 创建拉取请求。 当工作区拥有 GitHub 凭据时(这也是在虚拟机内为
gh进行身份验证所需的),合并对话框会多出第三个按钮,创建拉取请求。它不是在本地合并,而是推送分支并让代理针对所选目标打开一个干净的 GitHub 拉取请求。参阅凭据。 - 合并不会丢弃工作树——你在对结果满意后自行清理它。
附加终端会打开一个普通终端标签页——没有代理,只是一个已经 cd 进工作树检出的 shell——嵌套在工作树下方,以便你手动检查或测试它的更改。
丢弃工作树是清理步骤,它具有破坏性:它会移除检出并删除分支。该分支上任何从未合并的提交都会丢失,因此它会先询问——“Discard worktree “«name»”?”——并连同检出一起关闭标签页。
注意: 只有已提交的工作才会跨越合并或拉取请求。工作树中未提交的更改会留在该工作树中,一旦你丢弃它就会永久消失。
来自定时自动化的工作树
定时自动化也会创建工作树。每次无人值守的运行都会在自己的 wt/<slug> 分支上创建一个全新的 git 工作树并在其中启动代理,因此一次运行会落地为一个普通的工作树标签页——缩进、可附加、可合并,与你手动创建的完全一样。参阅自动化。
终端
活动标签页在一个原生的、宿主机侧的终端界面(libghostty,Metal 渲染)中渲染,通过 virtio 套接字附加到它的 tmux 窗口。该界面的子进程仅仅是一个字节泵,因此子进程死亡——虚拟机重启、套接字断开——绝不会丢失终端状态:界面只是重新生成并以退避方式重新连接。如果原生终端无法启动,应用会静默回退到虚拟机的图形帧缓冲;两者都是同一个 tmux 会话的视图。
外观——字体族与大小、背景与前景色、光标形状与闪烁——来自工作区的外观设置,并在你保存配置文件时实时生效。新工作区以深板岩背景(#212734)上的 JetBrains Mono 12 作为初始设置,前景色取自你的 Terminal.app 主题。只有等宽字体才会渲染;无法解析或比例字体会回退到 Menlo。
字体缩放可按每个界面进行:⌘+ / ⌘− / ⌘0、触控板捏合(每 ±0.25 放大步进对应一个字号),以及双指双击以重置。
窗口不透明度低于 1.0 的工作区会获得磨砂玻璃终端:终端区域以背景模糊与桌面合成,而标题栏、侧边栏和分隔条保持不透明。不透明度被限制在 0.3–1.0 之间,并在保存配置文件时实时生效。
终端网格
网格是一个舞台界面,它可以并排显示最多 25 个实时终端(布局趋向方形,上限为 5 × 5),来自任意工作区的混合组合——非常适合观察一群工作树代理。每个单元格都是该 tmux 窗口上自己的实时终端界面,独立于工作区的舞台视图,因此两者可以同时打开。
- 添加终端——将任意标签页行拖到侧边栏顶部固定的 Grid 节点上(其工具提示为“Drag terminals here to watch them side by side”),或在活动终端上按 ⌘D 以将其固定并跳转到网格。工作区 ⋯ 菜单中的将工作树添加到网格会一次性添加每个工作树标签页。
- 显示网格——点击 Grid 节点(或折叠图标栏上的网格按钮)。点击某个成员行会聚焦其单元格。
- 单元格控件——每个单元格的标题显示状态点、工作区名称和标签页标签,带有悬停控件在工作区中打开和从网格中移除 — 终端保持运行,以及一个用于交换单元格位置的拖动手柄。右键点击单元格标题可获得相同的操作。
- 缩放——双击单元格(或在聚焦的单元格上按 ⌘↩)以将其放大到全舞台;再次操作可取消放大。Esc 有意不取消放大,因为代理会使用 Esc。
属于关闭或挂起工作区的单元格会保留为带有 Off 或 Suspended 标签和启动按钮的占位卡片;其 tmux 窗口已消失的单元格会被清除。网格成员关系会在应用重启后保留(存于 ~/Library/Application Support/BromureAC/grid-layout.json)。
代理浏览器窗格
浏览器窗格是舞台内右侧的一个分栏,承载一个实时的 Chromium——运行在自己的一次性辅助虚拟机中,每个工作区一个,在首次打开时惰性创建。你和代理都可以驱动它:代理通过内置的浏览器 MCP 服务器控制它,它们的工具调用可以为所选工作区自动启动并显示浏览器。在你手动关闭窗格之后,它绝不会自行重新打开。
提示: 本节将浏览器作为会话窗口的一个窗格来介绍。有关使用它的完整指南——自己驱动它、让代理通过
browser_*工具驱动它、保持登录状态以及隐私模型——请参阅嵌入式浏览器。
用 ⌃⌘B 或工具栏的地球按钮切换窗格。首次打开它时,一个许可卡片会询问安装浏览器?,附带 下载并安装 / 暂不——浏览器镜像是一次性下载,大约 500 MB。
你可以在其中做什么
窗格是一个无边框的浏览器视图,顶部带有一个紧凑的 Safari 风格标签栏:
- 后退 / 前进——箭头按钮,或 ⌘[ 和 ⌘]。
- 标签药丸——每个标签一个药丸;活动药丸兼作 URL 字段(“Search or enter URL”)。裸主机名会被加上
https://前缀;任何不是 URL 的内容都会变成一次 Google 搜索。 - +——新建标签页(窗格获得焦点时按 ⌘T)。
- 开发者工具——切换 Chromium 的开发者工具(F12)。
- 共享——标准的 macOS 共享菜单。
- 站点信息——点击网站图标可获得站点信息弹出框,在 HTTPS 页面上包括证书详情。
由于浏览器虚拟机与工作区虚拟机共享同一个 NAT 子网,它可以通过工作区的 IP 直接加载代理的开发服务器——从工具栏的 IP 药丸复制它即可。
拖动窗格的左边缘可以调整其大小(默认 640 点,介于 380 和 1400 之间;终端始终至少保留 240 点)。拖到最小值以下会关闭窗格。
生命周期与持久化
浏览器默认是一次性的:它的磁盘是一个临时克隆,在浏览器拆除时被删除,因此 cookie 和登录信息会随之消失。隐藏的浏览器会在 10 秒后挂起,并在折叠 5 分钟后被完全拆除。窗格的打开/关闭状态会在应用运行期间按工作区记住,但有意不跨应用重启保留——反正临时浏览器也无法在重启后存活。
要保持登录状态,请在工作区的浏览器设置中启用保持网站登录状态:Chromium 的配置文件随后会存放在每个工作区独立的加密磁盘上,并在拆除后存活。切换该设置会重启工作区的浏览器(保存时会有警告)。
注意: 当浏览器视图拥有键盘焦点时,⌘Q 和 ⌘Tab 会被客户机捕获。点击终端或侧边栏可将它们收回。
文件浏览器窗格
文件浏览器窗格(标题为 FILES)以 IDE 风格的源文件树显示活动标签页的 git 仓库。只要活动标签页的目录进入某个 git 仓库,它就会自行打开——cd 进入某个仓库,或切换到已经在仓库内的标签页——因此你很少需要手动打开它;你也可以用 ⌃⌘E 或显示或隐藏仓库文件 (⌃⌘E) 工具栏按钮切换它。进入仓库是触发条件,因此从不访问仓库的工作区就干脆永远不显示该窗格。
- 一目了然的 git 状态——文件按状态着色并带有单字母徽标(M/A/U/D/R/!),包含更改的文件夹带有橙色点,一个药丸显示已更改文件的数量。标题中有一个“仅已更改文件”过滤器和一个手动刷新按钮。
- 差异与预览——选择一个文件会打开一个带有 差异 / 文件 分段控件的详情分栏:一个带有 +/− 计数和行号边栏的彩色统一差异,或一个渲染后的预览(Markdown 已渲染、源文件语法高亮、图像和二进制文件被标记)。已删除的文件显示为删除线——“File was deleted — switch to Diff to see what was removed.”未跟踪和新添加的文件没有差异,只有预览。
- 弹出查看器——一个弹出按钮会在一个独立的、支持全屏的文件查看器窗口中打开详情,该窗口会实时跟随窗格的选择。
- 工作树操作——标题正下方的一个栏可以为当前仓库管理 git 工作树,而无需打开侧边栏菜单:新建工作树… 在仓库内始终可用,而合并和删除在活动标签页本身是工作树时出现。它们运行的正是 Git 工作树下描述的相同操作——新建工作树…打开创建对话框,合并打开目标选择器,删除在确认后丢弃工作树及其分支。(仅限本地会话;在远程镜像中,请从侧边栏标签页菜单管理工作树。)
所有数据都是通过 virtio 套接字 shell 通道在客户机内部运行 git(和 head)来收集的——即使没有共享文件夹,窗格也能工作,对远程工作区也是如此。树在可见时每 4 秒自动刷新一次,包含更改的目录会在每个仓库中自动展开一次。
窗格会以 IDE 风格自行打开和关闭:进入仓库(cd 进入某个仓库,或切换到目录位于仓库内的标签页)会打开它;离开进入非仓库目录会关闭它。手动关闭会一直有效,直到你更换仓库。拖动窗格的左边缘可调整大小(默认 260 点,介于 200 和 1000 之间;低于 200 会关闭它)。
注意: 文件树是只读的——它绝不会编辑文件内容(工作树栏运行的是 git 操作,而不是文件编辑)。限制:最多列出 20,000 个文件(超出后树会被截断)、每个预览 512 KB、每个差异 1 MB。
移动文件与剪贴板
文件和剪贴板内容以四种方式跨越宿主机/虚拟机边界:文件浏览器窗口、共享文件夹、终端剪贴板和图像粘贴。
文件浏览器窗口
点击浏览文件工具栏按钮(文件夹图标)可打开一个类似访达的窗口,标题为 Files — «workspace»,用于在虚拟机中传入传出文件。它的位置侧边栏提供 Home——客户机真实的 /home/ubuntu,通过 virtio 套接字文件服务实时浏览——加上每个共享宿主机文件夹一个条目(直接在宿主机上浏览)。行显示图标、名称、大小和修改日期,列表每 1.5 秒自动刷新一次。
- 复制出去——将文件从窗口拖到访达。客户机文件在放下时惰性下载。
- 复制进来——将文件放到面板上的任意位置以将它们复制到当前目录。传输分块进行(6 MB),带有“Copying … in/out”进度药丸;名称冲突会获得访达风格的“ copy”后缀;放入的文件夹会整体到达。
- 工具栏——上箭头(上级文件夹)、等宽的客户机路径面包屑、新建文件夹、在访达中显示(仅限宿主机位置)和刷新。
- 上下文菜单——打开、在访达中显示(宿主机行)和移到废纸篓(宿主机)或删除(客户机)。
- 双击——宿主机文件用其默认应用打开;客户机文件先下载到每个工作区的缓存,然后打开。
注意: 隐藏的点文件不会显示。客户机位置需要一个活动的虚拟机(“The workspace must be running to browse its files.”),刚启动的虚拟机可能短暂报告“The in-VM agent is updating — try again in a few seconds.”
共享文件夹
对于持续的项目工作,共享文件夹通常比一次性传输更好:最多可将 8 个宿主机文件夹挂载到虚拟机中,每个都以 ~/<basename> 的形式符号链接到客户机主目录(带有自动去重,例如 src-2)。在工作区的文件夹设置中配置它们。
剪贴板
剪贴板通过终端协议本身桥接——没有需要配置的单独代理:
- 客户机 → Mac——在客户机内复制(tmux 复制模式、OSC 52)会自动落到 macOS 粘贴板上;在 tmux 中释放鼠标选择即可复制它。
- Mac → 客户机——⌘V 使用括号粘贴将 macOS 剪贴板粘贴到终端中。
- 选择——普通的鼠标拖动以 macOS 风格选择文本;⌘C 复制宿主机侧的选择。选择本身绝不会自动复制。
粘贴图像
在剪贴板上有图像时按 ⌘V 会变成一次文件传输:图像被写入客户机的 /home/ubuntu/.bromure/pastes/clipboard-<timestamp>-<id>.<ext>,并以文本形式在原位粘贴客户机文件路径——因此代理可以从磁盘读取该图像。一个瞬态缩略图小片会出现在插入点,在上传期间带有进度行,完成后短暂停留(失败时为红色),并在你下一次按键时消失。
被识别为图像的内容:从访达复制的图像文件(仅当每个复制项都是图像时)以及裸位图,例如截图或浏览器的“复制图像”——任何同时携带文本风格的内容都会照常以文本形式粘贴,因此普通的 ⌘V 绝不会被劫持。粘贴总量上限为 96 MB(更大则回退到文本),超过 7 天的粘贴文件会在客户机内部自动清理。粘贴目录位于主目录镜像中,因此粘贴的路径能在虚拟机重启后存活。
提示: 链接会自动在另一个方向工作:代理或 CLI 工具在客户机内打开的 URL(OAuth 登录、
xdg-open)会被中继到宿主机并在你默认的 Mac 浏览器中打开。只有http/httpsURL 会被中继,且有速率限制;mailto:链接会被有意丢弃。
检查点与回滚
Bromure 会自动创建回滚点,这样出错的会话无需完全重置即可回退。
捕获什么,以及何时捕获
在工作区每次成功启动时,应用都会在工作区的 checkpoints/ 目录下静默地将两个存储层快照为写时复制克隆:
- 系统磁盘(
disk.img),以及 - ext4 主目录镜像(
home.img,存于checkpoints/home/下),适用于采用现代主目录模型的工作区。
由于检查点只在产生了可用终端的启动之后才创建,因此每个检查点都被证明可启动。保留策略遵循分层阶梯:最近几次启动无条件保留,然后一周内每天保留一个,再然后一个月内每周保留一个。检查点创建是免费的,但随着实时磁盘与它们分歧,会消耗真实的磁盘空间。
恢复主目录
恢复主目录… 位于工作区编辑器的资源窗格中,在你的主目录存储行上(工作区运行时它被禁用——请先关闭会话窗口)。
点击它会在弹出框中列出可用的回滚点——正如对话框所解释的,“each one is the home as it was when that session started”。选择一个并确认:当前主目录会先被创建检查点,因此恢复本身也可以被撤销。从未在 ext4 主目录模型上启动过的工作区会改为显示 No home checkpoints yet。
重置系统磁盘
重置为基础镜像… 位于同一窗格的工作区系统磁盘行上(也是侧边栏 ⋯ 菜单中的重置磁盘),是系统层的核选项:它会删除 disk.img,这样下次启动就会重新克隆基础镜像的全新副本。确认——“Reset “«name»” system disk to base?”——会明确说明会擦除什么:你所有 sudo apt install 的东西,对 /etc、/var、/usr、/opt 的修改,以及系统级配置。你的主目录不受影响:项目、点文件、SSH 密钥和 shell 历史都会存活。
重置在虚拟机运行时被阻止,且重置也会丢弃任何保存的 RAM 快照和标签页状态——全新的磁盘加上旧的 RAM 会立即损坏。
注意: 检查点回答的是与挂起不同的问题。挂起保留当前会话的运行状态,以便你恢复它;检查点保留已知良好时间点的磁盘内容,以便你将损坏的环境回退。挂起快照会在它所属的磁盘被重置或还原时被丢弃。
提示: 要在不启动任何东西的情况下对检查点或已停止工作区的主目录镜像进行取证访问,Workspaces ▸ Open ext4 file… 会在一个只读、类似访达的浏览器中打开任意 ext4
.img——你可以直接在 Mac 上预览和提取文件。有关完整的浏览器、就地编辑和fsck集成,请参阅高级。
关闭会话
关闭会话——通过工作区侧边栏行上的 ×、其弹出窗口的关闭按钮,或在其最后一个标签页上按 ⌘W——会解析工作区在通用设置窗格中的关闭窗口时偏好设置:
| 操作 | 作用 |
|---|---|
| 在后台运行 | 仅分离 UI。虚拟机继续无界面运行——代理继续工作——你可以随时从侧边栏重新连接。 |
| 挂起 | 暂停虚拟机并将其 RAM 保存到磁盘(工作区存储中的 vm.state)。下次启动几乎瞬时恢复它,带有相同的终端;标签栏也会被快照(tabs.json),因此恢复的会话会立即显示其标签页。 |
| 关机 | 一次干净的 ACPI 关机。进行中的进程会停止。系统磁盘和主目录会保留——不销毁任何东西。完整关机会清除任何保存的挂起状态,因此下次启动会冷启动。 |
| 询问(默认) | 每次都显示一个提示:“Close “«name»”?”,带有按钮在后台运行、挂起、关机和取消,以及说明“Run in the background keeps the VM running so you can reattach later. Suspend saves its state to disk. Shut down powers it off.” |
有几个值得了解的细节:
- 挂起/恢复的身份——恢复要求完全相同的虚拟机配置,因此工作区的机器标识符、MAC 地址和共享路径会与快照一起持久化。恢复时,宿主机会 ping 客户机以重新同步其时钟。
- 恢复失败——如果保存的快照在交互式启动时无法恢复,应用会回退到全新启动。而由自动化发起的启动则会中止——它们绝不会静默销毁挂起的会话。
- 挂起期间更改共享文件夹——快照无法针对不同的共享集恢复,因此编辑共享文件夹会强制一个**丢弃挂起的虚拟机…**确认;下次启动会冷启动。主目录和共享文件夹文件不受影响。
- 客户机发起的重启——在客户机内运行
reboot不会结束会话:应用会检测到重启意图并就地重新启动虚拟机。 - 销毁数据始终是显式的——已关机的工作区会保留其磁盘和主目录。数据只会被重置为基础镜像…、清除主目录…、删除工作区(均需确认;参阅工作区)或凭据外泄入侵后的强制擦除所销毁——即便如此,你的配置文件设置、令牌和 SSH 密钥也会保留,共享的宿主机文件夹绝不会被触及。
键盘快捷键
会话窗口的组合键归宿主机所有——它们在终端看到之前就被拦截,因此无论虚拟机内运行什么,它们都能工作。
窗口与标签页
| 快捷键 | 操作 |
|---|---|
| ⌘T | 新建标签页 |
| ⌘W | 关闭标签页(最后一个标签页会结束会话) |
| ⌘1 – ⌘9 | 按侧边栏行顺序选择标签页 |
| ⌘D | 将活动终端固定到网格并显示它 |
| ⌘↩ | 放大 / 取消放大聚焦的网格单元格 |
| ⌘N | 打开工作区管理器 |
| ⌃⌘S | 切换侧边栏 |
| ⌃⌘E | 切换文件浏览器窗格 |
| ⌃⌘B | 切换代理浏览器窗格 |
| ⇧⌘I | 打开追踪检查器 |
终端
| 快捷键 | 操作 |
|---|---|
| ⌘C | 复制选择 |
| ⌘V | 粘贴(图像作为文件上传到客户机) |
| ⌘+ / ⌘− / ⌘0 | 字号增大 / 减小 / 重置 |
| 捏合 / 双指双击 | 缩放字体 / 重置缩放 |
浏览器窗格(获得焦点时)
| 快捷键 | 操作 |
|---|---|
| ⌘T / ⌘W | 新建 / 关闭浏览器标签页 |
| ⌘R | 重新加载 |
| ⌘[ / ⌘] | 后退 / 前进 |
| ⌘L | 聚焦地址字段 |
| F12 | 切换开发者工具 |
注意: 80 毫秒的自动重复保护意味着按住某个组合键只会触发一次;有意的重新按压则全部触发。