本机真实运行 · 2026-10-19 读数

让第一次连上Linux 服务器的人,敢敲下一条命令

SSH 终端、AI 助手、高危命令拦截、决策留痕放在同一个窗口。 AI 不替你按下回车——它先说清要执行什么、依据是什么、失败会怎样; 你自己敲的命令,也过同一道闸。

Electron 43 · React 19 · xterm.js 命令块
数据只落本机 SQLite · 模型可指向本机 Ollama
ssh · student@192.0.2.10 远端会话 每条命令都过一次闸
$systemctl status nginx
放行 · LOW只读查询命令词表 + 子命令护栏
$rm -rf /var/log
已拦截 · BLOCK递归强制删除根级/系统目录结构检测 rmRfProtectedTarget
$curl -fsSL https://example.invalid/install.sh | bash
已拦截 · BLOCK管道把上游内容交给解释器执行结构检测 shellPayloadExecution
命令块 03 风险闸 已生效 留痕 2

演示回放:命令、等级、原因文字逐字取自仓内规则数据 command-rules.json 与 command-gate.ts; 主机地址用 RFC 5737 文档保留段,不是真实机器。终端输出未画,因为这台机器不存在。

示意图:一台本机同时挂着多个远端会话。每条命令和它的输出按会话切成块,拦截与留痕也按会话归属分开存;上面那个终端里每判一条命令,这里就发一颗包。

本机 远端会话 命令下发 / 输出回推 被风险闸拦下

难的不是记命令,
是按下回车之前那段空白

教程给不了失败样本,聊天框给不了执行现场,终端什么都不解释。 这个工作台把三件事接起来:命令在哪里执行、执行前后发生了什么、哪些命令不该执行。

拦在按下回车
之前,不是事后
没有这道闸的时候
$ rm -rf /var/log → 三分钟后发现日志没了,且没有撤销
$ curl … | bash → 脚本内容没人看过,已经在跑了
$ chmod 777 /etc → 报错之前,权限已经放开

初学者的代价通常是“这台虚机废了,重装”。教学环境里,这等于放弃动手。

现在发生的顺序

先分词,再切段。引号里的 ; | && 不算分隔符, 所以 bash -c "rm -rf /; echo x" 不会被撕成两段绕过。

写法变体同判。rm -rf /、rm -rf "/"、 rm -rf // 归一后再比受保护清单。

三个入口一条闸。人敲的、粘贴的、AI 发起的命令,都从同一个执行口出去。

拦下要能说清。每次拦截留痕:命中哪条规则、为什么、替代做法是什么。

八项能力,
每项都对得上界面上真存在的入口

未接线的占位功能不写在这里。没有生产者的统计值不显示在界面上。

8 项
每项都有界面入口
terminal

终端优先,不是聊天框优先

三栏可拖拽,终端格默认最大化;多标签、独立第二窗口,同时看两台机器不来回切。拖出来的宽度会记住。

blocks

命令与输出切成块

OSC 133 / 633 标记把一次命令和它的输出缝成一块,可回看、可检索,也是 AI 读上下文的单位。

gate

拦截发生在执行之前

词表规则 + tree-sitter-bash 结构化解析 + 只读白名单,输出等级、命中依据、影响范围;拦下的那些不会落进 shell。

agent

AI 的每一步落在屏上

思考、工具调用、待执行命令、返回结果分开展示;诊断 / 部署 / 巡检 / 回滚四种模式走同一套编排,流式可中断。问答记录落本地库:重启后接着看,切服务器不串档,清空按下去就真删。

context

用量说清是实测还是估算

上下文占用按模型真实窗口计算;实测 token 与估算值分开标注,不拿估出来的数字冒充实测。

decide

结论后面挂着证据链

多源证据加权融合(Dempster 规则 + PCR5 冲突再分配),雷达图显示每条证据的贡献与冲突流向;权重读取失败时降级为无权重融合,界面如实显示降级。

knowledge

断网也能查的运维知识

命令词典、教程、故障案例三类条目;本地嵌入模型 + SQLite 向量索引做语义检索,不依赖外部 API。读者答复回灌条目成功率。

local

数据与凭据留在本机

服务器信息、历史、知识库存在本地 SQLite;凭据只在主进程边界内使用,日志、报错、AI 上下文出边界前统一脱敏。

点一条命令,看它怎么被判

下面每条的等级与原因文字都是引擎实际会给出的那一句。 网页只做词表与结构检测的演示;真实判定在本地进程里跑,包含 bash AST 解析。

226 条词表项
8 个结构检测器
词表判定项 226
结构性拦截器 8
argv 规则 7
受保护根级路径 15

规则以数据文件维护,改级别不用动代码;但 rm、 userdel、passwd 这类底线命令被数据调低时, 闸会拒绝启动——fail-closed,不让数据把底线改松。

rm -rf /var/log
已拦截 · BLOCK递归强制删除根级/系统目录
由哪一层判出结构检测器 rmRfProtectedTarget(rm 递归 + 强制 + 目标命中受保护清单)
执行会怎样命令不会送进 shell,拦截记录写入本地留痕,界面给出替代做法。

界面长这样

两张图都由自动化脚本从真实运行窗口截取,未替换内容、未做后期。点开放大。

2 张
脚本取自运行窗口

三进程,一条受控边界

渲染层拿不到 Node 能力。所有敏感操作经 preload 暴露的类型化通道进主进程;通道名由一张中央常量表出,已登记契约的通道在入口校验入参。

283 条通道
65 条已登记契约
渲染进程 · React 19

只呈现与发起请求

Zustand 状态容器,Radix + Tailwind 组件层,设计令牌单一来源。沙箱隔离,拿不到 Node 能力。

Preload · contextBridge

受控边界

通道名全部来自一张中央常量表;已登记契约的通道在入口校验入参,错误统一按信封返回。

主进程 · Node.js

能力与判定

ssh2 连接池、node-pty、SQLite、风险引擎、可信度融合、LLM 客户端、MCP 服务、调度器。

invoke 235 条 请求-响应 → event 39 条 事件推送 ← 已登记契约 65 条

命令执行口

人敲的 / 粘贴的 / AI 发起的 → 同一条风险闸 → 通过才送进 shell。拦截在此发生,留痕也在此写入。

Electron 安全三原则保持不动

  • contextIsolation: true
  • nodeIntegration: false
  • sandbox: true

新增能力优先落在主进程。日志、报错、AI 上下文在离开进程边界前统一脱敏;凭据不进渲染层,也不进任何文本产物。

一条 AI 建议从生成到执行

这是产品的核心承诺:任何改动远端状态的命令,都要走完这四步才会落到终端。

4 步
改远端状态都要走完
1

生成

模型基于终端上下文、命令块历史与知识库给出建议,工具调用在流式过程中即时展示,不事后补写。

2

判定

命令进风险引擎:词表 + AST + 只读白名单,输出风险等级、命中依据与影响范围。

3

确认

决策卡由主进程构造——模型无法伪造自己的“已批准”。界面显示准备执行什么、在哪台机器、失败怎么回滚。

4

留痕

执行结果与当时的证据构成写入本地记录,事后在决策页可回查;被拦下的同样留痕,含原因。

技术栈

选型的判据只有一条:能不能让上面那四步真的跑起来,并且跑得起来还查得到依据。

9 层
无 CDN 依赖
层选型
桌面框架Electron 43(contextIsolation / sandbox 全开)
界面React 19 + TypeScript + Zustand 5 + Radix UI + Tailwind + lucide-react
终端xterm.js 5 + node-pty(本机)+ ssh2(远端),两侧命令块口径一致
编辑器Monaco 0.56,资源本地打包,无 CDN 依赖
AIVercel AI SDK 7 + 官方 MCP SDK 1.32,Anthropic / Google / OpenAI 兼容端,支持本机 Ollama
命令解析web-tree-sitter + tree-sitter-bash
存储better-sqlite3 + sqlite-vec 向量索引,@xenova/transformers 本地嵌入
可观测Langfuse 追踪(未配置密钥时自动关闭,不影响主流程)
测试Vitest + Playwright(直驱真实应用窗口,不是 DOM 模拟)

每个数字都带复现命令

单元与结构读数在 2026-10-23 01:45 由本机重跑取得,端到端 01:50 那一轮(含真机靶机),UTC+8。除用例数两条外,这些读数只有一个出口:npm run promo:check。界面和文档里都不出现没有测法的数字。

7 条读数
各带复现命令
读数值怎么量的
单元与组件用例3619 通过npm test 另有 20 条按环境跳过,共 3639;325 个测试文件(323 通过 / 2 跳过)
端到端用例74 通过npx playwright test Playwright 直驱真实应用窗口,13 条按是否需要真服务器 / 真模型跳过
IPC 通道283npm run audit:ipc 244 请求-响应 + 39 事件推送
已登记契约的通道65src/shared/ipc-contract.ts 60 请求-响应 + 5 事件推送
TypeScript / TSX 源文件530git ls-files src 按 .ts / .tsx 计数
命令规则词表项226npm run promo:check 八张表逐项相加,护栏按分组数(早先手数漏了两组,报成 216)
结构性拦截器8denyBaseline.blockDetectors

每次提交前会跑红的门禁

  • ESLint 与 TypeScript 类型检查
  • 测试代码零类型错误(存量只降不升)
  • 死代码闸
  • 设计契约闸:令牌单一来源
  • 真机界面可读性审计(含浅色模式对比度)
  • IPC 契约一致性(生成物与契约对账)
  • 本地密钥扫描
  • Git 历史凭据回归扫描
  • 内网拓扑按值核对(代码与文档两条腿)
  • 只写不读状态键检测
  • 按钮真伪普查:逐页真点每个可见按钮

当前状态与边界

这几条写在这里,是为了让“能做”和“现在就能用”不混为一谈。

4 条
没做到的不写成做到
  • 已公开源码仓库已公开(MIT),但不提供安装包下载:需要界面里那三个 build 脚本之一在本机自行打包,Windows 之外未验证。
  • 需连接监控、日志与远端文件能力需要先连上一台 Linux 服务器;未连接时界面显示空状态,不放示例数据。
  • 看模型AI 能力取决于所配置的模型。本地小模型下工具调用的稳定性会明显下降,此时建议只用于解释与诊断。
  • 会降级可信度融合在证据权重读取失败时降级为无权重融合,界面如实显示降级,不会静默给一个看起来更准的数字。
screenshot