SSH client for Android. Native libssh, Compose UI, no ads, no tracking.
Web · Beta · Build · License
ShellDroid is in closed beta on Google Play:
- Join the testers group (one click)
- Download from Google Play
JuiceSSH disappeared. One day it was there, the next the Pro unlock was gone and the app stopped getting updates. Years of muscle memory — the hacker keyboard, quick connect, snippets — vanished.
The alternatives? ConnectBot hasn't had a meaningful commit since 2019. Termius wants $10/month. I use maybe 20% of what Termius offers.
So I built my own.
What's different technically:
Most Android SSH clients sit on JSch or sshlib — pure Java, aging crypto, slow key exchange. ShellDroid uses libssh 0.11.4 compiled natively via JNI with mbedTLS. Ed25519 and ECDSA work properly, and the first connection is noticeably faster because the key exchange isn't fighting the JVM.
The terminal runs on ConnectBot's termlib but as a real @Composable — not an AndroidView hacked into Compose. IME resizing, focus, and key handling live in the composition tree. No flickering, no workarounds.
Connection — libssh native (password, RSA, Ed25519, ECDSA). Quick Connect (user@host:port), TOFU with per-host known hosts, live session indicator.
Terminal — Compose-native termlib. Two-row hacker keyboard (ESC, arrows, CTRL/ALT sticky, F1–F12). Snippets (saved commands, one tap). Auto-command on connect. Volume keys for font size.
Port forwarding — LOCAL (ssh -L), DYNAMIC/SOCKS5 (ssh -D, RFC 1928 in Kotlin). Auto-connect on play. REMOTE (ssh -R) coming next.
Security — Tink AES-256-GCM credential vault (CharArray + zeroize, never in the string pool). App lock via BiometricPrompt + system credential. Configurable auto-lock timeout. allowBackup=false.
UI — Two skins (Abyss, Solarized Dark). Dark/Light follows system. English + Spanish. Foreground service with notification actions. Clone anything with one tap.
Everything runs in Docker — no Android SDK on the host:
./vendor/setup.sh # first time: clones libssh, mbedtls
./docker-gradle.sh :app:assembleDebug # APK in app/build/outputs/apk/debug/
./docker-gradle.sh test # unit testsLocal OpenSSH server via Docker Compose at 127.0.0.1:2222 for integration tests.
12 Gradle modules. Kotlin, Jetpack Compose + Material 3, Hilt, Room, libssh native + mbedTLS. Min SDK 26.
:app → Activity, NavHost, Settings
:core:ssh → LibSshClient, SshSessionManager, ShellChannel
:core:ssh-native → JNI bindings (libssh + mbedTLS .so)
:core:db → Room entities, DAOs, migrations
:core:security → CredentialVault (Tink), LockManager
:core:ui → Theme, strings i18n, shared UI
:feature:hosts → CRUD hosts + Quick Connect
:feature:identities → CRUD identities (password, keys)
:feature:terminal → TerminalBridge, TerminalScreen, KeyBar, skins
:feature:snippets → CRUD snippets
:feature:portforward → CRUD port forwards
:service:session → Foreground service + notification
v0.4.2-alpha — functional, I use it daily. What's left for 1.0: REMOTE forwarding, host groups, panic button, public Play Store release.
GPLv3. Third-party licenses: Settings → About → Licenses in the app.




