Repository navigation
Architecture
English · Русский
One Kotlin Multiplatform core, one Compose Multiplatform UI, four platforms. iOS/iPadOS is
deferred — there are no iOS targets and no iosMain.
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
| 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.
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.
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
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.
| 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.
-
Search before you write. The abstraction catalogue in
docs/coding-guidelines.mdlists 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.
User guide
- Installation
- Getting started
- Hosts and connections
- Vault and credentials
- Terminal
- Files (SFTP)
- Port forwarding
- Remote desktops
- Snippets and runbooks
- Monitoring and guard
- AI assistant
- Sync and devices
- Teams and sharing
- Settings and shortcuts
- Android
- Troubleshooting
Development
- Architecture
- Building and running
- Connections and transports
- Terminal engine
- Vault and crypto
- Sync protocol
- Remote desktop stacks
- UI layer
- Testing and the gate
- Contributing and releases
Русский — оглавление