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.
  • 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.js script 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.
Loading diagram...

The Terminal Pipeline

How does a keystroke become a pixel?

  1. Input: You press A on your keyboard.
  2. Renderer: React captures onKeyDown. It sends an IPC message term.write('A') to the Main Process.
  3. Main: Writes A to the PTY file descriptor (stdin of the SSH binary).
  4. SSH Binary: Sends the packet to the remote server.
  5. Remote Server: Echoes A back (stdout).
  6. Main: Captures the data from the PTY stdout. Sends IPC message term.data('A') to Renderer.
  7. Renderer (xterm.js): Parses the ANSI sequence.
  8. 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

  1. git clone https://github.com/binaricat/Netcatty
  2. npm install
  3. npm run dev in one terminal (starts Renderer).
  4. npm run electron in another (starts Main).