Skip to content

Architecture

Se.Cherkasov edited this page Aug 23, 2026 · 1 revision

Architecture

English · Русский

One Kotlin Multiplatform core, one Compose Multiplatform UI, four platforms. iOS/iPadOS is deferred — there are no iOS targets and no iosMain.

Modules

flowchart TD
  A[androidApp<br/>MainActivity, manifest] --> C[composeApp<br/>Compose Multiplatform UI]
  D[composeApp desktop main] -.same module.- C
  C --> S[shared<br/>KMP core]
  SV[server<br/>Ktor sync server] --> W[sync-wire<br/>client⇆server DTOs]
  S --> W
Loading
Module What it is License
shared/ the core: protocols, vault, sync, terminal, remote desktops, AI GPL-3.0
composeApp/ the whole UI, desktop entry point included GPL-3.0
androidApp/ Android shell: MainActivity, manifest, applicationId app.skerry GPL-3.0
server/ self-hosted sync server (Ktor, Exposed, SQLite/PostgreSQL) AGPL-3.0
sync-wire/ the wire contract both sides compile against — never mirrored by hand shared by both, no separate license file

settings.gradle.kts drops the client modules when -PserverOnly (or SKERRY_SERVER_ONLY=1) is set, which is how the Docker image builds without an Android SDK.

Source sets

shared/src/
  commonMain/       contracts, domain types, pure logic — the only thing the UI sees
  jvmSharedMain/    JVM code shared by desktop and Android (sshj, Ktor, mosh, RDP/VNC transports)
  desktopMain/      desktop-only actuals (JavaSound, ffmpeg H.264, pty4j local shell)
  androidMain/      Android-only actuals (MediaCodec, biometrics keystore, USB serial)
  commonTest/ desktopTest/

jvmSharedMain is the load-bearing one: desktop and Android are both JVM, so anything using a JVM library lives there once instead of twice. Platform libraries sit behind expect/actual or an interface; the UI only ever sees commonMain contracts.

Layering

flowchart LR
  UI[composeApp<br/>screens · controllers · design primitives]
  DEP[AppDependencies<br/>the graph the platform assembles]
  CORE[shared/commonMain<br/>contracts + pure logic]
  PLAT[jvmShared / desktop / android<br/>implementations]
  UI --> DEP --> CORE
  PLAT -. implements .-> CORE
  DEP -. built from .-> PLAT
Loading

AppDependencies is a single holder passed to the root composable. A new subsystem becomes a field there rather than another root parameter; null means "not wired up on this platform" and the UI degrades to a placeholder instead of crashing.

Core packages (shared/commonMain/.../shared/)

Package Contents
ssh/ transport contract, targets and jumps, known hosts, port forwarding, ~/.ssh/config import
sftp/, files/ file transfer contracts
terminal/ emulator, reflow, SGR, search, selection, history, recording, step marks
vault/ vault contract, crypto, records, credentials, trash, security log, biometrics
sync/ sync engine, client contract, cursors, settings
team/, share/ teams and their scopes; live session sharing and its wire framing
rdp/, vnc/, graphics/, audio/ remote desktop stacks and the framebuffer/audio contracts they share
mosh/, telnet/, serial/, container/, local/ the other transports
snippet/, runbook/, host/, tag/ user-facing domain models
ai/ (+ ai/local/) providers, per-host policy, redaction, risk scoring, local llama.cpp runtime
guard/, trust/, update/, text/, io/ production guard, host-trust prompts, update check, text sanitising, private file IO

rdp/ is the largest package by file count — the RDP stack is written here, not borrowed.

Design rules that shape the code

  • Search before you write. The abstraction catalogue in docs/coding-guidelines.md lists what already exists for each recurring task; the second repetition is a signal, the third makes extraction mandatory.
  • Files stay under ~400–500 lines, split by screen section or subsystem when they approach it.
  • Logic never lives inside a composable. Parsers, state machines and protocols live in shared/, or beside the UI but pure and directly testable.
  • Desktop⇆Android parity is a completion criterion, not a follow-up.

Details per subsystem: Connections and transports, Terminal engine, Vault and crypto, Sync protocol, Remote desktop stacks, UI layer.

Clone this wiki locally