Skip to content
beamiterPublic

About

GTK4-based terminal emulator

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

2,128 Commits

Folders and files

Repository files navigation

forge

forge 是一个面向开发工作流的原生 GTK4 终端。它默认使用 Block 后端,把命令、输出、退出状态和工作目录组织成可搜索的结构化块;需要传统终端语义时也可切换到 VTE 后端。

能力概览

  • 默认 Block、连续滚屏 Unified、传统 VTE 的三终端后端
  • 标签页、混合后端分屏、方向导航、缩放、前台进程关闭确认与多窗口独立会话恢复
  • 拖动普通单-pane 标签到目标 pane 四边即可无损并入分屏;拖动分屏标题栏回标签栏即可恢复为普通标签。短暂悬停会预览目标页,取消或中心释放不会重启、复制 PTY
  • 跨命令块搜索、失败/慢命令筛选、只记录元数据的 JSONL 命令历史
  • 搜索栏 Preview:在有界、冻结的已完成记录保留文本中逐个高亮同一行的重复匹配;不改变原生终端选择
  • 跨终端区域拖选以整区轮廓标记,按显示顺序复制完整保留文本;单区域仍使用原生按字选区,不抢占 PRIMARY
  • 活动选择卡片常驻 Review selection 操作;审阅关闭后恢复原历史操作焦点,保留滚动和未读状态
  • 原生 Block review:完整命令、工作目录、完成/捕获来源,以及按历史顺序审阅与安全复制多选命令
  • 统一模糊面板:动作、历史、YAML/TOML workflow 和自然语言命令入口
  • 可执行 .jtnb.md Notebook,逐 cell 运行/停止并分离 stdout 与 stderr
  • 基于现代 GTK4 列表模型的异步文件树、Git 分支/脏状态条、长命令桌面通知
  • SSH 主机选择、连接复用与自动重连
  • 可选多 provider AI、可搜索和归档的多会话 Chats 库,以及绑定当前 Block pane 的原生 Shell Agent;每条候选命令均可编辑且需单独批准
  • 配置热重载、可覆盖的应用动作快捷键、8 套内置主题
  • CJK 输入法和 Unicode 安全的搜索/通知显示

分屏会继承当前 pane 的后端:Block 创建 Block sibling,VTE 创建 VTE sibling,并可继续嵌套。每个可见 pane 都独立拥有并清理其进程,关闭 pane、标签或窗口前会统一检查前台任务。

Ctrl+滚轮按鼠标位置独立缩放:顶部栏与侧栏共用一组字号,主内容区(含分屏、Block/Chat/VTE)为另一组;基础字号与倍率分别保存并在重启后恢复。普通滚动不变,字号快捷键仍控制主内容区。

附加字体回退列表不会再把多余空格当作字体名的一部分,缺失主字体时可正确解析显式回退字体。

默认字体 JetBrainsMono Nerd Font Mono 未安装时,运行时自动使用系统 Monospace 等宽字体; 不会改写配置或覆盖自定义字体/字体列表。安装字体后重启即可使用。

构建与运行

推荐使用仓库提供的 Nix 开发环境:

nix develop
cargo run

也可以在安装 GTK4、libadwaita、VTE GTK4、PCRE2 与 pkg-config 开发包后直接使用 Cargo。

GTK4 栈必须足够新(glib >= 2.80、pango >= 1.52、gtk4 >= 4.14、libadwaita >= 1.5, 以及 GTK4 版 VTE vte-2.91-gtk4 >= 0.76)。Ubuntu 22.04 等稳定发行版自带的这些库过旧, 或根本没有 vte-2.91-gtk4,会导致 cargo install --path . 在 *-sys 构建脚本处失败。 运行 ./scripts/bootstrap_deps.sh 一键准备依赖:

./scripts/bootstrap_deps.sh            # 配好推荐工具链(Nix)
./scripts/bootstrap_deps.sh --check    # 只检测缺什么,不安装
./scripts/bootstrap_deps.sh --backend system --install   # 改用发行版系统包

脚本默认使用 Nix(精确固定匹配的库版本、不污染系统包),也可用 --backend system 改装发行版 -dev 包。

完整本地质量门禁由核心验证和扩展安全检查两部分组成:

make verify
make security
make test-display

make verify 运行格式、测试、独立 Xvfb 下的真实 GTK/VTE 回归、Clippy、Rustdoc、 release 构建、shell 语法和已跟踪文本隐私 检查;make security 通过与 CI 共用的入口对主程序和 ASCII organism 原型的已提交 Cargo.lock 运行 warnings-denied RustSec、依赖策略/许可证/来源门禁、重复依赖审计与 ShellCheck,不会在检查过程中解析出另一份依赖图。 两者现在都自动进入锁定的 Nix 开发环境,不会意外使用系统中过旧的 GTK/VTE; make test-display 会在独立 Xvfb 会话中逐项运行真实 GTK/VTE 回归。只需运行轻量隐私 检查时可使用 make privacy。

make package 刻意使用宿主 Cargo 与系统 GTK/VTE 开发库:发行归档按兼容系统的动态库 ABI 分发,不能把 Nix store 解释器/RPATH 烘进裸二进制。日常构建和验收仍使用上面的 Nix 门禁。

安装脚本默认优先使用 Nix;没有 Nix 时自动退回 Cargo,并在备份已有配置后替换为随版本提供的默认配置(保留自定义配置请加 --no-config):

./scripts/install.sh
./scripts/install.sh --backend cargo
./scripts/install.sh --binary /path/to/forge   # 跳过构建,安装已有产物
./scripts/install.sh --prefix /opt/forge --no-config
./scripts/install.sh --dry-run

无参数源码安装统一使用 ~/.local/bin/forge,显式 --prefix 时二进制改为 PREFIX/bin/forge;安装与卸载使用同一规则。脚本同时安装 forge-support-bundle,并把 shell 集成、内置 workflow 和欢迎 Notebook 安装到 ~/.local/share/forge/;安装器会自动纳入 共享加载器接受的全部 .toml / .yaml / .yml 示例,卸载时只移除这些自带文件并保留同目录的用户 workflow。配置使用 0600。即使桌面设置了自定义 XDG_DATA_HOME,运行时也会把这个默认安装位置作为兼容搜索层, 因此不会在删除源码 checkout 后丢失示例或 Notebook。脚本支持 DESTDIR、XDG_CONFIG_HOME 和 CARGO_TARGET_DIR;使用非默认 prefix 时可通过 FORGE_ASSET_DIR / FORGE_WORKFLOW_DIR 指向对应的 share/forge 目录。 同一套 workflow 资产收集器也用于 Nix、Flatpak 和可重定位 release bundle;发布包回归会实际完成打包、 解包、私有 HOME 安装与卸载,阻止某个通道退回只复制 .yaml 或手写文件名。

--binary 输入必须是可读、非符号链接的普通文件。Bash 的初始 no-follow 检查与 open 本身并非原子操作;只有成功打开且用 GNU stat 复核路径和描述符指向同一设备号/inode 后, 之后替换路径名才不会改变通过 Linux /proc/self/fd 复制的 inode。目标文件先在同目录用 mktemp 写完,再由 GNU mv -T 原子替换;rename 前失败或退出会清理临时文件并保留旧版。 rename 是二进制更新的提交点:只保证提交前失败/退出保留旧目标并清理未提交临时文件; 之后若其他资源安装失败,不会回滚已经提交的二进制。 支持工具、shell 集成、workflow、Notebook、AppStream 与图标也都在目标目录内先写入 mode 正确的临时文件,再原子 rename;所有源文件在构建和首次写入前完成预检。 首次配置用同目录临时文件加无覆盖硬链接原子发布:若另一个进程先创建 config.toml,安装器保留并报告并发赢家。--binary 拒绝零字节文件,且不能与显式 --backend 同用。非根 DESTDIR 会先折叠重复 / 和词法 . 段,再从 / 起检查其 完整既存祖先链;任何符号链接都会在安装写入或卸载删除前被拒绝(--purge-config 的 递归根也先整体预检)。这是既存状态预检,不承诺抵御检查后的并发路径替换;普通主机 安装/卸载不套用这条打包边界策略。--prefix、--bin-dir、XDG 路径与 DESTDIR 必须是 无控制字符、无词法 .. 段的绝对路径;运行时路径仍可含空格、Unicode 与 . 段。 卸载默认保留用户配置、状态与历史:

./scripts/uninstall.sh
./scripts/uninstall.sh --purge-config   # 明确删除全部配置和状态
bash scripts/test-install-paths.sh      # 私有 DESTDIR 安装/卸载合同

桌面集成(应用列表里的图标)

./scripts/install.sh 默认一并安装桌面集成,无需额外步骤,安装后 forge 就会出现在 GNOME/KDE 的应用列表里,可以搜索、点击启动、固定到 dock:

安装内容 位置(默认 prefix)
启动器条目 ~/.local/share/applications/io.github.beamiter.forge.desktop
应用图标 ~/.local/share/icons/hicolor/{scalable,128x128,256x256}/apps/io.github.beamiter.forge.*
AppStream 元数据 ~/.local/share/metainfo/io.github.beamiter.forge.metainfo.xml

安装时脚本会把 Exec= / TryExec= 改写成二进制的绝对路径(系统 prefix 如 /usr 除外), 因为桌面会话的 PATH 在登录时就固定了:若 ~/.local/bin 不在其中,TryExec=forge 会失败并让条目整个从应用列表中消失——这是"装好了却找不到图标"最常见的原因。 随后脚本会校验条目并刷新 update-desktop-database 与 gtk-update-icon-cache(陈旧的图标 缓存会盖住刚装进去的图标);DESTDIR 打包场景下跳过刷新,交由包管理器处理。 --no-desktop 可只装二进制。

自检与手动刷新:

desktop-file-validate ~/.local/share/applications/io.github.beamiter.forge.desktop
gtk-launch io.github.beamiter.forge          # 按启动器条目实际启动一次

图标若一时没刷新,注销重登(或 X11 下 Alt+F2 → r 重启 GNOME Shell)即可。 Wayland 下窗口按 app_id 与条目关联,X11 下则依赖 StartupWMClass=forge——GTK4 的 X11 WM_CLASS 取自程序名而非 application ID,写成 application ID 会导致 dock 里出现 一个没有图标的重复条目。

nix build / nix run 分别构建和启动 flake 中的默认 package/app, nix flake check 验证同一 package。离开 nix develop 后,可用宿主系统工具链生成 确定性、带 SHA-256 的本地安装归档:

make package
(cd target/dist && sha256sum --check *.sha256)

该归档可换目录后安装,但仍动态依赖兼容的 GTK4、libadwaita、VTE GTK4 和 PCRE2 系统运行库,并非静态或自包含的 portable 应用。

Flatpak 与桌面集成

项目使用稳定应用 ID io.github.beamiter.forge,提供 desktop、AppStream、 SVG/PNG 图标以及可复现 Flatpak 清单。Flatpak 中的 Shell、SSH、Git、curl 和通知命令通过 flatpak-spawn --host 运行,因此终端操作的是宿主环境而 不是一次性沙箱;原生安装路径保持直接执行。内置 shell 集成、workflow 和 欢迎 Notebook 一并安装在 /app/share/forge/。

flatpak-builder --user --install-deps-from=flathub --force-clean \
  --disable-rofiles-fuse --repo=flatpak-repo flatpak-build \
  packaging/flatpak/io.github.beamiter.forge.yml
flatpak build-bundle flatpak-repo io.github.beamiter.forge.flatpak \
  io.github.beamiter.forge

权限模型、宿主桥接、安全边界、安装命令与已知限制见 Flatpak 指南。

启动与配置

默认配置路径为 ~/.config/forge/config.toml。从完整示例开始:

forge --init-config
forge --check-config

也可使用独立配置:

forge --config ~/my-forge.toml
forge --check-config ~/my-forge.toml

常用启动覆盖不会修改配置:

forge ~/project
forge --mode block --no-restore
forge --mode chat --no-restore
forge -d /tmp --execute bash -lc 'printf "hello\\n"'
forge --safe-mode

--safe-mode 不读取指定或默认配置,也不采用 FORGE_* 外观/行为覆盖;它使用内置 VTE 主题与默认快捷键,并禁用配置重载、恢复、持久化、远程主机、历史、仓库探测、AI/Agent 与 Notebook 执行,适合排查损坏配置或启动环境。

诊断命令均可在没有图形显示的 SSH/CI 环境运行:

forge --help
forge --doctor --json       # 同时报告 ready / active 会话快照数量
forge --check-config --json
forge --config-path
forge --restore-config-backup
forge --print-default-config
forge --shell-integration bash
forge --generate-completion zsh
forge-support-bundle ~/Desktop

--doctor 除配置语义和运行时依赖外,还检查配置权限、有效轮换备份、写锁、AI provider/密钥存在性、workflow 搜索位置、欢迎 Notebook、历史和 SSH 就绪度;不会发起网络请求。support bundle 使用额外的脱敏诊断模式,只收集权限/大小、计数、非敏感系统特征和选定环境变量的“存在/不存在”,不包含配置、命令/输出、会话内容、密钥、主机名或本地路径。分享前仍应逐项检查归档内容。

配置文件保存后会自动热重载;Ctrl+Shift+R 可手动重载。应用内保存会先验证 TOML 与语义、获取进程锁并检查磁盘 revision,再以 0600 临时文件同步、原子替换并轮换两份有效备份;冲突、锁超时、无效内容或 I/O 错误会显示原生提示,且不会覆盖磁盘。--restore-config-backup 可恢复最近的有效备份。

远程连接在最终 argv、重连、会话恢复和 remote Files probe 边界都会重跑同一个 应用级 gate(字段/总 argv 字节预算、视觉欺骗字符、目标语义与结构化 OpenSSH 选项)。ssh_args 可以使用 -p 22、-o Name=value 等选项,但不能塞入第二个 destination 或提前的 --。最多前 128 个 profile 可执行;索引越界或运行态被改坏的 profile 只显示安全有界诊断,不会 spawn。

Files 侧边栏的位置选择器可直接浏览 Local、ssh: … 与 docker: …;旁边的 终端按钮把“浏览”接到“进入”:本地在当前树根新开标签,远端通过同一受管 profile 建立 SSH/Docker 会话(由远端 shell 决定默认目录)。远端 home 探测在后台进行,失败 会保留此前已提交的位置、树、选择与历史。热重载或设置改动会按完整 profile 身份重映射 位置和剪贴板;不能证明仍是同一目标时会先验证安全的 Local 目标,绝不会把旧路径静默 指向另一台主机或容器。 文件树默认隐藏点文件,标题区的眼睛按钮可直接切换;它只重新过滤已加载的 GTK 模型, 不会扫描磁盘、改变远端身份或丢失展开状态,并可与名称过滤同时使用。 远端目录的展开、手动刷新和文件操作后刷新共享逐目录的 latest-wins revision;同一路径 有多个慢请求重叠时,新 revision 会主动取消并从队列物理移除旧扫描;已运行的 SSH/Docker list 通过进程组 watchdog 终止。扫描由固定 8 个 worker 和最多 64 个排队任务承载,不会 按请求无限创建线程;root 导航、手动刷新、惰性展开使用带权优先队列,导航优先且每轮仍给 惰性展开服务机会。调度器还按完整 filesystem authority 公平轮询;全局最多 8 个扫描、每个 远端最多 2 个运行中扫描和 16 个 pending,某台慢主机不能独占 worker 或填满全局队列。全局 64 项已满时,新 authority 的首个 root/手动交互可从最拥挤的其他 authority 腾出一项(优先 惰性任务);其余请求显示可重试的背压状态。文件变更也由固定 4 个 worker 与 32 项有界队列执行,不再 为每个菜单操作创建线程。只有最新结果能发布。右键目录会刷新该目录而不是整棵树根;即使目录已折叠,只要 子树曾物化,文件操作仍会精确刷新其缓存。刷新继续原位合并条目,网络失败不会清空已经显示 的内容或折叠仍然存在的子树;消失或改型的目录会同步退休其后代扫描、快照和缓存。 远端 list 探针由客户端传入 4097 条硬上限,在远端达到上限即停止输出;多出的第 4097 条只作为“目录已截断”证据,界面最多保留 4096 条,根目录与手动刷新会明确提示。wire parser 仅接纳合法 UTF-8 basename,跳过重复/碰撞路径;符号链接(包括指向目录的链接) 始终不可展开。 初次展开会在树内显示 Loading…;已有内容重验时显示 Refreshing…,仍可继续查看 last-good 条目。失败会在同一目录内变成 Error: … 和可聚焦的 Retry 按钮(带辅助技术标签), 而不是把远端目录伪装成空目录。最近一次成功快照的完成时间会显示为相对年龄;UI 只展示 稳定的错误类别,不回显可能含主机、参数或凭据的 SSH/probe 诊断,所有标签按 UTF-8 边界 截断并替换控制/欺骗字符。失败会按临时/持久类别施加最长 30 秒的逐目录冷却,自动 TTL 与 普通刷新遵守冷却,树内显式 Retry 只旁路一次。远端成功快照满 5 分钟后仍继续可用;Files 可见时每 30 秒最多后台重验 4 个可见且已物化的过期目录,pending revision 自动合并。 焦点位于 Files 文件树时,裸 F5 刷新当前树根;Alt+Up、 Alt+Home、Alt+Right 分别进入父目录、当前文件系统 home、选中的目录,标题栏也提供 Up 和 Home 按钮,右键目录可选 Open Folder。普通 Home/方向键仍由列表导航;终端获得焦点时 这些按键完全不会被文件树截获,其他带修饰 F5 也继续传播。远端 home 必须是绝对且严格 UTF-8 的路径,且 Home 探测冻结启动时的 filesystem authority;配置热重载复用同一数字索引时, 旧主机的晚到结果直接失效,不能作为新主机的路径继续扫描。重新选择当前已提交位置会显式取消 尚在解析 Home 或扫描的另一位置。 刷新对账还会移除已消失条目的选择、清除拖放 hover,并拒绝菜单或确认框里仍引用旧 row 的延迟操作;新建或重命名成功后,下一次成功对账会恢复到新路径的选择。文件操作即使返回 连接类失败也会精确重验受影响父目录,因为远端可能已在断线前提交,避免把回收后的 GTK 行 或过期远端路径用于下一次动作。

树根导航使用独立 nonce 事务:新目标的 listing 成功后才一起提交 location、execution overlay、 root、rows、selection 与 history;失败、被取消或乱序的结果只恢复标题和位置选择器,旧树保持 完全可用。标题栏提供 Back/Forward(分支导航会清空 Forward),每边最多保留 64 个已提交目标; Up、Home、Open Folder、终端 cwd 自动跟随与 profile 重映射都复用同一提交边界。点击路径标题 会打开安全的绝对路径输入与祖先面包屑;长目录名在中间省略以保留操作按钮,悬停可查看完整显示名称,点击仍使用原始完整路径。目录层级较深时,祖先列表可在窗口内滚动,路径输入与 Open/Cancel 保持可见,键盘聚焦会显示对应祖先按钮。输入在 4096 字节内做 POSIX 词法规范化,并拒绝相对路径、 越过 /、控制字符和视觉欺骗字符。扫描日志分别记录 queue/list/reconcile 延迟、入队深度和 对账增删量;活跃子树由 GTK 保持稳定对象身份,旁路注册表使用弱引用,已回收子树不会被缓存永久钉住。 配置重排会按完整 profile 重映射历史;无法证明的历史点直接丢弃。若数字索引已指向另一 profile, 保留的旧快照会明确进入只读 unavailable 状态,扫描、文件变更和“打开终端”均不会把旧路径发给新目标。

在任一 Block、Unified 或 VTE 标签中启动交互式 ssh user@host -p port 时,Forge 也会通过 jterm_core::process::observed_ssh_command 从操作系统报告的真实前台进程树 识别目标(包括来源验证通过的 jsh SSH 升级 launcher);不会解析提示符、OSC 命令文本 或重新解释 shell 字符串。唯一匹配的已保存 profile 优先,否则使用带 temporary 标记的 内存目标。远端 home 探测成功前保留现有文件树;成功且标签、SSH 进程、配置身份和用户 导航/文件操作 generation 均未变化时才自动展开 Files。显式或 jsh 派生的 ControlPath 只保存在扫描、操作、剪贴板和传输的执行快照中,不参与 profile 身份;saved/temporary 表示同一目标时粘贴也不会误走本地 relay。失败提供会重新检查实时进程的重试,SSH 退出 不会强制切回 Local。temporary 位置的终端按钮启动普通交互式 SSH,不假定远端装有 jsh。超长 DSW 等 endpoint 会在选择器中安全地中间省略、保留可辨识的用户/主机前后缀, 悬停仍可查看完整目标。带远端命令或无法安全复用的 SSH 选项会明确拒绝自动跟随,并可 转到 profile 选择器。

日志支持普通级别和标准 target 指令,并输出进程内相对时间、级别与模块名:

FORGE_LOG=debug forge
RUST_LOG='warn,forge=debug,forge::state=trace' forge

FORGE_LOG 优先于 RUST_LOG;未知指令会被忽略,默认级别保持 warn。

CLI 补全可按需加载,支持 bash、zsh、fish 和 PowerShell,不需要额外运行时依赖:

# bash
source <(forge --generate-completion bash)

# zsh
source <(forge --generate-completion zsh)

# fish
forge --generate-completion fish | source

# PowerShell
forge --generate-completion pwsh | Out-String | Invoke-Expression

Block 模式可通过 finished_block_viewport_rows 调整长块出现顶部/底部导航控件的行数阈值;block_compact = true 可启用更接近 anvil/Warp 的紧凑块间距。两项配置均保持 GTK4 原生实现,不增加运行时依赖。

底部状态栏的长路径和 Git 信息会按可用宽度在中间省略,避免把窗口撑得过宽;悬停可查看完整状态文本,网格、退出状态和标签计数保持正常显示。

安装与更新 jsh

forge 优先使用配套 shell jsh,找不到时才退回 bash。 命令面板中的 Install or update jsh 会在一个独立标签页里运行安装脚本:标签页本身就是进度界面, 可以 Ctrl+C 中断,脚本结束后等待 Enter 再关闭,失败原因不会一闪而过。

安装脚本来自 jsh 仓库并内嵌在二进制里,因此一台从未装过 jsh 的机器也能引导;校验和验证、 rename(2) 原子替换(运行中的 shell 不受影响,新标签页才使用新版本)、旧二进制回滚副本, 以及 PATH 上的 jsh 其实是同名的其他程序时的提示,全部由脚本统一处理。

缺少 jsh 或有新版本时,顶栏下方出现一条可忽略的提示条。检查在后台线程进行,从不自动安装:

jsh_update_check = "daily"    # "startup" 每次启动联网;"daily" 复用缓存;"never" 关闭

daily 复用安装脚本自己的缓存(~/.cache/jsh/update-check.json),同机同时开着多个 jterm 也只产生一次网络请求。 检查失败(离线等)时提示条保持隐藏,只写日志。

核心快捷键

功能 快捷键
新建 / 关闭 Ctrl+Shift+T / Ctrl+Shift+W
下一个 / 上一个标签 Ctrl+Tab / Ctrl+Shift+Tab
标签 1–8 / 最后一个 Ctrl+1…Ctrl+8 / Ctrl+9
搜索 / 命令面板 Ctrl+Shift+F / Ctrl+Shift+P
左右 / 上下分屏 Ctrl+Shift+E / Ctrl+Shift+D
聚焦 / 调整 Pane Ctrl+Alt+方向键 / Ctrl+Alt+Shift+方向键
复制 / 粘贴 Ctrl+Shift+C / Ctrl+Shift+V
配置 / 重载 Ctrl+Shift+O / Ctrl+Shift+R
SSH 主机选择 Ctrl+Shift+S
Block 历史 / 跨块搜索 Ctrl+Shift+H / Ctrl+Shift+G
workflow / 失败块 / 最早块 Ctrl+Shift+M / Ctrl+Shift+X / Ctrl+Shift+N
全选 / 回填 / 清空 Block Ctrl+Shift+A / Ctrl+Shift+I / Ctrl+Shift+K
回填 / 重跑选中块 Enter / Ctrl+Enter
删除选中块 Delete
Block 过滤 / 书签 / 标签栏位置 Alt+Shift+F / Ctrl+Shift+B / Ctrl+Alt+B
AI 面板 / 询问选中块 Ctrl+Alt+Shift+A / Ctrl+Shift+Q
Shell Agent(Block) Ctrl+Alt+G
Agent 任务面板(需 agent_tasks_enabled) Ctrl+Alt+Shift+T
字号增 / 减 / 复位 Ctrl+= / Ctrl+- / Ctrl+0

Tasks 面板显示当前可见数与搜索匹配数,各状态按钮也显示当前搜索下的任务数量;在搜索框按 Enter 打开首个匹配任务。 Clear filters 清除搜索和状态筛选; 当前任务被筛选隐藏时,Show selected task 恢复它的详情并保留原选择。 任务卡的 Agent terminal 与 Validation output 可返回已有终端或验证输出, 包括其他标签页中的分屏。 失败和等待处理的任务会在列表中显示原因预览,悬停可查看有界完整说明。

开启 ascii_organism_enabled 后,本地 ASCII 生命体会响应命令与 Agent 状态。 关闭期间的 Agent 活动不会改变它的生命状态,也不会在重新开启时补发反应。

命令面板中的应用动作及其当前绑定可在 Ctrl+Shift+P 中搜索;这些动作可在 [keybindings] 中覆盖,设为 false 可解除绑定。Block 视图内的上下文键 Alt+Shift+F(过滤)、Ctrl+Shift+B(书签)和 Ctrl+, / Ctrl+.(前后书签) 目前固定,不会被 [keybindings] 覆盖。Ctrl+R 与 Ctrl+P 保留给 shell/readline; Block 历史统一使用 Ctrl+Shift+H。

AI provider、model、endpoint 和 API key 均可在 Settings 的 AI & Agent 分组配置;面板输入的 key 会原子保存到独立的 owner-only 文件,绝不会写入 config.toml,环境变量仍具有最高优先级。AI 面板的分隔条宽度会随配置持久化。New chat 会创建并选中一个新会话,旧会话继续保留在可搜索的 Chats 会话库中;会话自动取标题,也可 Rename、Archive/Unarchive,Delete 前会要求确认;会话库上限为 50,槽位全满且当前会话是最后一个未归档会话时,Archive 会在改动任何状态之前被拒绝并提示先删除一个会话,避免留下一个全部已归档、没有可写会话的库。输入框使用 Enter 或 Ctrl+Enter 发送,Shift+Enter 换行,并保留输入法候选确认语义。请求期间可 Stop,失败或停止后可按原 chat/context Retry;选中 Block 会显示可清除的 context chip,输出被截断时 chip 会明确提示。空会话也提供只填充、不自动发送的快捷提示。

当前选择、每个 chat 的草稿和实际发送的选中 Block 上下文会跟随各自窗口快照恢复;快速关窗会先强制刷新草稿,发送失败或中途退出的问题也会作为可重试 draft 恢复,Ask selected Block 不会覆盖正在编辑的文字,关窗时其内存重试也会转成可恢复 draft/context。集合最多保存 50 条 chat metadata、每个 chat 最多 100 个 turn,紧凑 JSON 总预算仍为 8 MiB;超出总预算时只裁剪最旧的完整问答对,不会删除在途问题,并在对应会话显示 truncated。出站请求另保留最近至多 40 个 turn/256 KiB,单条输入、Block 输出和模型文本分别有 64 KiB、64 KiB、256 KiB 硬上限,可见 AI/Agent activity 各限制为 1 MiB,同时最多运行 4 个 provider 请求。非流式成功响应保持 raw bytes,先通过 jagent 的 1 MiB envelope gate 才解码 JSON;非 2xx 响应最多只有前 2 KiB 可进入诊断 JSON 解析器。窗口状态另为完整 chat metadata 预留 64 KiB,Pane/Tab 数据挤压空间时也不会静默删除整个 Chats 库。旧版单会话 schema v1 会自动迁移。后台回复始终绑定发起请求的 chat,切换不会串话,已经 Delete 的 chat 收到迟到回复时会直接丢弃。默认脱敏覆盖 active、non-active、archived chat 及其 draft/context;--safe-mode 与 --no-restore 的隔离和恢复语义保持不变。

命令面板使用模糊匹配;输入 > 只看动作、@ 只看 JSONL 历史、: 只看 workflow、? 提交自然语言命令请求。历史和 workflow 只写入当前编辑行;? 请求会绑定当前 Block pane,在块流中显示可 Stop/Retry/Regenerate 的审阅卡,并携带可见的 selected Block 不可信上下文。它与命令纠正、Shell Agent proposal 共用可编辑、复制、动态风险提示的审阅逻辑,主操作只会 Insert for review,不会执行。所有审阅式插入都拒绝 CR、LF、Tab、NUL 和终端控制字符,避免多行条目越过“不提交”边界。Ctrl+Alt+G 或顶部栏的 Agent 开关会打开绑定当前 Block pane 的 Shell Agent;若打开时已选中 finished Block,它会作为可见、可移除的不可信上下文附加。Agent 显示目标、provider/model、shell、回合进度、activity 与实时 prompt readiness,可单独 Stop/Retry 当前模型请求,并可切换持久化的 typo-like 命令纠正。严格 JSON proposal 可复制、编辑、Reject、Insert only 或逐条 Approve & Run;Insert only 只回填普通 shell 编辑行并在 Agent 上下文记录“未执行”,危险命令执行仍需第二次确认。完成块的退出码和截断输出随后回灌到下一轮;done 后可用 Follow up 保留上下文追问,回合耗尽后可用 New task 在同一 pane 重置 Agent transcript 与预算。

workflow 是 ~/.config/forge/workflows/ 下的 .toml / .yaml / .yml 「保存的带参命令」,四个 jterm 终端共用同一份格式与同一个加载器(jterm_core::workflows),因此同一个文件在 anvil / ember / forge / frost 里含义相同。没有声明 default 的参数不能留空:留空或只填空白时插入被拒绝并报 missing values: <名字>,参数对话框在按 Insert 之前就用 “Still needs a value: …” 列出仍然空着的行——kill -9 {pid} 不会再插入 kill -9 。每行的 Reset 会恢复文件声明的默认值;没有默认值的行则回到真正的“未填写”状态。声明了 default 的参数(包括 default = "")仍可渲染成空值:「空值有没有意义」由文件说了算,手动清空一个有默认值的字段是有意的空值,Reset 才会恢复默认值;清空一个没有默认值的字段是缺值。模板支持 {name} 与 {{name}} 两种占位符,占位符名两侧的空格会被忽略({{ service }} 等同于 {{service}}),{{ }} 是字面花括号转义且零参数 workflow 也走同一条渲染路径,未闭合的 {{ 原样保留。字段类型必须正确:default = 3000 这类忘了加引号的值、tags 里的非字符串元素、缺 name 的 [[args]] 都会连带整份文件被拒绝,并留下 workflows: skipping <路径>: <原因> 日志(超限、符号链接、非 UTF-8 同理)。用户目录优先于 FORGE_WORKFLOW_DIR、已安装示例和源码树示例,同名先到先得;用户配置目录解析不到绝对路径时该层直接跳过,绝不相对当前工作目录解析。

命令纠正(command_correction_enabled,默认开启)只在 Block 命令以 typo 形状的错误失败后触发,且只在 shell 自己上报了退出状态时触发——边界推断、日志恢复或来源未知的完成记录不再弹卡,那些卡片建立在归属错误的旧 scrollback 上。它先尝试不出网的本地证据(APT 索引、可执行文件 PATH、目标命令自己打印的建议),只有本地证据无法给出候选时才回落到 AI。这一步回落受 ai_share_command_context 管辖,而该开关默认关闭:默认配置下命令纠正不会联系 AI provider,失败的命令、工作目录与至多 8 KiB 终端输出不会离开本机。 需要 AI 纠错请显式设置 ai_share_command_context = true(或 FORGE_AI_SHARE_COMMAND_CONTEXT=1);本地可验证的纠正在两种设置下都照常工作。候选命令统一通过一道安全门:不得引入原命令没有的 shell 控制符、sudo/su/doas、ssh/mosh/scp/sftp,也不得新增“管道进解释器”的阶段(原命令已含管道时也一样,| sh、| /bin/sh、| zsh、| python3 都在内),因此扩大权限或范围的纠正——包括 apt install sud → apt install sudo 这类善意的——会被拒绝;ls | gerp foo → ls | grep foo 不受影响。卡片显示 exit {code} · 证据来源 徽标,失败命令预览截断到 160 字符;纠正永不自动提交,编辑过的候选一律降级为只插入不执行。--safe-mode 关闭 AI 与命令纠正。

全新的 Block pane 在没有完成块、也没有恢复到历史块时,会显示一次性使用提示:完成的命令会成为 可复用卡片,点击 header 选择,右键查看更多操作,Ctrl+Shift+G 跨块搜索。首次被终端接受的 用户输入、第一张卡片完成或历史恢复后,提示都会永久撤下;清空、过滤或容量淘汰到空也不会在同一 pane 重播。它是不可点击且不参与测量 的浮层,不占用实时提示符的 PTY 行数;alt-screen 接管时暂时隐藏、退出后恢复,因而不会遮住 首次启动的 TUI。Unified 与传统 VTE 模式不显示。

跨块搜索现统一提供 Aa(区分大小写)、.*(正则)和 W(整词)三个可组合开关; Ctrl+I / Ctrl+R / Ctrl+W 可在搜索框保持焦点时切换它们。整词边界按 Unicode 字母、数字和下划线判断,扫描结果与落到对应 VTE 后的高亮使用同一查询配置。All / Cmd / Out 可把搜索限制到全部文本、命令或输出,Ctrl+O 循环切换;范围过滤发生在 500 条结果 上限之前,因此另一类文本不会挤占所选范围的结果预算。Failed 只保留真正失败的块(不把用户 主动中断算失败),Slow 只保留耗时至少 1 秒的块;两者可组合且同样先于结果上限执行。查询为空时,任一元数据筛选仍会 为每个符合条件且在所选范围有内容的保留块生成一条可定位代表结果,因此可独立浏览失败或慢块。 结果列表显示当前位置,并支持 ↑/↓ 循环、Home/End 首尾跳转及 PageUp/PageDown 十条分页;查询框保持焦点且选中行 会自动滚入可视区域。Enter 定位并关闭;Shift+Enter 在成功定位实时终端结果后保持面板并 前进到下一条。仅剩快照的结果仍打开快照,不会伪装成可连续定位;失效结果保持原位并显示诊断。 关闭后再打开会在当前窗口进程内恢复上次有效查询、匹配选项、范围及 Failed/Slow/Bookmarked/ Background 筛选,绝不写入 配置或会话快照;Ctrl+U 只清空查询,Reset 或 Ctrl+Shift+U 会把查询、三个匹配开关、 范围及四个元数据筛选一次恢复默认, 超过 8 KiB 的无效文本不会被记住。鼠标点击任一匹配控件或范围后,输入焦点会自动回到查询框。 面板打开期间每 500 ms 只探测完成块的数量、首尾稳定 ID 与 bookmark revision;新增块、同长度历史 轮换或书签变化会防抖刷新结果, 仍存在的当前命中保持选中,查询/输出正文不会在探测阶段被复制。 Block Search 3.8 在稳定命中已被 retention 淘汰时保留最接近的原结果排名,不再突然跳回首行; 查询、匹配开关或范围发生变化仍作为新意图从第一项开始。F5 可立即强制刷新当前索引并保留 选择连续性,且会同步自动探针版本,避免紧接着重复重建。 Block Search 3.9 在标题栏新增可点击的刷新按钮;按钮与裸 F5 共用同步版本探针、取消待执行 防抖及保留选择的重建动作,随后焦点返回查询框。Ctrl / Shift / Alt / Super / Hyper / Meta 修饰的 F5 不会被面板截获,会继续向下传播。辅助技术可读取完整动作名称和 F5 快捷键。每次物理按下 F5 到释放期间最多刷新一次,按住产生的自动重复不会连续重建; 若该次按下带修饰键,保持 F5 时再松开修饰键也不会补触发刷新;窗口失焦会清除 latch,避免 GTK 遗漏 release 后永久抑制刷新。 Block Search 4.0 将标题栏收敛为 Refresh / Reset,匹配与范围、元数据筛选分别占用下面两行, 两行共用显式的自动水平 overflow;在窄窗或放大字体/主题下,超出自然宽度的控件可 滚动到达,Tab 顺序保持不变而不会被裁掉。窗口级 Capture 控制器按 hardware keycode 记录当前 block:search 物理按键,并把同一状态交给 dialog fallback:首次按下 打开或关闭一次,直到 release 前的 repeat 全部只消费,长按不会让面板闪开即关或关闭后再弹回; 中途松开 chord 修饰键也不会把 repeat 泄漏为查询字符;窗口失活会清理可能丢失 release 的 latch。手动刷新会先显示并以中等优先级播报 Refreshing blocks…,让该状态完整绘制一帧,下一帧才执行同步、保留选择的有界重建;期间产生的 新查询、筛选意图或再次刷新会取消旧 frame callback,查询焦点仍立即恢复。 Block Search 4.1 在同一元数据行加入 Background。Block 后端按 commandless block 分类, Unified 后端按记录的显式 background 标志分类;搜索结果会把这类记录的命令、退出码与耗时统一 视为空值,因此它不会同时命中 Failed、精确退出码、Slow 或耗时上下限,即使旧数据含有矛盾字段。 空查询时 Cmd 不为 Background 合成命令结果,All / Out 也只使用真实保留输出的首个非空行; 没有快照或只有空白输出就不显示。范围与筛选仍先于 500 条上限执行。Background 会随窗口内搜索 记忆恢复,并由 Reset 一并清除。关闭请求会持续占用当前 dialog slot 直到其自身 closed 回调, 所以快速关闭、松键再打开不会创建被旧回调误清的第二实例。 Block Search 4.2 加入 Bookmarked 元数据筛选,并与 Failed、Slow、Background 按 AND 组合且先于范围和 500 条上限执行;空查询可直接浏览当前 pane 的书签。书签只在当前运行期保留, Block 与 Unified 共用 pane-local 集合和单调 revision,已打开的面板会自动感知变化;Unified 仅在 真实记录被 retention 淘汰时清除对应书签,不因输出快照或 chrome marker 丢失而误删。每条结果 都有可访问的 ☆ / ★ 按钮,选中结果也可用 Ctrl+Shift+B 切换;同一物理按键长按只切换一次, 中途松开修饰键不会重复切换或向查询框泄漏字符。Block 路径仍复用卡片的集中 toggle,因此卡片 星标、CSS、已启用的 Bookmarked 卡片筛选和搜索面板会同步;Unified 结果也可直接创建书签。 Reset 会清除 Bookmarked 搜索筛选,但不会清空书签集合;书签不写入配置、历史或会话快照。

若希望 Block 准确记录命令边界、退出码和 cwd,可加载内置 shell 集成:

source <(forge --shell-integration bash)

也可从已安装的 share/forge/shell-integration/ 加载 bash、zsh、fish 或 PowerShell 脚本。 若支持的交互式 shell 在启动宽限后仍未发送 OSC 133,Block 会在提示符旁显示原位说明和针对 该 shell 的一行加载命令,可直接复制;随后手动加载集成并出现首个 marker 时,说明会自动撤下。 手动关闭后只保留轻量的 late-marker 监听,不会继续持有整棵 GTK 卡片。 只有通过生命周期与 PTY 前台门禁的 marker 才能撤下说明;伪 marker 不会把状态误报为健康。 jsh(自带 marker)、-c/PowerShell 单命令或脚本、禁用/替换默认 rc 的 shell、ssh/docker 会话与其他 wrapper 不会显示无法修复当前会话的本地 rc 建议。

Block 模式与 anvil 保持相同的选择语义:Ctrl+Up 从最新块进入选择,Shift+Up/Down 扩展范围,普通 Up/Down 移动 active edge,Enter 按终端顺序把所有选中命令回填为 可编辑文本而不执行,Escape 取消选择。回填也必须证明提示符 anchor 已稳定、光标仍在 anchor、 可见 suffix 为空且没有正在验证的 Agent/外部提交;键盘、卡片按钮、右键菜单和 reinput API 共用 这套边界,拒绝时不会发送 Ctrl+U 或历史文本。Ctrl+Enter 直接重跑单个选中块的命令 (右键菜单的 Re-run Command 等价):仅限本 pane 里用户自己已经执行过的单行命令, 并且必须同时证明提示符锚点已稳定、光标仍在锚点、可见后缀为空、没有用户/Agent/外部提交, 且 PTY 前台所有权已回到 shell;右键项的启用状态与键盘执行共用这套门禁。 通过门禁后也不会立即提交:Forge 先插入命令,等待 VTE 稳定显示字节一致的完整文本,再单独发送 CR,从而覆盖“同步检查为空、异步回显却已有输入”的竞态。 多选、后台块和会被截断为首行的多行命令一律拒绝执行,仍可按普通 Enter 回填审阅。 多选回填需要 shell 的 bracketed-paste 支持;否则整次拒绝并响铃,不会静默丢掉首行之后的命令。 卡片提示不再静态声称提示符已就绪:它会显示当前选中数量,单选使用 ↵ recall,多选明确使用 ↵ recall all;只有可安全重跑的单选才显示 Ctrl+↵ run,其他选区不会宣传不存在的动作。 为降低误删,紧凑提示不宣传 Delete,但删除能力与单级撤销保持不变。 选区中的拒绝会消费普通 Enter 或 Ctrl+Enter,短暂显示 busy、dirty、多选或命令不安全等可见 原因并响铃,然后恢复动作提示;连续拒绝会刷新提示时长,旧状态不会提前覆盖新状态;同一个 Enter 不会继续交给实时 VTE。淡出的卡片快捷操作区也不参与 pointer hit-test,因此触摸 header 不会命中 看不见的按钮。 含控制符、嵌入 paste marker 或任何经 sanitizer 改写的历史命令也保持只回填审阅。 AI / Agent / 命令面板的建议仍然只 Insert for review,永不自行提交。 Delete 删除整个选区(不只是 active edge),并且可撤销:命令面板里的 Undo removing blocks 把它们放回按 id 该在的位置——即使期间又跑过新命令,删掉的块也回到 中间而不是被塞到最前面。撤销槽是单级的:一次新的移除(删除或清空)会替换掉上一次。 清空后的 Toast 提供 Undo;清空恢复会把仍保留的旧块书签和多选状态与新状态合并。空 Pane 再次清空不会覆盖撤销槽。全屏程序占用 Pane 或历史容量不足时会保留撤销槽并提示重试,Toast 的 Undo 也仍可用。 Show only failed blocks / Show only slow blocks / Show only bookmarked blocks 会真正 收窄块流:不匹配的卡片被隐藏且不再占据虚拟画布高度(滚动条随之变短),选择用的方向键会跳过 它们,过滤期间新完成的命令若不匹配也不会冒出来;Show all blocks 恢复全部。被信号停止的 命令不算失败,因此不会出现在 failed 过滤里。 Collapse all blocks / Expand all blocks / Collapse or expand block 同样在命令面板里, 用于快速收拢一长串输出;这三个和 Undo 一样默认不占快捷键,可在 [keybindings] 里自行绑定 (collapse_all_blocks、expand_all_blocks、toggle_block_collapsed、undo_clear_blocks)。 折叠状态目前不跨重启保存。 卡片 header 的 Block actions(⋮)始终可见,鼠标、触摸和 Tab 键都能找到完整操作, 与右键菜单共用同一动作和安全门禁;不必先知道右键或快捷键。菜单高度有界,长菜单可滚动, 反复点击不会叠出多个实例。header 快捷区只保留复制输出与 Insert for review,后者只回填 可编辑命令而不执行;过滤、顶部/底部跳转、展开、折叠等统一从菜单可达,窄分屏不再为六个 隐藏图标预留宽度。快捷按钮持有键盘焦点时,鼠标移出不会让它消失;cwd/git/时间/耗时汇成一条可收缩的上下文 摘要,省略后的完整可见文本可通过 tooltip 查看,状态与动作保持独立。

右键多选区域可批量复制命令、输出或完整块;长 Block 提供顶部/底部跳转与 sticky header, 后台异步输出使用独立 Block 样式。历史恢复和撤销清空重建的块与新块拥有完全相同的右键菜单。

命令运行超过 2 秒后,顶部会出现常驻的运行状态条(▶ 命令 用时 加一键 Stop), 不必先滚动离开底部才能看到;滚动到历史中时它会立即出现,并在 alt-screen 程序下让位。 被信号停止的命令(130 SIGINT、141 SIGPIPE、143 SIGTERM)使用独立的 ⊘ interrupted 中性样式,不计入失败:滚动条失败标记、Ctrl+Shift+X 失败跳转和 Failed 过滤都会跳过它们, 原始退出码仍完整保留在徽章、导出和历史中。 生命周期由历史恢复、缺失结束 marker 推断或仍不完整时,卡片头部会显示 recovered / inferred / incomplete chip;健康记录与普通后台输出不显示额外状态。

块内输出过滤(Alt+Shift+F)打开后可用 Escape 或再次 Alt+Shift+F 关闭, 查询文本会保留、焦点交还提示符。alt-screen 程序运行期间,Ctrl+Up 不会进入块选择, Delete 也不会删除隐藏的块;进入 alt-screen 会清除既有块选择。

在块内拖选文本(用于复制)之后,键盘焦点会落在那张卡片上。此时所有 Block 快捷键 依然可用:方向键、PageUp/PageDown、Home/End、Ctrl+Up 进入选择、书签跳转、 Alt+Shift+F 过滤都照常工作;有选中块时 Enter/Ctrl+Enter/Delete/Escape 按卡片提示条的字面意思执行,没有选中块时它们仍然把焦点交还实时提示符。 若焦点位于卡片 header 按钮,普通 Return/Space 仍按 GTK 约定激活该按钮;Ctrl+Enter 才是 明确交给 Block 的重跑手势。 普通打字始终把焦点带回提示符。

后台输出只会在提示符空闲且用户尚未开始编辑时归入独立 Block;一旦输入开始,后续输出保持在当前终端中,避免把 shell 回显、补全或交互输出错误拆块。

许可证

forge 以 MIT OR Apache-2.0 双许可证发布,使用者可任选其一;完整文本见 LICENSE-MIT 与 LICENSE-APACHE。向本仓库提交 贡献即表示贡献者同意按相同的双许可证条款授权该贡献。仓库许可与 crates.io 发布 是两个独立决定,因此 Cargo 包目前仍保留 publish = false。

安全默认值

  • 原始与出站脱敏后的 system prompt 都受 64 KiB 硬上限约束;可选分隔符与完整的 history 省略计数 notice 必须同时容纳,否则请求 fail closed,不会截断高信任指令。预先有界的 history 若仍被 jagent 报告省略,请求同样拒绝发送。
  • AI 会话的公开 owning-string Turn 只支持序列化;恢复必须通过有预算的 ConversationSnapshot::from_json decoder,不提供可绕过该边界的普通 serde 反序列化。
  • 新安装不会写入任何远程主机、用户名、IP 或个人路径。
  • OSC 52 远程剪贴板写入默认关闭。
  • AI 会话库默认对常见云密钥、PAT、JWT 和私钥进行脱敏,覆盖 active、non-active、archived chat 以及草稿和 Block 上下文。
  • Agent 只支持显式选中的 Block pane;prompt 忙或已有输入时拒绝提交,危险模式会醒目标注,但最终批准仍由用户负责。
  • 命令纠正默认不出网:AI 回落需要显式打开 ai_share_command_context,本地证据(APT 索引、PATH、目标输出)始终留在本机。发往 provider 的字段全部以 _untrusted 键单独标注并在写入前净化,provider 应答有大小上限,超限直接拒绝而不解析。
  • workflow 只从解析得到绝对路径的搜索层加载(HOME 未设置时不再退化成 ./.config/forge/workflows),符号链接文件由 O_NOFOLLOW 拒绝,命令模板与 name/description/tags 一样要通过不可见 / 双向字符检查;任何一项不合格就拒绝整份文件,而不是抹掉坏值后照常加载。
  • 命令纠正的自动 helper 探测只执行 root 或当前用户拥有、且 group/other 不可写的规范化可执行文件,整条路径的每一级目录同样校验。属于第三方用户、排在 PATH 前面的同名程序不会被拉起(这也意味着这类机器上没有可用的本地证据,纠正会直接不出现);forge 以 root 运行时系统 helper 仍然可用。
  • Agent snapshot 只通过 jagent 的有预算 decoder 进入内存,Forge 再直接审计该 bounded view 的 proposal 连续性、观察生命周期和状态绑定,不会二次走普通 serde collection 解码。
  • 可执行 Notebook 在独立进程组运行,关闭或停止 cell 会终止其进程组;安全模式完全禁用 Notebook 执行。
  • 命令历史只保存 command、cwd、exit code 和完成时间,不保存输出,并限制单条/总文件大小。
  • Block 历史加载失败后,Retry 会重新加载;重试仍失败时常驻提示会再次显示,不会因先前错误已读而静默消失。
  • Unified 历史解码会校验所有条目,但只保留最新 64 条记录,避免大量微小条目撑大临时数组;不完整恢复仍保留原文件。
  • Unified 历史恢复失败后会保留原文件,空 pane 关闭和后续保存都不会覆盖它;pane 内常驻提示会说明修复或移走文件后需重新打开。更换历史路径也必须先恢复该路径,不能继承旧路径的写入许可。
  • 恢复上限舍弃标签或拆分布局时,原始窗口快照会先保留为恢复副本;若无法保留,窗口会报告并暂停会话保存。恢复副本沿用最多 8 份的既有保留策略。
  • 每个窗口使用独立的原子会话快照;并发窗口互不覆盖,崩溃遗留快照会在下次启动回收。恢复时跳过无效或超限布局不会把活动选择移到其他标签;选中布局无法恢复时,选择其前方最近的保留标签,没有则选择第一个。
  • 配置、会话快照、JSONL 命令历史和 Block 历史使用 owner-only 权限;关键替换路径使用同步写入与原子 rename,降低信息泄露和断电损坏风险。
  • forge-support-bundle 不读取或打包上述内容,只报告脱敏诊断与文件元数据,并以 0600 创建归档。
  • 项目采用 MIT OR Apache-2.0 双许可证;Cargo 包仍有意保留 publish = false,不将仓库许可自动等同于 crates.io 发布。依赖继续由每周 RustSec 审计与 Dependabot 检查。

进一步说明见 用户指南、架构说明、Block 模式验收清单、AI / Agent / Chat 验收矩阵、性能指南、发布流程 和 Tailscale/SSH 配置。参与开发前请阅读 贡献指南、安全策略 与 变更日志。

Files 远端文件安全约束

远端重命名/移动、复制和目录上传的发布阶段需要 Linux、Python 3,以及 libc 和目标文件系统支持 renameat2(RENAME_NOREPLACE)。探针先在目标文件系统检查该能力;不支持时明确失败,不回退到普通 mv,也不安装远端软件。浏览、新建空文件和单文件硬链接上传不依赖 Python。

上传目录先在本地生成有界、私有的完整归档,确认 tar 成功后才连接远端发布;远端在私有同父目录 staging 内解包并原子拒绝同名目标。失败不会删除其他进程创建的目标。子进程组在主进程被回收前终止;非阻塞管道和期限确保继承管道的逃逸子进程无法让取消或超时永久等待。

Native Chat terminal mode

Select forge --mode chat or terminal_mode = "chat" for right-aligned command capsules, wide output cards and a docked native multiline shell composer. This is independent of AI Chat and needs no LLM. The original PTY, shell editor, completion, password input and interactive applications remain in control; running commands and alternate-screen programs temporarily own the same native terminal. Existing defaults and existing panes are unchanged. See Chat mode behavior and acceptance.

Source install upgrades

./scripts/install.sh installs the executable to ~/.local/bin by default. --prefix PATH selects PATH/bin; --bin-dir PATH overrides only the binary directory. Existing binaries are replaced atomically.

The configuration is installed to ${XDG_CONFIG_HOME:-$HOME/.config}/forge/config.toml. An existing regular config is backed up as config.toml.backup.<unique suffix> before replacing it with the bundled defaults. Identical configs do not create extra backups. Use --no-config to retain all custom settings, or copy selected settings back from the private backup after installation. Symlinked configs are left unchanged. --dry-run does not write binaries, configs, or backups.

An already-running terminal keeps its current process; restart it to use the new binary and configuration. If an older copy comes first in PATH, the installer prints the conflicting path.

When installing to the default path, an older ~/.cargo/bin/forge is backed up inside a private .forge.backup.* directory and replaced with a compatibility symlink to ~/.local/bin/forge. This prevents the old PATH entry from launching stale code. Repeated installs reuse that link. Uninstall removes only a matching compatibility link and leaves the backup available for recovery. Other prefixes and unrelated PATH entries are not modified.

About

GTK4-based terminal emulator

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages