# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## 语言偏好 **请使用中文与用户交互。** 所有交流使用中文,代码注释和文档可使用中文或英文。 --- ## 项目概述 **OpsXShell** - 跨平台 SSH/SFTP 终端工具 · 简洁高效 · 安全可靠 · 操作便捷人性化 · 基于 Electron + React + TypeScript 构建。支持终端仿真、SFTP、端口转发、会话管理。 ### 技术栈 - **UI 框架**: Electron 28 + React 18 + TypeScript 5 - **构建工具**: Vite 5 - **状态管理**: Zustand - **终端仿真**: XTerm.js + WebGL - **SSH/SFTP**: ssh2 - **数据库**: better-sqlite3 - **样式**: Tailwind CSS - **测试**: Vitest - **支持平台**: macOS, Windows, Linux --- ## 常用命令 ### 安装和运行 ```bash npm install # 安装依赖 npm run dev # 启动开发服务器 + Electron ``` ### 构建和打包 ```bash npm run build # 构建生产版本(前端 + Electron) npm run dist # 打包分发(当前平台) npm run dist:mac # 打包 macOS npm run dist:win # 打包 Windows npm run dist:linux # 打包 Linux ``` ### 代码检查 ```bash npm run lint # 运行 ESLint ``` ### 测试 ```bash npm test # 运行所有测试 npm run test:watch # 监听模式 npm run test:coverage #覆盖率报告 ``` --- ## 项目架构 ### 进程模型 Electron 双进程架构: - **主进程** (`electron/`): 窗口管理、IPC 处理器、本地操作 - **渲染进程** (`src/`): React UI、状态管理、XTerm.js 终端 ### 目录结构 ``` electron/ ├── main.ts # 主进程入口 ├── preload.ts # 上下文桥接 (window.electronAPI) ├── services/ │ ├── ssh-service.ts # SSH/SFTP 操作 (ssh2) │ └── database-service.ts # SQLite 操作 └── ipc/ # IPC 处理器分层 ├── ssh.ipc.ts # SSH 连接/Shell/端口转发 ├── sftp.ipc.ts # SFTP 操作/传输 ├── session.ipc.ts # 会话 CRUD ├── settings.ipc.ts # 设置读写 ├── dialog.ipc.ts # 文件对话框 ├── file.ipc.ts # 本地文件操作 ├── zmodem.ipc.ts # rz/sz 传输 └── app.ipc.ts # 应用信息 src/ ├── components/ # React 组件 │ ├── TerminalView.tsx # 终端仿真 (XTerm.js + WebGL) │ ├── SFTPView.tsx # SFTP 双面板文件管理 │ ├── sftp/ # SFTP 子组件 │ │ ├── Breadcrumb.tsx │ │ ├── SortHeader.tsx │ │ ├── FileRow.tsx │ │ ├── ContextMenu.tsx │ │ ├── TransferItem.tsx │ │ └── ConnectionSelector.tsx │ └── ... ├── stores/ # Zustand 状态管理 │ ├── tabStore.ts # 标签页管理 │ ├── connectionStore.ts # 连接状态 │ └── connection/ # 连接池分层 │ ├── poolStore.ts # 连接池核心 (创建/获取/释放) │ ├── lifecycleStore.ts # 状态机/超时 │ └── storeHooks.ts # 组合接口 └── themes/ # 终端主题 shared/ └── types/ # 跨进程共享类型 ├── session.types.ts # Session, AuthType ├── connection.types.ts # PooledConnection, ConnectionState ├── sftp.types.ts # FileItem, TransferTask └── ipc.types.ts # IPC 通道常量 test/ # Vitest 测试 ├── setup.ts # 测试环境配置 (Electron API mock) ├── stores/ # Store 单元测试 └── components/ # 组件工具函数测试 ``` ### IPC 通信 渲染进程通过 `window.electronAPI` 与主进程通信。所有 IPC 处理器已分层到 `electron/ipc/` 目录。 **主要通道**: - `ssh:connect`, `ssh:disconnect`, `ssh:createShell`, `ssh:shellWrite`, `ssh:shellResize` - `sftp:connect`, `sftp:listDirectory`, `sftp:upload`, `sftp:download`, `sftp:mkdir` - `session:create`, `session:update`, `session:delete` - `local:readDir`, `local:mkdir`, `local:delete`, `local:rename` 事件推送: Shell 输出通过 `ssh:shellData`;SFTP 进度通过 `sftp:progress`。 ### 数据库架构 SQLite(`~/.opsxshell/`): - **sessions**: SSH 会话配置 - **connection_history**: 连接历史 - **settings**: 应用设置 - **keys**: SSH 密钥 - **port_forwards**: 端口转发规则 ### 连接池架构 连接池已拆分为两个 Store: 1. **poolStore** - 连接 Map、LRU 淘汰、引用计数、创建/断开 2. **lifecycleStore** - 状态机(disconnected/connecting/connected/background/suspended)、超时管理 --- ## 设计模式参考 ### IPC 通信 ```typescript // electron/ipc/ssh.ipc.ts ipcMain.handle('ssh:connect', async (_event, config) => { try { const result = await sshService.connect(config) return { success: true, connectionId: result.id } } catch (error: any) { return { success: false, error: error.message } } }) ``` ### 事件推送 ```typescript // 主进程发送 mainWindow?.webContents.send('ssh:shellData', shellId, data) // 渲染进程监听 window.electronAPI.onShellData((_event, shellId, data) => { terminal.write(data) }) ``` ### Zustand Store ```typescript // 使用组合模式 export const useConnectionStore = () => { const pool = usePoolStore() const lifecycle = useLifecycleStore() return { ...pool, ...lifecycle } } ``` --- ## 开发注意事项 ### ✅ 推荐做法 1. 使用 contextBridge 暴露 API,保持 `contextIsolation: true` 2. IPC 返回 `{ success: false, error: error.message }` 格式 3. 在 `app.on('before-quit')` 清理资源 4. 组件卸载时清理事件监听 (`removeAllListeners`) 5. 添加新 IPC 处理器时:在 `electron/ipc/` 创建/修改对应文件 + 在 `electron/preload.ts` 暴露 + 在 `src/electron.d.ts` 添加类型 ### ❌ 避免做法 1. 渲染进程直接使用 `require('ssh2')` - 必须通过 IPC 2. 暴露 `nodeIntegration: true` 3. SSH 连接未关闭导致资源泄漏 4. 硬编码数据库路径 5. 忽略 Shell 窗口大小变化 --- ## 添加新功能指南 ### 添加 IPC 处理器 1. 在 `electron/ipc/` 对应模块添加 handler 2. 在 `electron/preload.ts` 添加暴露方法 3. 在 `src/electron.d.ts` 添加类型声明 ### 添加 UI 组件 1. 在 `src/components/` 创建组件 2. 如需状态管理,在 `src/stores/` 添加/扩展 Store 3. 在 `TabContent.tsx` 添加渲染逻辑 ### 添加测试 1. 在 `test/stores/` 或 `test/components/` 创建 `.test.ts` 文件 2. 使用 `test/setup.ts` 中的 mock 配置 3. 运行 `npm test` 验证 --- ## 参考资源 - [Electron](https://www.electronjs.org/docs) - [React](https://react.dev) - [XTerm.js](https://xtermjs.org) - [ssh2](https://github.com/mscdex/ssh2) - [Zustand](https://zustand.docs.pmnd.rs) - [Vitest](https://vitest.dev)