Jesse A. Green / notebook

eDEX-UI Administrator & Developer Guide

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.

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 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.

        ┌──────────────────────── 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).
  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)

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.

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:

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).
  • 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. Registers global keyboard shortcuts via electron.remote.globalShortcut, re-registering on window focus and clearing on blur.

3. Repository Structure

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), 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 Password Mode previously revealed keystrokes on macOS — verify on your version before relying on it for secret entry
#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). 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:

[
  { "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

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:

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:

{
  "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). 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, #1135). The terminal is unaffected.

unable to verify the first certificate

TLS interception (corporate proxy). eDEX has no proxy support (issue #1050); network panels stay blank.

High CPU usage

Continuous graphs + globe + polling (issue #1169). Apply the performance levers in §9.4.

Layout overlap on ultrawide displays

Unusual aspect ratios are not fully supported (issues #832, #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, #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

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