# eDEX-UI Administrator & Developer Guide

This guide is the complete technical reference for eDEX-UI: its architecture, the terminal client/server design, the system-monitoring pipeline, security model, configuration surface, build and distribution process, and per-module internals. It is written for administrators deploying eDEX-UI (including kiosk/touchscreen scenarios), developers building from source or authoring themes and keyboard layouts, and architects who want to understand how the project works end to end.

It is the companion to the **User Guide**, which covers day-to-day usage. Everything here is derived directly from the eDEX-UI source at commit `04a00c4` (version 2.2.8).

---

## 1. Executive Summary

eDEX-UI is an [Electron](https://www.electronjs.org/) desktop application that presents a fullscreen, TRON-inspired "computer console" UI wrapping a real terminal emulator and a suite of live system monitors. It is cross-platform (Windows, macOS, Linux), single-window, single-instance, and fullscreen by default.

| Attribute | Value |
|-----------|-------|
| Version documented | 2.2.8 |
| License | GPL-3.0 |
| Author | Gabriel "Squared" SAILLARD |
| App ID | `com.edex.ui` |
| Project status | **Archived** (October 18, 2021); no longer maintained |
| Runtime | Electron `^12.1.0` (Chromium renderer + Node.js main) |
| Terminal | xterm.js `4.14.1` (renderer) ↔ node-pty `0.10.1` (main) over a local WebSocket |
| System data | `systeminformation` `5.9.7`, run across a worker cluster |
| Languages | JavaScript (ES6 classes), HTML, CSS |
| Source size | ~134 files, ~264 KB of source across `src/` |

### Architectural shape

eDEX-UI is a two-process Electron app with an unusual internal twist: the terminal is wired together with a **localhost WebSocket** between the renderer (xterm.js front-end) and the main process (node-pty back-end), rather than going purely through Electron IPC. The main process additionally spins up a **cluster of Node worker processes** to offload `systeminformation` polling so the UI stays smooth.

```text
        ┌──────────────────────── Electron main process (Node.js) ───────────────────────┐
        │  src/_boot.js                                                                   │
        │   • single-instance lock, settings/shortcuts/theme bootstrapping               │
        │   • creates the BrowserWindow (loads src/ui.html)                               │
        │   • Terminal (role:"server") → node-pty + ws WebSocket server (:3000, :3002-5)  │
        │   • src/_multithread.js → cluster of N workers running systeminformation        │
        │   • IPC handlers: ttyspawn, theme/kb override, systeminformation-call, log      │
        └───────────────▲───────────────────────────────▲───────────────────────────────┘
                        │ Electron IPC                   │ WebSocket  ws://127.0.0.1:<port>
                        │ (resize, cwd, process, si)     │ (keystrokes ↔ pty output)
        ┌───────────────┴───────────────────────────────┴───────────────────────────────┐
        │  Electron renderer process (Chromium) — src/ui.html + src/_renderer.js         │
        │   • boot animation → initUI() builds the layout                                 │
        │   • 18 module classes in src/classes/ (Terminal client, Keyboard, FS, monitors) │
        │   • window.si Proxy → IPC → main-process worker cluster                         │
        └────────────────────────────────────────────────────────────────────────────────┘
```

> [!NOTE]
> Because the project is archived, this guide also calls out which subsystems are known to be fragile (GeoIP lookup, proxy handling, Windows CWD tracking) so operators know what to expect rather than discovering it in production.

---

## 2. System Architecture

### 2.1 Process model

| Process | Source | Responsibilities |
|---------|--------|------------------|
| **Main** | `src/_boot.js` | App lifecycle, window creation, terminal back-end(s), config bootstrapping, IPC routing |
| **Renderer** | `src/ui.html` + `src/_renderer.js` | UI construction, all 18 visual modules, terminal front-end, input handling |
| **Multithread controller + workers** | `src/_multithread.js` | A Node `cluster` master plus N workers that execute `systeminformation` calls |

### 2.2 Startup sequence

The boot flow in `src/_boot.js` (`app.on('ready', …)`) proceeds:

1. **Single-instance lock** via `app.requestSingleInstanceLock()`. A second launch logs *"Another instance of eDEX is already running"* and exits.
2. **GPU tuning** — appends Chromium switches `ignore-gpu-blocklist`, `enable-gpu-rasterization`, `enable-video-decode` to trade some stability for rendering performance (notably on Linux).
3. **Proxy env scrubbing** — `http_proxy` / `https_proxy` are deleted from the environment to avoid breaking the internal WebSocket connections ([issue #222](https://github.com/GitSquared/edex-ui/issues/222)).
4. **Config bootstrapping** — creates the user-data directory and writes default `settings.json`, `shortcuts.json`, and `lastWindowState.json` if absent; mirrors the built-in `themes/`, `keyboards/`, and `fonts/` into the user-data directory (overwriting each launch).
5. **Version history** — appends the current version + timestamp to `versions_log.json`.
6. **Shell resolution** — resolves the configured `shell` to an absolute path with `which`. Failure here stalls startup at *"Settings loaded!"*.
7. **Environment assembly** — loads a clean login shell environment via `shell-env`, then overlays `TERM=xterm-256color`, `COLORTERM=truecolor`, `TERM_PROGRAM=eDEX-UI`, `TERM_PROGRAM_VERSION`, plus any user `env`.
8. **Terminal back-end** — instantiates `Terminal({role:"server", …})` on `settings.port` (default `3000`).
9. **Multithread controller** — `require("./_multithread.js")` forks the worker cluster.
10. **Window creation** — `createWindow(settings)` builds the `BrowserWindow` and loads `ui.html`.
11. **Extra-tab back-ends** — reserves four extra TTY slots on ports `basePort+2 … basePort+5` for additional tabs.

### 2.3 The terminal: a WebSocket-bridged client/server

The single most important design element lives in `src/classes/terminal.class.js`, which is **one class with two roles**:

#### Server role (main process)

```text
node-pty spawn(shell, args, {cols, rows, cwd, env})
        │
        ├── ws WebSocket server on settings.port (verifyClient: max 1 client)
        │      ws "message"  → tty.write(msg)        (keystrokes in)
        │      tty.onData     → ws.send(data)         (pty output out)
        │
        └── 1-second tick:  CWD tracking + foreground-process tracking
               Linux : readlink /proc/<pid>/cwd ;  ps -o comm ... -g <pid>
               macOS : lsof -a -d cwd -p <pid>  ;  ps -o comm ... -g <pid>
               Windows: unsupported → "Fallback cwd" (detached mode)
```

- `node-pty` spawns the actual shell. Non-Windows shells get `--login` by default when no `shellArgs` are set.
- A `ws` WebSocket server is created on the port. `verifyClient` **rejects a second connection**, so each pty has exactly one front-end.
- Keystrokes arrive as WebSocket messages and are written to the pty; pty output is sent back over the socket.
- Every second the server updates the **current working directory** and the **foreground process name** and pushes them to the renderer over the Electron IPC channel `terminal_channel-<port>`.

#### Client role (renderer)

- Builds an `xterm.js` `Terminal` with the `FitAddon`, `WebglAddon`, `LigaturesAddon`, and `AttachAddon`.
- Opens `new WebSocket("ws://127.0.0.1:<port>")`; the `AttachAddon` binds the socket to xterm so output renders and input is sent.
- Resize is negotiated over IPC (`terminal_channel-<port>` → `"Resize"`), recomputed by `FitAddon.proposeDimensions()` with aspect-ratio correction heuristics.
- Receives `"New cwd"`, `"Fallback cwd"`, and `"New process"` IPC messages — the CWD drives the filesystem panel; the process name drives the tab label.

> [!IMPORTANT]
> The WebSocket server binds to the loopback interface and accepts only **one** client per port, but it performs **no authentication**. Any local process able to reach `127.0.0.1:<port>` before the renderer connects could occupy the socket. On a single-user desktop this is low-risk; on shared/multi-user hosts treat the terminal ports as a local trust boundary. See [Security](#5-security-model).

### 2.4 Multi-tab terminals

`initUI()` creates the main terminal on `settings.port`. Up to **four additional tabs** are supported (five total). When a user opens an empty tab, the renderer sends an `ttyspawn` IPC; the main process allocates the next free port from the reserved pool (`basePort+2 … basePort+5`), spawns a new `Terminal` server **in the active tab's current working directory**, and replies with `ttyspawn-reply: SUCCESS: <port>`. If the pool is exhausted it replies `ERROR: max number of ttys reached`.

### 2.5 The systeminformation pipeline (`window.si`)

System data is the heaviest workload, so it is offloaded from the renderer:

```text
renderer:  window.si.cpu()        (a Proxy)
   │  ipc.send("systeminformation-call", "cpu", id, ...args)
   ▼
main (_multithread.js master):
   • dispatch round-robin to a worker  (or call inline if args.length>1)
   ▼
worker:  si["cpu"](...).then(res => process.send({id, res}))
   ▲
   │  ipc "systeminformation-reply-<id>"
renderer: Promise resolves with res
```

- `window.si` in the renderer is a JavaScript `Proxy`. Any property access (`window.si.cpu`, `window.si.mem`, …) returns a function that round-trips through IPC and resolves a Promise.
- The master (`_multithread.js`) forks `min(os.cpus().length - 1, 7)` workers (leaving a core for the renderer; capped at 7 per [issue #904](https://github.com/GitSquared/edex-ui/issues/904)).
- Calls are dispatched round-robin to workers; multi-argument calls are executed inline by the master.
- An illegal method name (`si[type]` undefined) is rejected with a warning, preventing arbitrary function invocation through the channel.

### 2.6 Rendering and UI construction

`src/_renderer.js` orchestrates the front-end:

1. Disables `eval()` globally (`window.eval` / `global.eval` throw) as a hardening measure.
2. Defines HTML/CSS sanitization helpers (`_escapeHtml`, `_purifyCSS`, `_encodePathURI`).
3. Loads `settings.json`, `shortcuts.json`, `lastWindowState.json` and applies CLI overrides (`--nointro`, `--nocursor`).
4. Loads the theme (`_loadTheme`) — injects CSS variables, fonts, and any theme-defined `injectCSS` (purified).
5. Runs the boot animation (unless `nointro`) reading `assets/misc/boot_log.txt`.
6. `initUI()` builds the DOM scaffold and instantiates every module in order (see [Module Reference](#7-module-reference)).
7. Registers global keyboard shortcuts via `electron.remote.globalShortcut`, re-registering on window focus and clearing on blur.

---

## 3. Repository Structure

```text
edex-ui/
├── package.json              Root: build config (electron-builder), dev deps, scripts
├── src/
│   ├── _boot.js              Main process entry (package.json "main")
│   ├── _renderer.js          Renderer orchestration
│   ├── _multithread.js       systeminformation worker cluster
│   ├── ui.html               Renderer HTML shell
│   ├── package.json          Runtime deps (xterm, node-pty, ws, systeminformation, …)
│   ├── classes/              18 ES6 module classes (see §7)
│   └── assets/
│       ├── css/              Per-module stylesheets (mod_*.css, main.css, boot_screen.css)
│       ├── themes/           20 built-in theme JSON files
│       ├── kb_layouts/       19 keyboard layout JSON files
│       ├── fonts/            Fira Code/Mono, United Sans (woff2)
│       ├── audio/            13 sound-effect WAV files
│       ├── icons/            file-icons.json (generated SVG icon set)
│       ├── misc/             boot_log.txt, file-icons-match.js, grid.json
│       └── vendor/           encom-globe.js (3-D globe library)
├── file-icons/               Git submodules: icon source sets (atom, devopicons, etc.)
├── file-icons-generator.js   Regenerates file-icons.json + matcher from submodules
├── prebuild-minify.js        CI minification of src before packaging
├── media/                    App icons + screenshots
├── SECURITY.md
└── LICENSE                   GPL-3.0
```

### Key file roles

| File | Role |
|------|------|
| `src/_boot.js` | Main process: lifecycle, window, terminal server, config defaults |
| `src/_renderer.js` | Renderer: UI build, settings/shortcuts editors, theme loader, shortcut registration |
| `src/_multithread.js` | `cluster` master + workers for `systeminformation` |
| `src/classes/terminal.class.js` | Dual-role terminal (xterm client / node-pty+ws server) |
| `file-icons-generator.js` | Build helper: compiles SVG icon submodules into `file-icons.json` and a `matchIcon()` function |
| `prebuild-minify.js` | Pre-package minification step |

---

## 4. Requirements

### 4.1 Runtime (release binaries)

| Requirement | Detail |
|-------------|--------|
| OS | Windows (x64/ia32), macOS (x64), Linux (x64/arm64) |
| Node.js | **Not required** for release builds — Electron is bundled |
| GPU | Hardware acceleration recommended; GPU blocklist is bypassed for performance |
| Network | Optional, but required for the network-status, globe, and update-check features |
| Permissions | Read access to `/proc` (Linux) and `lsof`/`ps` availability (macOS) for CWD/process tracking |

### 4.2 Build-from-source

| Requirement | Detail |
|-------------|--------|
| Node.js + npm | Required to install dependencies and rebuild native modules |
| Native build tools | `node-gyp` and a C/C++ toolchain (for `node-pty`) |
| Windows | `windows-build-tools` + Python 2.7 (legacy native build path); run shell **as administrator** |
| macOS | Xcode Command Line Tools |
| `electron-rebuild` | Rebuilds `node-pty` against the bundled Electron ABI |

### 4.3 Runtime dependencies (`src/package.json`)

| Package | Version | Purpose |
|---------|---------|---------|
| `@electron/remote` | `^1.2.2` | Renderer access to main-process modules (`app`, `clipboard`, `globalShortcut`, …) |
| `xterm` + addons (`-attach`, `-fit`, `-ligatures`, `-webgl`) | `4.14.1` / various | Terminal front-end and rendering |
| `node-pty` | `0.10.1` | Pseudo-terminal back-end (native module) |
| `ws` | `7.5.5` | WebSocket server bridging pty ↔ xterm |
| `systeminformation` | `5.9.7` | All CPU/RAM/network/process/hardware data |
| `geolite2-redist` + `maxmind` | `^2.0.4` / `4.3.2` | GeoIP database download + lookups for the globe |
| `smoothie` | `1.35.0` | Real-time streaming charts (CPU, network) |
| `howler` | `2.2.3` | Sound-effect playback |
| `pdfjs-dist` | `2.11.338` | In-app PDF viewer |
| `color` | `3.2.1` | Theme color filters / terminal palette generation |
| `nanoid` | `3.1.30` | Modal and request IDs |
| `mime-types` | `^2.1.33` | File-type detection in the browser |
| `pretty-bytes` | `5.6.0` | Human-readable byte formatting |
| `shell-env` | `3.0.1` | Capturing a clean login-shell environment |
| `signale` | `1.4.0` | Main-process logging |
| `tail`, `which`, `username` | various | Misc utilities |
| `osx-temperature-sensor` | `1.0.7` (optional) | macOS CPU temperature |

---

## 5. Security Model

eDEX-UI follows the **permissive Electron security posture** that was common before the contextBridge hardening era, because the renderer needs broad Node.js access to run terminals, read the filesystem, and call native modules. This is a deliberate design trade-off, not an oversight — but administrators deploying it (especially on shared or kiosk machines) should understand it precisely.

### 5.1 BrowserWindow `webPreferences` (from `src/_boot.js`)

| Option | Value | Implication |
|--------|-------|-------------|
| `nodeIntegration` | `true` | The renderer can `require()` Node modules directly |
| `contextIsolation` | `false` | Page scripts and Electron/Node share one context |
| `enableRemoteModule` | `true` | `@electron/remote` exposes main-process objects to the renderer |
| `webSecurity` | `true` | Same-origin policy stays enforced |
| `allowRunningInsecureContent` | `false` | Mixed/insecure content blocked |
| `nodeIntegrationInSubFrames` | `false` | Subframes do **not** get Node access |
| `experimentalFeatures` | from `settings.experimentalFeatures` (default `false`) | Optional Chromium experimental web features (flagged DANGEROUS in-app) |
| `backgroundThrottling` | `false` | Keeps panels updating when unfocused |

> [!WARNING]
> With `nodeIntegration:true` and `contextIsolation:false`, **any code that executes in the renderer has full local user privileges** (filesystem, process spawning, network). eDEX mitigates this by only ever loading its own local `file://` UI and locking navigation — but if you extend eDEX or inject untrusted CSS/HTML/themes, you are running it inside a fully privileged context.

### 5.2 Mitigations actually present in the code

eDEX does not rely on a sandbox; instead it constrains what can run:

| Layer | Mechanism | Source |
|-------|-----------|--------|
| **No remote content** | Only `file://ui.html` is ever loaded | `createWindow()` |
| **Navigation lock** | `will-navigate` is prevented unless the URL equals the current page | `app.on('web-contents-created')` |
| **External links** | `new-window` is prevented and routed to `shell.openExternal` | same |
| **`eval()` disabled** | `window.eval`/`global.eval` throw `"eval() is disabled for security reasons."` | `_renderer.js` |
| **Input/CSS sanitization** | `_escapeHtml`, `_purifyCSS` (strips `<`), `_encodePathURI` for filenames and theme CSS | `_renderer.js` |
| **Single instance** | `requestSingleInstanceLock()` | `_boot.js` |
| **Single WS client** | `ws` `verifyClient` rejects connection #2 per port | `terminal.class.js` |
| **si method allow-check** | `systeminformation-call` rejects unknown method names | `_multithread.js` |

### 5.3 Network egress

eDEX makes several **outbound** connections. There are no inbound listeners except the loopback terminal WebSockets.

| Destination | Purpose | Module |
|-------------|---------|--------|
| `127.0.0.1:3000` (+`3002–3005`) | Terminal pty ↔ xterm bridge (loopback only) | `terminal.class.js` |
| `myexternalip.com:443` | Discover the machine's external IPv4 | `netstat.class.js` |
| GeoLite2 redistribution endpoint | Download the GeoIP database to `userData/geoIPcache` | `netstat.class.js` (via `geolite2-redist`) |
| `settings.pingAddr` (default `1.1.1.1:80`) | TCP connect-time latency ("ping") | `netstat.class.js` |
| `api.github.com/repos/GitSquared/edex-ui/releases/latest` | Update check on launch | `updateChecker.class.js` |
| Peer IPs from `systeminformation.networkConnections()` | Pinned on the globe (display only) | `locationGlobe.class.js` |

> [!CAUTION]
> On restricted / proxied networks these lookups fail. eDEX **scrubs `http_proxy`/`https_proxy`** at startup and does not offer proxy configuration ([issue #1050](https://github.com/GitSquared/edex-ui/issues/1050)), so the network panels may stay blank behind a corporate proxy. This does not affect the terminal itself.

### 5.4 Things that do **not** exist (negative knowledge)

To prevent fabricated configuration assumptions:

- **No HTTP/REST API.** eDEX exposes nothing over HTTP; the only sockets are the loopback terminal WebSockets.
- **No authentication or multi-user model.** It is a single-user desktop app.
- **No remote management, telemetry, or analytics.** The only outbound calls are those listed in §5.3.
- **No plugin system or extension API.** Customization is limited to themes, keyboard layouts, settings, and shortcuts.
- **No environment-variable configuration.** All configuration is via JSON files in the user-data directory (and two CLI flags).
- **No system-wide config file.** Configuration is strictly per-user under the Electron `userData` path.

### 5.5 Known security-relevant issues

| Issue | Note |
|-------|------|
| [#1160](https://github.com/GitSquared/edex-ui/issues/1160) | Password Mode previously revealed keystrokes on macOS — verify on your version before relying on it for secret entry |
| [#1103](https://github.com/GitSquared/edex-ui/issues/1103) | `unable to verify the first certificate` on intercepting proxies |
| Unsigned binaries | Release artifacts are not code-signed (`forceCodeSigning: false`) — distribute checksums/links from the official repo only |

---

## 6. Configuration Reference

All configuration lives in the Electron user-data directory:

| Platform | Path |
|----------|------|
| Windows | `%APPDATA%\eDEX-UI\` |
| macOS | `~/Library/Application Support/eDEX-UI/` |
| Linux | `~/.config/eDEX-UI/` |

| File | Contents |
|------|----------|
| `settings.json` | All behavioral settings (table below) |
| `shortcuts.json` | Keyboard + custom command shortcuts |
| `lastWindowState.json` | `{ "useFullscreen": bool }` |
| `versions_log.json` | Per-version first/last-seen timestamps |
| `themes/`, `keyboards/`, `fonts/` | Mirrored copies of built-in assets + user additions |
| `geoIPcache/` | Downloaded GeoLite2 database |

### 6.1 `settings.json` — complete reference

Defaults are those written by `_boot.js` on first run. Keys marked *(editor)* are exposed in the settings editor but have no hardcoded default.

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `shell` | string | `bash` / `powershell.exe` (Win) | Program run as the terminal |
| `shellArgs` | string | `""` | Arguments passed to the shell (non-Windows defaults to `--login` when empty) |
| `cwd` | string | userData dir | Starting working directory; must exist or startup fails |
| `env` | object/string *(editor)* | — | Custom environment overrides merged into the shell env |
| `username` | string *(editor)* | — | Display name shown in the boot greeting (falls back to OS username) |
| `keyboard` | string | `en-US` | On-screen keyboard layout code |
| `theme` | string | `tron` | Theme name |
| `termFontSize` | number | `15` | Terminal font size (px) |
| `audio` | bool | `true` | Master sound-effects switch |
| `audioVolume` | number | `1.0` | Sound-effects volume `0.0`–`1.0` |
| `disableFeedbackAudio` | bool | `false` | Mute frequent stdin/stdout click sounds only |
| `clockHours` | number | `24` | `12` or `24`-hour clock |
| `pingAddr` | string | `1.1.1.1` | IPv4 address for the latency test |
| `port` | number | `3000` | Base port for the terminal WebSocket(s) |
| `monitor` | number *(editor)* | primary | Display index to open on |
| `iface` | string *(editor)* | auto | Force a specific network interface for monitoring |
| `nointro` | bool | `false` | Skip the boot animation/logo |
| `nocursor` | bool | `false` | Hide the mouse cursor (kiosk) |
| `forceFullscreen` | bool | `true` | Launch fullscreen |
| `allowWindowed` | bool | `false` | Permit `F11` to leave fullscreen |
| `keepGeometry` | bool *(editor)* | `true` | Keep a 16:9 aspect ratio in windowed mode |
| `excludeThreadsFromToplist` | bool | `true` | Collapse threads in the process list |
| `hideDotfiles` | bool | `false` | Hide dotfiles in the browser |
| `fsListView` | bool | `false` | Use list view in the browser |
| `experimentalGlobeFeatures` | bool | `false` | Scan terminal output for IPs and pin them on the globe |
| `experimentalFeatures` | bool | `false` | Enable Chromium experimental web features (**DANGEROUS**) |

> [!NOTE]
> `experimentalGlobeFeatures` makes the terminal client scan **all pty output** for IPv4 addresses and pin them on the globe ([issue #397](https://github.com/GitSquared/edex-ui/issues/397)). This means terminal content is parsed by a regex on every message — disable it if you process sensitive output or want lower CPU usage.

### 6.2 `shortcuts.json` — schema

An array of shortcut objects:

```json
[
  { "type": "app",   "trigger": "Ctrl+Shift+C", "action": "COPY",     "enabled": true },
  { "type": "app",   "trigger": "Ctrl+X",       "action": "TAB_X",    "enabled": true },
  { "type": "shell", "trigger": "Ctrl+Shift+Alt+Space", "action": "neofetch", "linebreak": true, "enabled": false }
]
```

| Field | Meaning |
|-------|---------|
| `type` | `"app"` (built-in action) or `"shell"` (run a terminal command) |
| `trigger` | Accelerator string (`Ctrl`/`Alt`/`Shift` + key); `X` in `TAB_X` expands to tabs 1–5 |
| `action` | One of the app actions below, or for `shell` type the command text to send |
| `linebreak` | (`shell` only) append `\r` so the command runs immediately |
| `enabled` | Whether the shortcut is active |

**App action identifiers:** `COPY`, `PASTE`, `NEXT_TAB`, `PREVIOUS_TAB`, `TAB_X` (`TAB_1`…`TAB_5`), `SETTINGS`, `SHORTCUTS`, `FUZZY_SEARCH`, `FS_LIST_VIEW`, `FS_DOTFILES`, `KB_PASSMODE`, `DEV_DEBUG`, `DEV_RELOAD`.

> [!TIP]
> Shortcuts are registered globally via `globalShortcut` while eDEX has focus and unregistered on blur, so they will not interfere with other applications when eDEX is in the background.

### 6.3 Command-line flags

eDEX accepts exactly two runtime flags (parsed in `_renderer.js`):

| Flag | Effect |
|------|--------|
| `--nointro` | Skip the boot animation (the bundled `npm start` uses this) |
| `--nocursor` | Hide the mouse cursor |

There are **no other CLI flags** and no environment-variable configuration.

---

## 7. Module Reference

The renderer's functionality is implemented as 18 ES6 classes in `src/classes/`, instantiated by `initUI()`. Each panel manages its own DOM and its own update timer (driven by `window.si` calls).

### 7.1 Core interaction modules

| Class | File | Responsibility |
|-------|------|----------------|
| `Terminal` | `terminal.class.js` | Dual-role: xterm.js front-end (client) and node-pty + `ws` back-end (server); CWD/process tracking; resize; copy/paste; color filters |
| `Keyboard` | `keyboard.class.js` | On-screen keyboard: renders a layout JSON, handles touch/mouse/physical key sync, modifier state, dead-key accent composition, Password Mode, and shortcut dispatch |
| `FilesystemDisplay` | `filesystem.class.js` | CWD-following file grid; click-to-`cd`, Ctrl/Shift-click behaviors; disk view; special icons for eDEX config files; opens PDFs/text/media |
| `FuzzyFinder` | `fuzzyFinder.class.js` | Modal fuzzy search over the current directory's entries |
| `Modal` | `modal.class.js` | Draggable modal windows (error/warning/info/custom) with `augmented-ui` framing; backs settings, shortcuts, viewers |

### 7.2 System-monitor modules (left column)

| Class | File | Data source (`window.si.*`) / refresh |
|-------|------|---------------------------------------|
| `Clock` | `clock.class.js` | Local time; 1s |
| `Sysinfo` | `sysinfo.class.js` | Date, `os.uptime()`, OS type, `battery()`; uptime 60s, battery 3s |
| `HardwareInspector` | `hardwareInspector.class.js` | `system()`, `chassis()`; 20s |
| `Cpuinfo` | `cpuinfo.class.js` | `cpu()`, `currentLoad()`, `cpuTemperature()`, `processes()`; per-core Smoothie charts |
| `RAMwatcher` | `ramwatcher.class.js` | `mem()`; 440-point grid + swap bar; 1.5s |
| `Toplist` | `toplist.class.js` | `processes()`; top 5; click → full sortable process modal; 2s |

### 7.3 Network modules (right column)

| Class | File | Behavior |
|-------|------|----------|
| `Netstat` | `netstat.class.js` | Interface selection, online/offline, external IP via `myexternalip.com`, GeoIP via `maxmind`/`geolite2-redist`, TCP ping; 2s |
| `LocationGlobe` | `locationGlobe.class.js` | ENCOM 3-D globe; pins your location + established connections (`networkConnections()`); optional IP scanning of terminal output |
| `Conninfo` | `conninfo.class.js` | Up/down traffic Smoothie charts + cumulative bytes via `networkStats(iface)`; 1s |

### 7.4 Media / support modules

| Class | File | Responsibility |
|-------|------|----------------|
| `AudioManager` | `audiofx.class.js` | Loads 13 WAV effects via `howler`; returns a Proxy so missing sounds no-op safely |
| `DocReader` | `docReader.class.js` | PDF.js-based viewer (page nav, zoom) inside a modal |
| `MediaPlayer` | `mediaPlayer.class.js` | Audio/video player controls (play/pause, seek, volume, fullscreen) |
| `UpdateChecker` | `updateChecker.class.js` | Queries the GitHub releases API; shows a modal if a newer version exists |

> [!NOTE]
> Several modules guard their DOM updates in `try/catch` because the DOM can be torn down mid-update during a theme hot-swap (which reloads the UI). This is intentional defensive code, not a sign of error.

### 7.5 Inter-module communication

- The terminal client exposes `oncwdchange` / `onprocesschange` callbacks. `FilesystemDisplay.followTab()` subscribes to `oncwdchange` to re-read the directory; `_renderer.js` subscribes to `onprocesschange` to update the tab label.
- `window.mods` holds the live panel instances (`clock`, `sysinfo`, `netstat`, `globe`, …) so modules can reference each other (e.g. `Conninfo` reads `window.mods.netstat.iface`).
- `window.term[n]` holds the per-tab terminal clients; `window.currentTerm` is the active index.

---

## 8. Build & Distribution

### 8.1 Running from source

=== "Linux / macOS"

    ```bash
    git clone https://github.com/GitSquared/edex-ui.git
    cd edex-ui
    npm run install-linux      # or rely on Xcode CLT on macOS
    npm run start
    ```

    `install-linux` runs `npm install` at the root and in `src/`, then `electron-rebuild -f -w node-pty` to recompile the native pty module against Electron's ABI.

=== "Windows"

    Open `cmd` or PowerShell **as administrator**, then:

    ```powershell
    git clone https://github.com/GitSquared/edex-ui.git
    cd edex-ui
    npm run install-windows
    npm run start
    ```

    The legacy `preinstall-windows` step installs `windows-build-tools`, `node-gyp`, and points `PYTHON` at the bundled Python 2.7 for native compilation.

`npm run start` launches `electron src --nointro`.

### 8.2 npm scripts

| Script | Purpose |
|--------|---------|
| `start` | `electron src --nointro` |
| `install-linux` / `install-windows` | Install deps + `electron-rebuild` native `node-pty` |
| `preinstall-windows` | Install Windows build toolchain + Python 2.7 |
| `prebuild-linux` / `-darwin` / `-windows` | Copy `src` → `prebuild-src`, minify, then `npm install` there |
| `build-linux` / `-darwin` / `-windows` | Run `electron-builder` for the host OS |
| `postbuild-*` | Remove the temporary `prebuild-src` |
| `test` | Prebuild + `snyk test` for dependency vulnerabilities |
| `init-file-icons` | `git submodule update --init` |
| `update-file-icons` | Pull icon submodules + run `file-icons-generator.js` |

> [!IMPORTANT]
> Because `node-pty` is a **native module**, you can only build artifacts for the host OS you are on — there is no cross-compilation. Run `npm install` (not the `install-*` variants) before `build-*`.

### 8.3 Packaging (`electron-builder`)

The root `package.json` `build` block defines the release matrix:

| Platform | Target | Artifact name |
|----------|--------|---------------|
| Linux | AppImage (x64, ia32, arm64, armv7l) | `eDEX-UI-Linux-${arch}.AppImage` |
| macOS | dmg (x64) | `eDEX-UI-macOS-${arch}.dmg` |
| Windows | NSIS (x64, ia32) | `eDEX-UI-Windows-${arch}.exe` |

- `asar: true` — source packed into an asar archive.
- `forceCodeSigning: false` — **binaries are unsigned**.
- `npmRebuild: true` — native modules rebuilt during packaging.
- NSIS: `oneClick: false`, `allowToChangeInstallationDirectory: true`, `deleteAppDataOnUninstall: true`.
- `publish: github` — releases are published to GitHub.

### 8.4 The boot pipeline

`prebuild-minify.js` (via `terser`/`clean-css`) minifies JS and CSS before packaging so distributed binaries are smaller and obfuscated. `file-icons-generator.js` compiles the SVG icon submodules (Atom file-icons, devopicons, mfixx, font-awesome, bytesize) into `src/assets/icons/file-icons.json` plus a generated `file-icons-match.js` that maps filenames to icons by regex.

---

## 9. Operations

### 9.1 Deploying as a kiosk / touchscreen display

eDEX-UI is well-suited to a fullscreen kiosk. Recommended configuration:

```json
{
  "forceFullscreen": true,
  "allowWindowed": false,
  "nocursor": true,
  "nointro": true,
  "theme": "tron-notype",
  "audio": false
}
```

- [x] `forceFullscreen` + `allowWindowed:false` locks the display fullscreen (`F11` is intercepted).
- [x] `nocursor:true` hides the pointer for touch-only use.
- [x] `nointro:true` skips the boot animation on every restart.
- [x] A `-notype` theme hides the keyboard/filesystem for a cleaner monitor wall, if input isn't needed.
- [x] Launch with `--nointro --nocursor` to enforce kiosk behavior even before settings load.
- [x] Pre-seed `settings.json` and `themes/`/`keyboards/` in the user-data directory during provisioning.

> [!TIP]
> eDEX opens on the primary display by default. Use the `monitor` setting (a display index) to target a specific screen in multi-monitor setups.

### 9.2 Logs and diagnostics

- The main process logs via `signale` to stdout/stderr (startup timing, terminal lifecycle, errors). Launch from a terminal to see them.
- The renderer forwards errors to the main log over IPC (`ipc.send("log", "error", …)`) and shows them as on-screen error modals.
- Open Chromium DevTools with `Ctrl+Shift+I` (enable the `DEV_DEBUG` shortcut first — it ships disabled).

### 9.3 Resetting configuration

To reset eDEX to defaults, quit it and delete (or rename) the user-data directory (§6). eDEX recreates default `settings.json`, `shortcuts.json`, and re-mirrors built-in assets on next launch.

### 9.4 Performance tuning

| Lever | Effect |
|-------|--------|
| Theme choice | `-notype`/simpler themes and disabling color filters reduce GPU load |
| `experimentalGlobeFeatures: false` | Stops per-message IP regex scanning of terminal output |
| Fewer tabs | Each tab is a full pty + WebSocket + tracking timer |
| Worker cap | The si worker count is `min(cores-1, 7)` — already bounded |
| `backgroundThrottling` | Disabled by design (keeps panels live); not user-tunable |

---

## 10. Troubleshooting (Operator Reference)

In-code error strings and their meaning:

### Error: `eDEX-UI crashed`

An uncaught exception reached the main process. The dialog shows the underlying message; eDEX closes all ptys and exits with code 1. Launch from a terminal to capture the `signale.fatal` stack trace.

### Error: `Another instance of eDEX is already running. Cannot proceed.`

The single-instance lock rejected a second launch. Use the existing window or fully quit it first.

### Error: `Configured cwd path does not exist.`

`settings.cwd` points to a missing directory. Fix `settings.json` and restart.

### Stuck at "Settings loaded!"

`which(settings.shell)` failed to resolve the shell to a path ([issue #1168](https://github.com/GitSquared/edex-ui/issues/1168)). Ensure the configured shell is installed and on `PATH`.

### Error: `ERROR: max number of ttys reached`

All five terminal slots are occupied. Close a tab (exit its shell) before opening another.

### Error: `eval() is disabled for security reasons.`

Expected — eval is intentionally disabled. If you see this it means some code (often an injected theme/plugin attempt) tried to call `eval`. Remove the offending customization.

### Error: `RAM Watcher Error: Bad memory values`

`systeminformation.mem()` returned inconsistent totals on this platform. Usually transient; if persistent, it indicates a `systeminformation` incompatibility with the OS.

### Error: `fsDisp media displayer: unknown type <…>`

The filesystem display tried to render a media type it doesn't handle. Open the file externally (Ctrl+click) instead.

### Globe / IP blank, `NetStat: Error parsing data from myexternalip.com`

The external-IP lookup failed (offline, blocked, or proxied) ([issues #964](https://github.com/GitSquared/edex-ui/issues/964), [#1135](https://github.com/GitSquared/edex-ui/issues/1135)). The terminal is unaffected.

### `unable to verify the first certificate`

TLS interception (corporate proxy). eDEX has no proxy support ([issue #1050](https://github.com/GitSquared/edex-ui/issues/1050)); network panels stay blank.

### High CPU usage

Continuous graphs + globe + polling ([issue #1169](https://github.com/GitSquared/edex-ui/issues/1169)). Apply the performance levers in §9.4.

### Layout overlap on ultrawide displays

Unusual aspect ratios are not fully supported ([issues #832](https://github.com/GitSquared/edex-ui/issues/832), [#1162](https://github.com/GitSquared/edex-ui/issues/1162)). Use a 16:9 display or `extra_ratios` CSS.

---

## 11. Code Quality & Conventions

| Aspect | Observation |
|--------|-------------|
| **Style** | Plain ES6 classes, one per file under `src/classes/`, each `module.exports`-ing its class. No transpilation or bundler; files are loaded directly by the Electron renderer. |
| **State** | Heavily uses globals on `window` (`window.mods`, `window.term`, `window.settings`, `window.modals`). Acceptable for a single-window app but tightly couples modules. |
| **DOM construction** | Modules build DOM via template-literal `innerHTML`. User/file input is routed through `_escapeHtml` / `_encodePathURI`; theme CSS through `_purifyCSS`. |
| **Concurrency guards** | Update methods use `currentlyUpdating`/`_reading` flags to prevent overlapping async refreshes (e.g. `RAMwatcher`, `Cpuinfo`, `FilesystemDisplay`). |
| **Error resilience** | DOM updates wrapped in `try/catch` to survive theme hot-swaps; the `AudioManager` Proxy and `window.si` Proxy degrade gracefully. |
| **Platform branching** | Many `process.platform === "win32"` branches (CWD tracking, CPU temp, paths) — Windows is a consistent special case. |
| **Native dependency** | `node-pty` requires `electron-rebuild`; the single biggest build/portability constraint. |

---

## 12. Potential Improvements

> [!NOTE]
> The project is archived, so these are observations for forks or maintainers rather than a roadmap.

- **Migrate to the modern Electron security model.** Move to `contextIsolation:true` + a `contextBridge` preload exposing a minimal API, and run the terminal bridge over IPC instead of an unauthenticated localhost WebSocket. This is a substantial rewrite but removes the broadest part of the attack surface.
- **Replace the deprecated external-IP/GeoIP path.** The `myexternalip.com` dependency and GeoLite2 download are common failure points; a configurable provider (or making the feature optional/offline) would improve reliability on restricted networks.
- **Add proxy support.** Honoring `http_proxy`/`https_proxy` (or an explicit proxy setting) would fix the corporate-network failures ([#1050](https://github.com/GitSquared/edex-ui/issues/1050), [#1103](https://github.com/GitSquared/edex-ui/issues/1103)) instead of scrubbing the variables.
- **Windows CWD tracking.** Investigate a Windows-native mechanism (e.g. querying the pty child's working directory via the Win32 API) to remove the "detached" limitation.
- **Reduce idle CPU.** Throttle or pause graphs/globe when unfocused (currently `backgroundThrottling:false`), and make polling intervals configurable.
- **Decouple modules from globals.** Introduce a small event bus or dependency injection to reduce the `window.*` coupling and ease testing.
- **Pin/refresh dependencies.** `node-pty 0.10`, `xterm 4`, and Electron 12 are several major versions behind current; upgrading would bring security and rendering improvements (at the cost of API migration).

---

## 13. Quick Reference

### Default ports

| Port | Use |
|------|-----|
| `3000` | Main terminal WebSocket |
| `3002`–`3005` | Extra terminal tabs (up to 4) |

### Default keyboard shortcuts

| Trigger | Action |
|---------|--------|
| `Ctrl+Shift+C` / `Ctrl+Shift+V` | Copy / paste |
| `Ctrl+Tab` / `Ctrl+Shift+Tab` | Next / previous tab |
| `Ctrl+X`+n | Switch to / create tab n |
| `Ctrl+Shift+S` / `Ctrl+Shift+K` | Settings / shortcuts editor |
| `Ctrl+Shift+F` | Fuzzy file search |
| `Ctrl+Shift+L` / `Ctrl+Shift+H` | List view / dotfiles toggle |
| `Ctrl+Shift+P` | Password Mode |
| `Ctrl+Shift+I` / `Ctrl+Shift+F5` | DevTools / reload |

### Config directory

| Platform | Path |
|----------|------|
| Windows | `%APPDATA%\eDEX-UI\` |
| macOS | `~/Library/Application Support/eDEX-UI/` |
| Linux | `~/.config/eDEX-UI/` |

### Build commands

```bash
npm run install-linux   # or install-windows (admin)
npm run start           # run from source
npm install && npm run build-linux   # package for host OS (build-darwin / build-windows)
```

### Key facts

| Fact | Value |
|------|-------|
| Entry point | `src/_boot.js` |
| Main IPC channels | `terminal_channel-<port>`, `systeminformation-call`, `ttyspawn`, `log`, `*ThemeOverride`, `*KbOverride` |
| Max terminal tabs | 5 |
| Scrollback | 1,500 lines |
| si worker count | `min(cores − 1, 7)` |
| Built-in themes / layouts | 20 / 19 |
| License | GPL-3.0 |

---

_Generated June 2026 from GitSquared/edex-ui at 04a00c4. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
