Project Architecture
Under the hood of Netcatty's engineering
Netcatty is not just a "wrapper around SSH". It is a complex engineering effort that bridges the gap between low-level system calls (via Node.js C++ addons) and high-performance rendering (via WebGL).
This document explains how Netcatty works. It is intended for developers, security auditors, and curious power users.
The Electron Process Model
Netcatty leverages the Electron Multi-Process Architecture to ensure stability and security.
1. The Main Process (Node.js)
- Role: The Orchestrator.
- Responsibilities:
- Spawning native PTY (Pseudo-Terminal) processes (
node-pty). - Managing System Menus and Windows.
- Handling Global Shortcuts (
Cmd+K, etc.). - Interfacing with the OS-level Keytar for secure password storage.
- Spawning native PTY (Pseudo-Terminal) processes (
- Privileges: Has full access to the Node.js API.
2. The Renderer Process (React, Chrome)
- Role: The UI.
- Responsibilities:
- Rendering the React Component Tree.
- Managing Application State (Zustand).
- Drawing the xterm.js WebGL canvas.
- Privileges: Sandboxed. The renderer cannot directly access the disk or spawn processes. It must request these actions via IPC (Inter-Process Communication).
3. Context Isolation (Security)
We enforce contextIsolation: true. This means the Renderer code cannot access Electron internals or Node.js primitives.
- The Bridge: A
preload.jsscript exposes a strict, typed API (window.electron) to the Renderer. - Why? If a malicious server tried to exploit an XSS vulnerability in the terminal output (e.g., printing a weird escape sequence that triggers HTML rendering), they would find themselves trapped in a sandbox with no access to your file system.
The Terminal Pipeline
How does a keystroke become a pixel?
- Input: You press
Aon your keyboard. - Renderer: React captures
onKeyDown. It sends an IPC messageterm.write('A')to the Main Process. - Main: Writes
Ato the PTY file descriptor (stdin of the SSH binary). - SSH Binary: Sends the packet to the remote server.
- Remote Server: Echoes
Aback (stdout). - Main: Captures the data from the PTY stdout. Sends IPC message
term.data('A')to Renderer. - Renderer (xterm.js): Parses the ANSI sequence.
- Engine (WebGL/Canvas): Draws the glyph using the most efficient engine for the current platform (WebGL for raw speed, Canvas for crisp text on macOS).
This round-trip usually happens in less than 16ms (60fps), giving the illusion of instant typing.
Data Persistence Strategy
Netcatty operates on a Local-First philosophy.
Local Data (Vault)
- Storage: We use standard browser-based
localStorage(backed by Electron's native persistent storage) for the local machine's Vault. - Security: For local machine security, we recommend using OS-level full-disk encryption (FileVault / BitLocker). Advanced app-level encryption (Zero-Knowledge) is engaged during Cloud Sync.
- Validation: We use Zod schemas at runtime to ensure that corrupted data doesn't crash the app. It will degrade gracefully or prompt for recovery.
State Management (Zustand)
We eschew Redux for Zustand. Use cases:
- Session State: Which tabs are open? Which pane is focused? (Ephemeral, RAM-only).
- Settings State: Theme preferences, font size. (Persisted to separate
config.json).
Performance Optimizations
Virtualization
When you have 5,000 hosts in the Vault, rendering 5,000 DOM nodes would freeze the UI.
- Solution: We use
react-window(Virtual Scrolling). We only render the ~20 items currently visible on screen. - Search: We use a customized Fuzzy Search implementation that indexes the object tree in a Web Worker to avoid blocking the main thread during typing.
Keep-Alives
SSH connections are kept alive in the Main Process even if the Renderer reloads (e.g., during development or a crash). This is done via "Detached Sessions".
- Rehydration: When the UI reloads, it queries the Main Process: "Do you have any active sessions?". The Main process replies with the existing PTY handles and replay buffers.
Contribution Guide
Netcatty is Open Source (MIT). We welcome contributions.
Tech Stack
- Language: TypeScript (Strict Mode).
- Runtime: Node.js 20+.
- Bundler: Vite (for super-fast HMR).
- UI Framework: React 18, Tailwind CSS, shadcn/ui.
Getting Started
git clone https://github.com/binaricat/Netcattynpm installnpm run devin one terminal (starts Renderer).npm run electronin another (starts Main).