Skip to content

Repository files navigation

Loki

A cross-platform terminal and remote-access client: SSH, SFTP, Mosh, Telnet, RDP, VNC and serial, organised around end-to-end encrypted vaults rather than a plaintext ~/.ssh/config. Dark green throughout.

Status: early. The connection engine, vault crypto, and protocol registry are built and tested. The desktop shell and UI are in progress. See Protocol support for what actually carries traffic today.

Why another one

Loki treats connection data as an object graph — Vault → Group → Host, with credentials in a Keychain that hosts reference rather than embed. Rotating a key touches one object instead of fifty host entries, and group defaults cascade so "route Production through the bastion" is set once.

The differentiator is the trust model. Loki's vaults are encrypted whole — including hostnames, usernames and tags, not just passwords — and secrets never leave the main process. The renderer receives hasPassword: true, never the password itself; the window that draws your UI cannot read your credentials.

Architecture

src/
  shared/          domain model + protocol catalogue (no I/O)
  main/
    vault/         envelope encryption + on-disk store
    connect/       resolver, connector registry, per-protocol transports
    session/       session base class + middleware pipeline

Three ideas carry most of the weight:

Protocol connectors. Every protocol is a Connector in one registry, keyed by a discriminated union. Nothing outside src/main/connect/ branches on protocol. Protocols split into direct (spoken in-process, works with no server at all) and gateway (needs a guacd sidecar — the only realistic path for RDP and VNC from JavaScript).

Session middleware. Everything between a transport and the terminal is a pipeline stage, so transcripts, shell integration, and startup scripts are added once rather than per protocol. Output stages run in insertion order and input stages in reverse, keeping the pipeline symmetric. Sessions buffer output until the renderer attaches, so server banners are never lost to a slow-mounting UI.

Envelope encryption. passphrase --scrypt--> KEK --wraps--> DEK --> payload. Changing the passphrase rewraps 32 bytes instead of re-encrypting the vault, and the KDF runs once per unlock rather than once per record. Each payload carries associated data binding it to its vault id, so an attacker with write access to the vault directory cannot swap payloads between vaults undetected.

Protocol support

Protocol Transport Status
SSH direct Implemented — jump-host chains, password / keyboard-interactive / key / agent auth, host-key verification
Telnet direct Implemented — full IAC option negotiation, NAWS, terminal-type
SFTP direct Pending — SSH transport is in place; needs the file-browser surface
Mosh direct Pending — needs the mosh-client binary and a UDP path
Serial direct Pending — needs the serialport native module
RDP gateway Pending — needs a guacd sidecar
VNC gateway Pending — needs a guacd sidecar

Pending protocols are registered, not omitted: attempting one raises a ProtocolNotImplementedError naming exactly what is missing, so the gap is visible in the code and explainable in the UI.

Screenshots

Hosts, with the Host Details panel:

Hosts

Group Details, including inherited defaults and cloud-sync intent:

Groups

Keychain — keys and identities, filtered by type:

Keychain

Identity editor — username and password login, with the password write-only:

Identity

Deleting names what is going, and warns about anything that depends on it:

Delete

Terminal, with the appearance side panel:

Terminal

Running it

Requires Node 20+ (see .nvmrc). Works the same on Windows, macOS and Linux.

npm install
npm run dev       # opens the Loki window

On Windows, npm install prints a warning about cpu-features failing to build if Visual Studio build tools are absent. That is expected and harmlesscpu-features is an optional dependency of ssh2, loaded inside a try/catch, and SSH works without it. Packaging excludes it outright, so no build toolchain is needed to produce an installer either.

Building an installer

npm run build:win            # NSIS installer (x64 + arm64) and a portable .exe
npm run build:win-portable   # portable .exe only
npm run build:mac            # dmg
npm run build:linux          # AppImage + deb
npm run build:unpacked       # unpacked app dir, for a quick smoke test

Output lands in release/. The Windows installer is per-user, so it does not prompt for admin rights, and lets you pick the install directory.

Windows binaries cannot be cross-built from Linux (that needs wine), so .github/workflows/build.yml builds each platform on its own runner and uploads the artifacts. Push a v* tag, or run the workflow manually.

Development

npm test          # 94 tests, including SSH against a real in-process server
npm run typecheck

Prior art

Loki is original code, but its design was chosen after studying three open-source clients. Credit where it is due:

  • Tabby (MIT) — the ProfileProvider registry and SessionMiddlewareStack shaped Loki's connector and middleware layers, as did its trick of buffering initial output until the terminal mounts.
  • Termix (Apache-2.0) — demonstrated that RDP/VNC realistically require a guacd sidecar, which is why Loki distinguishes direct from gateway transports.
  • MagicTerm (MIT) — the closest existing take on encrypted vaults. Loki's envelope design is a direct response to two limits in its approach: re-deriving the KDF per record, and holding the master password in the renderer.

No code was copied from any of them.

License

Apache-2.0. See LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages