<p align="center">
  <img src="../../src-tauri/icons/icon.ico" alt="OxideTerm" width="128" height="128">
</p>

<h1 align="center">⚡ OxideTerm</h1>

<p align="center">
  <a href="https://github.com/AnalyseDeCircuit/oxideterm/stargazers">
    <img src="https://img.shields.io/github/stars/AnalyseDeCircuit/oxideterm?style=social" alt="GitHub stars">
  </a>
  <br>
  <em>如果你想要一个没有 Electron、遥测或订阅的本地优先 SSH 工作区，请给 OxideTerm 点个 Star，让更多 SSH 用户发现它。</em>
</p>


<p align="center">
  <strong>本地优先的 SSH 工作区：围绕一个远程节点使用 Shell、SFTP、端口转发、trzsz、轻量编辑和 BYOK AI。</strong>
  <br>
  <strong>零 Electron。零 OpenSSL。零遥测。零订阅。BYOK 优先。纯 Rust SSH。</strong>
</p>

<p align="center">
  <img src="https://img.shields.io/badge/version-1.4.6-blue" alt="版本">
  <img src="https://img.shields.io/badge/platform-macOS%20%7C%20Windows%20%7C%20Linux-blue" alt="平台">
  <img src="https://img.shields.io/badge/license-GPL--3.0-blue" alt="许可证">
  <img src="https://img.shields.io/badge/rust-1.85+-orange" alt="Rust">
  <img src="https://img.shields.io/badge/tauri-2.0-purple" alt="Tauri">
  <img src="https://img.shields.io/github/downloads/AnalyseDeCircuit/oxideterm/total?color=brightgreen" alt="总下载量">
</p>

<p align="center">
  <a href="https://github.com/AnalyseDeCircuit/oxideterm/releases/latest">
    <img src="https://img.shields.io/github/v/release/AnalyseDeCircuit/oxideterm?label=%E4%B8%8B%E8%BD%BD%E6%9C%80%E6%96%B0%E7%89%88&style=for-the-badge&color=brightgreen" alt="下载最新版">
  </a>
  <a href="https://github.com/AnalyseDeCircuit/oxideterm/releases">
    <img src="https://img.shields.io/github/v/release/AnalyseDeCircuit/oxideterm?include_prereleases&label=%E4%B8%8B%E8%BD%BD%E6%9C%80%E6%96%B0Beta%E7%89%88&style=for-the-badge&color=orange" alt="下载最新Beta版">
  </a>
</p>

<p align="center">
  🌐 <strong><a href="https://oxideterm.app">oxideterm.app</a></strong> — Documentation & website
</p>

<p align="center">
  <a href="../../README.md">English</a> | <a href="README.zh-Hans.md">简体中文</a> | <a href="README.zh-Hant.md">繁體中文</a> | <a href="README.ja.md">日本語</a> | <a href="README.ko.md">한국어</a> | <a href="README.fr.md">Français</a> | <a href="README.de.md">Deutsch</a> | <a href="README.es.md">Español</a> | <a href="README.it.md">Italiano</a> | <a href="README.pt-BR.md">Português</a> | <a href="README.vi.md">Tiếng Việt</a>
</p>

<div align="center">

https://github.com/user-attachments/assets/4ba033aa-94b5-4ed4-980c-5c3f9f21db7e

*🤖 OxideSens AI —— 从一个助手控制实时终端与工作区工具。*

</div>

---

## 为什么选择 OxideTerm？

| 如果你在意... | OxideTerm 提供... |
|---|---|
| SSH 工作区，而不只是 Shell | **远程节点工作区**：一个节点下聚合终端、SFTP、端口转发、trzsz、轻量 IDE、监控和 AI 上下文 |
| 本地 Shell 也在同一套工作流里 | **混合引擎**：本地 PTY（zsh/bash/fish/pwsh/WSL2）与远程 SSH 同窗共存，本地和远程工作不再割裂 |
| SSH 工作流不需要云账号 | **本地优先核心**：SSH、SFTP、端口转发、本地 Shell 和配置管理都无需注册 |
| BYOK AI，而不是平台点数 | **OxideSens**：使用你自己的 OpenAI/Ollama/DeepSeek/OpenAI-compatible 端点，并支持 MCP 与 RAG |
| 不想要 Electron 运行时 | **Tauri 2.0**：原生 Rust 后端，25–40 MB 二进制文件 |
| 不想背 OpenSSL 包袱 | **russh 0.59**：基于 `ring` 编译的纯 Rust SSH——零 OpenSSL/libssh2 依赖 |
| 不想要遥测或应用订阅 | **零追踪，核心 SSH 工作流零应用订阅**：SSH/SFTP/端口转发/本地 Shell 不需要账号或订阅；数据默认留在你的设备上；云同步通过[官方插件](#官方插件)按需启用 |
| 连接稳定性 | **宽限期重连**：断开前探测旧连接 30 秒——网络抖动时 vim/htop/yazi 仍有机会存活 |
| 不想为了远程文件就打开 VS Code Remote | **内置 SFTP + 轻量 IDE**：在同一个 SSH 工作区内浏览、预览、传输和编辑远程文件 |
| 凭证安全 | **静态加密**：密码和 API 密钥保存在 OS 密钥链中，已保存连接的元数据在本地密封存储，`.oxide` 文件使用 ChaCha20-Poly1305 + Argon2id 加密 |

## 它是什么 / 不是什么

OxideTerm 是一个**本地优先的 SSH 工作区**：打开一次远程节点，就在同一处操作 Shell、文件、端口、终端内传输、轻量编辑和 AI 上下文。

OxideTerm **不是**云端 AI 平台、托管 Agent 服务、远程协议工具箱，也不以终端渲染性能跑分为主要卖点。许多现代终端正在围绕本地 Shell、AI 面板或云端 Agent 平台演进；OxideTerm 则专注于本地优先的 SSH 工作区。

---

## 截图

<table>
<tr>
<td align="center"><strong>SSH 终端 + OxideSens AI</strong><br/><br/><img src="../../docs/screenshots/terminal/SSHTERMINAL.png" alt="带 OxideSens AI 侧边栏的 SSH 终端" /></td>
<td align="center"><strong>SFTP 文件管理器</strong><br/><br/><img src="../../docs/screenshots/sftp/sftp.png" alt="SFTP 双窗格文件管理器与传输队列" /></td>
</tr>
<tr>
<td align="center"><strong>内置 IDE（CodeMirror 6）</strong><br/><br/><img src="../../docs/screenshots/miniIDE/miniide.png" alt="基于 CodeMirror 6 编辑器的内置 IDE 模式" /></td>
<td align="center"><strong>智能端口转发</strong><br/><br/><img src="../../docs/screenshots/PORTFORWARD/PORTFORWARD.png" alt="带自动检测的智能端口转发" /></td>
</tr>
</table>

---

## 下载

从 [GitHub Releases](https://github.com/AnalyseDeCircuit/oxideterm/releases/latest) 下载最新版本。

---

## 功能概览

| 分类 | 功能 |
|---|---|
| **终端** | 本地 PTY（zsh/bash/fish/pwsh/WSL2）、SSH 远程、分屏窗格、广播输入、会话录制/回放（asciicast v2）、WebGL 渲染、30+ 主题 + 自定义编辑器、命令面板（`⌘K`）、禅模式, **trzsz** 带内文件传输 |
| **SSH 与认证** | 连接池与多路复用、ProxyJump（无限跳数）拓扑图、宽限期自动重连、Agent 转发。认证方式：密码、SSH 密钥（RSA/Ed25519/ECDSA）、SSH Agent、证书、keyboard-interactive 2FA、Known Hosts TOFU |
| **SFTP** | 双窗格浏览器、拖放操作、智能预览（图片/视频/音频/代码/PDF/十六进制/字体）、带进度和预计到达时间的传输队列、书签、压缩包解压 |
| **IDE 模式** | CodeMirror 6 支持 30+ 语言、文件树 + Git 状态、多标签页、冲突解决、集成终端。可选 Linux 远程 Agent，其他架构需自行编译并上传 |
| **端口转发** | 本地（-L）、远程（-R）、动态 SOCKS5（-D）、无锁消息传递 I/O、重连自动恢复、终止报告、空闲超时 |
| **AI（OxideSens）** | 面向目标的助手：理解已保存连接、实时 SSH 会话、终端缓冲区、SFTP 路径、设置和知识库条目；可诊断远程输出、执行已批准命令、检查文件并解释故障，无需 OxideTerm 账号 |
| **插件** | 运行时 ESM 加载、18 个 API 命名空间、24 个 UI Kit 组件、冻结 API + Proxy ACL、熔断器、错误时自动禁用 |
| **CLI** | `oxt` 伴侣工具：JSON-RPC 2.0 基于 Unix Socket / Named Pipe、status/health/list/forward/config/connect/focus/attach/SFTP/import/AI、人类可读 + JSON 输出 |
| **安全** | .oxide 加密导出（ChaCha20-Poly1305 + Argon2id 256 MB）、本地配置静态加密、OS 密钥链、Touch ID（macOS）、便携式加密密钥库、主机密钥 TOFU、`zeroize` 内存清除 |
| **国际化** | 11 种语言：EN、简体中文、繁體中文、日本語、한국어、FR、DE、ES、IT、PT-BR、VI |

---

## 技术内幕

### 架构——双平面通信

OxideTerm 将终端数据与控制命令分离为两个独立平面：

```
┌─────────────────────────────────────┐
│        Frontend (React 19)          │
│  xterm.js 6 (WebGL) + 19 stores     │
└──────────┬──────────────┬───────────┘
           │ Tauri IPC    │ WebSocket (binary)
           │ (JSON)       │ per-session port
┌──────────▼──────────────▼───────────┐
│         Backend (Rust)              │
│  NodeRouter → SshConnectionRegistry │
│  Wire Protocol v1                   │
│  [Type:1][Length:4][Payload:n]      │
└─────────────────────────────────────┘
```

- **数据平面（WebSocket）**：每个 SSH 会话获得独立的 WebSocket 端口。终端字节以带有 Type-Length-Payload 头的二进制帧传输——无 JSON 序列化、无 Base64 编码，热路径零开销。
- **控制平面（Tauri IPC）**：连接管理、SFTP 操作、转发、配置——结构化 JSON，但不在关键路径上。
- **Node 优先寻址**：前端从不直接触及 `sessionId` 或 `connectionId`。一切通过 `nodeId` 寻址，由 `NodeRouter` 在服务端原子解析。SSH 重连会更换底层 `connectionId`——但 SFTP、IDE 和转发完全不受影响。

### 🔩 纯 Rust SSH — russh 0.59

整个 SSH 协议栈使用 **russh 0.59**，基于 **`ring`** 加密后端编译：

- **零 C/OpenSSL 依赖**——完整的加密栈由 Rust 实现，告别"哪个 OpenSSL 版本？"的调试噩梦。
- 完整的 SSH2 协议：密钥交换、通道、SFTP 子系统、端口转发
- ChaCha20-Poly1305 和 AES-GCM 加密套件，Ed25519/RSA/ECDSA 密钥
- 自定义 **`AgentSigner`**：封装系统 SSH Agent 并实现 russh 的 `Signer` trait，通过在 `.await` 前将 `&AgentIdentity` 克隆为 owned 值，解决 RPITIT `Send` 约束问题

```rust
pub struct AgentSigner { /* wraps system SSH Agent */ }
impl Signer for AgentSigner { /* challenge-response via Agent IPC */ }
```

- **平台支持**：Unix（`SSH_AUTH_SOCK`）、Windows（`\\.\pipe\openssh-ssh-agent`）
- **代理链**：每一跳独立使用 Agent 认证
- **重连**：`AuthMethod::Agent` 自动重放

### 🔄 智能重连与宽限期

大多数 SSH 客户端在断线时会销毁一切然后从头开始。OxideTerm 的重连编排器采用了截然不同的策略：

1. **检测**：WebSocket 心跳超时（300 秒，针对 macOS App Nap 和 JS 定时器节流优化）
2. **快照**：完整状态——终端窗格、进行中的 SFTP 传输、活动端口转发、打开的 IDE 文件
3. **智能探测**：`visibilitychange` + `online` 事件触发主动 SSH keepalive（~2 秒检测 vs 被动超时的 15-30 秒）
4. **宽限期**（30 秒）：通过 keepalive 探测旧 SSH 连接——如果恢复成功（例如 WiFi AP 切换），你的 TUI 应用（vim、htop、yazi）完全不受影响
5. 恢复失败 → 建立新 SSH 连接 → 自动恢复转发 → 恢复 SFTP 传输 → 重新打开 IDE 文件

管线流程：`queued → snapshot → grace-period → ssh-connect → await-terminal → restore-forwards → resume-transfers → restore-ide → verify → done`

所有逻辑运行在专用的 `ReconnectOrchestratorStore` 中——零重连代码散落在 hooks 或组件中。

### 🛡️ SSH 连接池

引用计数的 `SshConnectionRegistry`，以 `DashMap` 为底层实现无锁并发访问：

- **一个连接，多个消费者**：终端、SFTP、端口转发和 IDE 共享同一物理 SSH 连接——无冗余 TCP 握手
- **每连接状态机**：`connecting → active → idle → link_down → reconnecting`
- **生命周期管理**：可配置的空闲超时（5 分钟 / 15 分钟 / 30 分钟 / 1 小时 / 永不）、15 秒 keepalive 间隔、心跳故障检测
- **WsBridge 心跳**：30 秒间隔、5 分钟超时——兼容 macOS App Nap 和浏览器 JS 节流
- **级联传播**：跳板机故障 → 所有下游节点自动标记为 `link_down` 并同步状态
- **空闲断开**：向前端发送 `connection_status_changed`（而非仅内部 `node:state`），防止 UI 状态不同步

### 🤖 OxideSens AI

隐私优先的 AI 助手，提供双重交互模式：

- **内联面板**（`⌘I`）：快速终端命令，通过 bracketed paste 注入输出
- **侧边栏聊天**：持久对话，完整历史记录
- **面向目标的工作区上下文**：把已保存连接、实时 SSH 会话、终端缓冲区、SFTP 路径、设置和知识库条目视为可操作目标
- **已批准的动作**：可诊断远程输出、执行已批准命令、检查文件并解释故障，无需 OxideTerm 账号
- **MCP 支持**：连接外部 [Model Context Protocol](https://modelcontextprotocol.io) 服务器（stdio & SSE）进行第三方工具集成
- **RAG 知识库**（v0.20）：将 Markdown/TXT 文档导入作用域集合（全局或按连接）。混合搜索通过 Reciprocal Rank Fusion 融合 BM25 关键词索引 + 向量余弦相似度。Markdown 感知分块保留标题层级。CJK 双字符分词器支持中文/日文/韩文。
- **供应商**：OpenAI、Ollama、DeepSeek、OneAPI 或任何 `/v1/chat/completions` 端点
- **安全**：API 密钥存储在 OS 密钥链；macOS 上密钥读取受 **Touch ID** 通过 `LAContext` 保护——无需授权签名或代码签名，每次会话首次认证后缓存

###  端口转发——无锁 I/O

完整的本地（-L）、远程（-R）和动态 SOCKS5（-D）转发：

- **消息传递架构**：SSH Channel 由单一 `ssh_io` 任务拥有——无 `Arc<Mutex<Channel>>`，彻底消除互斥锁竞争
- **终止报告**：转发任务主动报告退出原因（SSH 断开、远端端口关闭、超时），提供清晰的诊断信息
- **自动恢复**：`Suspended` 状态的转发在重连时自动恢复，无需用户干预
- **空闲超时**：`FORWARD_IDLE_TIMEOUT`（300 秒）防止僵尸连接堆积

### 📦 trzsz — 带内文件传输

无需 SFTP 连接，直接通过 SSH 终端会话上传和下载文件：

- **带内协议**：文件以 Base64 编码帧的形式在现有终端流中传输——无需额外端口或 Agent，可透明穿透 ProxyJump 链和 tmux
- **双向传输**：服务端运行 `tsz <file>` 向客户端发送文件；`trz` 触发客户端上传；支持拖放
- **目录支持**：通过 `trz -d` / `tsz -d` 进行递归目录传输
- **传输限制**：可为每个会话配置分块大小、文件数量和总字节数上限
- **原生 Tauri I/O**：文件读写使用 Tauri 原生文件对话框和 Rust I/O——无浏览器内存限制
- **实时通知**：提供传输开始、完成、取消和错误的 Toast 通知——当检测到 trzsz 但功能未启用时也会给出提示
- 前往 **设置 → 终端 → 带内传输** 启用

### 🔌 运行时插件系统

动态 ESM 加载，安全加固的冻结 API 表面：

- **PluginContext API**：18 个命名空间——terminal、ui、commands、settings、lifecycle、events、storage、system
- **24 个 UI Kit 组件**：预构建的 React 组件（按钮、输入框、对话框、表格……）通过 `window.__OXIDE__` 注入插件沙箱
- **安全膜**：对所有上下文对象使用 `Object.freeze`，基于 Proxy 的 ACL，IPC 白名单，熔断器在重复错误后自动禁用
- **共享模块**：React、ReactDOM、zustand、lucide-react 对外暴露供插件使用，无需重复打包

### ⚡ 自适应渲染

三级渲染调度器，替代固定的 `requestAnimationFrame` 批处理：

| 级别 | 触发条件 | 帧率 | 收益 |
|---|---|---|---|
| **加速** | 帧数据 ≥ 4 KB | 120 Hz+（ProMotion 原生） | 消除 `cat largefile.log` 时的滚动卡顿 |
| **正常** | 常规打字 | 60 Hz（RAF） | 平稳的基准表现 |
| **空闲** | 3 秒无 I/O / 标签页隐藏 | 1–15 Hz（指数退避） | 接近零 GPU 负载，节省电量 |

级别切换完全自动——由数据量、用户输入和 Page Visibility API 驱动。后台标签页通过空闲定时器持续刷新数据，无需唤醒 RAF。

### 🔐 .oxide 加密导出

便携、防篡改的连接备份：

- **ChaCha20-Poly1305 AEAD** 认证加密
- **Argon2id KDF**：256 MB 内存开销、4 次迭代——抵御 GPU 暴力破解
- **SHA-256** 完整性校验
- **可选密钥嵌入**：私钥 base64 编码嵌入加密载荷
- **导出前分析**：认证类型分类、缺失密钥检测

### 📡 ProxyJump——拓扑感知多跳

- 无限链深度：`Client → Jump A → Jump B → … → Target`
- 自动解析 `~/.ssh/config`，构建拓扑图，Dijkstra 最短路径寻路
- 跳板节点可作为独立会话复用
- 级联故障传播：跳板机宕机 → 所有下游节点自动标记为 `link_down`

### ⚙️ 本地终端——线程安全 PTY

跨平台本地 Shell，基于 `portable-pty 0.8`，通过 `local-terminal` feature flag 控制：

- `MasterPty` 封装在 `std::sync::Mutex` 中——专用 I/O 线程将阻塞式 PTY 读取隔离在 Tokio 事件循环之外
- Shell 自动检测：`zsh`、`bash`、`fish`、`pwsh`、Git Bash、WSL2
- `cargo build --no-default-features` 可剥离 PTY 功能用于移动端/轻量构建

### 🪟 Windows 优化

- **原生 ConPTY**：直接调用 Windows Pseudo Console API——完整 TrueColor 和 ANSI 支持，无传统 WinPTY
- **Shell 扫描器**：通过注册表和 PATH 自动检测 PowerShell 7、Git Bash、WSL2、CMD

### 更多功能

- **IDE 模式**：CodeMirror 6 基于 SFTP，24 种语言，带 Git 状态的文件树，多标签，冲突解决——Linux 可选远程 Agent（~1 MB）以增强功能
- **资源分析器**：通过持久 SSH 通道读取 `/proc/stat` 获取实时 CPU/内存/网络数据，基于增量计算，非 Linux 环境自动降级为仅 RTT
- **自定义主题引擎**：30+ 内置主题，可视化编辑器实时预览，20 个 xterm.js 字段 + 24 个 UI 颜色变量，从终端调色板自动推导 UI 颜色
- **会话录制**：asciicast v2 格式，完整录制和回放
- **广播输入**：输入一次，发送到所有分屏窗格——批量服务器操作
- **背景画廊**：每标签页背景图片，16 种标签类型，透明度/模糊/适配控制
- **CLI 伴侣工具**（`oxt`）：~1 MB 二进制文件，JSON-RPC 2.0 基于 Unix Socket / Named Pipe，status/health/list/forward/config/connect/focus/attach/SFTP/import/AI 支持人类可读或 `--json` 输出
- **WSL Graphics** ⚠️ 实验性：内置 VNC 查看器——9 种桌面环境 + 单应用模式，WSLg 检测，Xtigervnc + noVNC

#### 官方插件

| 插件 | 说明 | 仓库 |
|---|---|---|
| **Cloud Sync** | 加密自托管同步——通过 WebDAV、HTTP JSON、Dropbox、Git 或 S3 上传和导入 `.oxide` 快照 | [oxideterm.cloud-sync](https://github.com/AnalyseDeCircuit/oxideterm.cloud-sync) |
| **Telnet Client** | 原生 Telnet 客户端，用于路由器、交换机和老旧设备——无需外部程序 | [oxideterm.telnet](https://github.com/AnalyseDeCircuit/oxideterm.telnet) |

<details>
<summary>📸 11 种语言实际展示</summary>
<br>
<table>
  <tr>
    <td align="center"><img src="../../docs/screenshots/overview/en.png" width="280"><br><b>English</b></td>
    <td align="center"><img src="../../docs/screenshots/overview/zhHans.png" width="280"><br><b>简体中文</b></td>
    <td align="center"><img src="../../docs/screenshots/overview/zhHant.png" width="280"><br><b>繁體中文</b></td>
  </tr>
  <tr>
    <td align="center"><img src="../../docs/screenshots/overview/ja.png" width="280"><br><b>日本語</b></td>
    <td align="center"><img src="../../docs/screenshots/overview/ko.png" width="280"><br><b>한국어</b></td>
    <td align="center"><img src="../../docs/screenshots/overview/fr.png" width="280"><br><b>Français</b></td>
  </tr>
  <tr>
    <td align="center"><img src="../../docs/screenshots/overview/de.png" width="280"><br><b>Deutsch</b></td>
    <td align="center"><img src="../../docs/screenshots/overview/es.png" width="280"><br><b>Español</b></td>
    <td align="center"><img src="../../docs/screenshots/overview/it.png" width="280"><br><b>Italiano</b></td>
  </tr>
  <tr>
    <td align="center"><img src="../../docs/screenshots/overview/pt-BR.png" width="280"><br><b>Português</b></td>
    <td align="center"><img src="../../docs/screenshots/overview/vi.png" width="280"><br><b>Tiếng Việt</b></td>
    <td></td>
  </tr>
</table>
</details>

---

## 运行时要求

OxideTerm 使用操作系统提供的原生 WebView 运行时。大多数用户的系统已经预装；只有在应用无法启动或处于离线/内网环境时，才需要手动安装。

| 平台 | 运行时依赖 |
|---|---|
| **Windows** | [WebView2 运行时](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) — 已预装于 Windows 10（1803+）和 Windows 11。对于**离线 / 内网**环境，请使用 [Evergreen 独立安装程序](https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download)（离线安装，约 170 MB），或通过组策略部署**固定版本**运行时。 |
| **macOS** | 无（使用原生 WebKit） |
| **Linux** | `libwebkit2gtk-4.1`（现代桌面环境通常已预装） |

---

## 便携模式

OxideTerm 支持完全自包含的便携模式——所有数据（连接、密钥、设置）存储在应用程序二进制文件旁边，适用于 USB 驱动器或离线环境。

### 激活方式

**方式 A — 标记文件**（最简单）：在应用程序旁创建一个名为 `portable` 的空文件（无扩展名）。

| 平台 | `portable` 文件放置位置 |
|---|---|
| **macOS** | `OxideTerm.app` 旁边（同级目录） |
| **Windows** | `OxideTerm.exe` 旁边 |
| **Linux (AppImage)** | `.AppImage` 文件旁边 |

```
/my-usb/
├── OxideTerm.app   (or .exe / .AppImage)
├── portable        ← 你创建的空文件
└── data/           ← 首次启动时自动创建
```

**方式 B — `portable.json`**（自定义数据目录）：在相同位置放置一个 `portable.json`：

```json
{
  "enabled": true,
  "dataDir": "my-data"
}
```

- `enabled` 省略时默认为 `true`
- `dataDir` 必须是**相对路径**（不能包含 `..`）；省略时默认为 `data`

### 工作原理

1. **首次启动** — 引导界面会提示你创建便携密码。此密码用于加密本地密钥库（ChaCha20-Poly1305 + Argon2id），保护所有已保存的密钥。
2. **后续启动** — 输入密码解锁。在支持 Touch ID 的 macOS 上，你可以在 **Settings → General → Portable Runtime** 中启用生物识别解锁。
3. **实例锁** — 同一时间只有一个 OxideTerm 实例可以使用便携数据目录（`data/.portable.lock`）。
4. **管理** — 在 **Settings → General → Portable Runtime** 中更改便携密码或切换生物识别解锁。
5. **可移植性** — 将整个文件夹（应用 + `portable` 标记 + `data/`）复制到另一台机器即可使用。密码随密钥库一起携带。

> [!TIP]
> 便携模式下自动更新已禁用。如需更新，替换应用程序二进制文件，保留 `data/` 目录即可。

---

## 快速开始

### 前置要求

- **Rust** 1.85+
- **Node.js** 18+（推荐 pnpm）
- **平台工具**：
  - macOS：Xcode Command Line Tools
  - Windows：Visual Studio C++ Build Tools
  - Linux：`build-essential`、`libwebkit2gtk-4.1-dev`、`libssl-dev`

### 开发

```bash
git clone https://github.com/AnalyseDeCircuit/oxideterm.git
cd oxideterm && pnpm install

# 构建 CLI 伴侣工具（CLI 功能必需）
pnpm cli:build

# 完整应用（前端 + Rust 后端，热重载）
pnpm run tauri dev

# 仅前端（Vite 运行在端口 1420）
pnpm dev

# 生产构建
pnpm run tauri build
```

---

## 技术栈

| 层级 | 技术 | 详情 |
|---|---|---|
| **框架** | Tauri 2.0 | 原生二进制，25–40 MB |
| **运行时** | Tokio + DashMap 6 | 全异步，无锁并发映射 |
| **SSH** | russh 0.59（`ring`） | 纯 Rust，零 C 依赖，SSH Agent |
| **本地 PTY** | portable-pty 0.8 | Feature 门控，Windows 上使用 ConPTY |
| **前端** | React 19.1 + TypeScript 5.8 | Vite 7，Tailwind CSS 4 |
| **状态** | Zustand 5 | 19 个专用 Store |
| **终端** | xterm.js 6 + WebGL | GPU 加速，60fps+ |
| **编辑器** | CodeMirror 6 | 30+ 语言模式 |
| **加密** | ChaCha20-Poly1305 + Argon2id | AEAD + 内存硬化 KDF（256 MB） |
| **存储** | redb 2.1 | 嵌入式 KV 存储 |
| **国际化** | i18next 25 | 11 种语言 × 22 个命名空间 |
| **插件** | ESM 运行时 | 冻结 PluginContext + 24 UI Kit |
| **CLI** | JSON-RPC 2.0 | Unix Socket / Named Pipe |

---

## 项目规模

使用 `tokei` 统计，已排除依赖和构建产物。

| 指标 | 当前规模 |
|---|---:|
| 总代码量 | 286K+ |
| TypeScript / TSX | 130K+ |
| Rust | 100K+ |
| 前端测试代码 | 24K+ |
| 前端测试文件 | 128 |
| 源文件（`src` + `src-tauri/src`） | 664 |

---

## 安全

| 关注点 | 实现方式 |
|---|---|
| **密码** | OS 密钥链（macOS Keychain / Windows Credential Manager / libsecret） |
| **便携式密钥库** | ChaCha20-Poly1305 加密保险库，位于应用程序旁边，可选通过 OS 密钥链绑定生物识别 |
| **AI API 密钥** | OS 密钥链 + macOS 上的 Touch ID 生物识别保护 |
| **导出** | .oxide：ChaCha20-Poly1305 + Argon2id（256 MB 内存，4 次迭代） |
| **内存** | Rust 内存安全 + `zeroize` 敏感数据清除 |
| **主机密钥** | TOFU 验证 `~/.ssh/known_hosts`，拒绝变更（防中间人攻击） |
| **插件** | Object.freeze + Proxy ACL，熔断器，IPC 白名单 |
| **WebSocket** | 一次性令牌，带时间限制 |

---

## 路线图

- [x] SSH Agent 转发
- [ ] 完整 ProxyCommand 支持
- [ ] 审计功能
- [ ] Agent 增强
- [ ] 会话搜索与快速切换
- [x] 通过 GPUI（Zed 的 GPU 加速框架）进行 Rust 原生迁移 — [进行中]

---

## 支持与维护

OxideTerm 由独立开发者以**尽力而为**的方式维护。Bug 报告和可复现的回归问题会优先处理；功能请求欢迎提出，但不一定都会实现。

如果 OxideTerm 帮到了你的工作流，GitHub Star、问题复现、翻译修正、插件或 Pull Request 都能让项目更容易继续前进。

---

## 许可证

**GPL-3.0** — 本软件是按照 [GNU 通用公共许可证 v3.0](https://www.gnu.org/licenses/gpl-3.0.html) 发布的自由软件。

您可以在 GPL-3.0 条款下自由地使用、修改和分发本软件。任何衍生作品也必须在由同一许可证下发布。

OxideTerm 从 v1.0.0 起由 **PolyForm Noncommercial 1.0.0** 切换到 **GPL-3.0**。我们主动做这个转换，就是为了不玩带非商用陷阱或竞业禁止附加条款的“开源 cosplay”，而是把用户、fork、再分发者和商业使用者的 copyleft 自由说清楚。

公开代码不自动等于开源。如果一个项目一边挂着常见开源许可证，一边额外写上“禁止再分发”“禁止重新打包”“禁止做竞争产品”“禁止未经授权的平台分发”这类附加条款，那它更接近 source-available 的营销话术，而不是用户通常理解的开源自由。OxideTerm 不添加竞业禁止或反分发附加条款：GPL-3.0 条款就是全部条款。

完整文本：[GNU 通用公共许可证 v3.0](https://www.gnu.org/licenses/gpl-3.0.html)

---

## 致谢

[russh](https://github.com/warp-tech/russh) · [portable-pty](https://github.com/wez/wezterm/tree/main/pty) · [Tauri](https://tauri.app/) · [xterm.js](https://xtermjs.org/) · [CodeMirror](https://codemirror.net/) · [Radix UI](https://www.radix-ui.com/)

---

<p align="center">
  <sub>286,000+ 行代码——以 ⚡ 和 ☕ 构建</sub>
</p>

## Star History

<a href="https://www.star-history.com/?repos=AnalyseDeCircuit%2Foxideterm&type=date&legend=top-left">
 <picture>
   <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=AnalyseDeCircuit/oxideterm&type=date&theme=dark&legend=top-left" />
   <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=AnalyseDeCircuit/oxideterm&type=date&legend=top-left" />
   <img alt="Star History Chart" src="https://api.star-history.com/chart?repos=AnalyseDeCircuit/oxideterm&type=date&legend=top-left" />
 </picture>
</a>
