Open-source, cross-platform manager for SSH connections, keys, and known hosts. A community-driven alternative to Termius.
Status: early scaffold. Desktop (Tauri) shell + shared Rust core are in place; mobile (iOS/iPadOS/Android) is planned.
- Secure by default. Private keys encrypted at rest (Argon2id + AES-256-GCM). OS keychain stores the vault passphrase. TOFU host-key verification with no silent auto-accept on mismatch. Private material is zeroized on drop.
- Fast & light. Tauri shell (~10 MB binaries) instead of Electron.
- Cross-platform. One Rust core, multiple UIs:
- Desktop (Linux / Windows / macOS): Tauri
- Mobile (iOS / iPadOS / Android): native UI over the same core via FFI
- Auditable. Minimal dependency surface, pinned versions, no telemetry on connection payloads.
Clavyn/
Cargo.toml # workspace root
core/ # clavyn-core: shared Rust library
src/
connection.rs # SSH transport (russh)
host.rs # host / auth models
keys.rs # key parse / generate (russh-keys)
known_hosts.rs # TOFU known_hosts store
vault.rs # encrypted-at-rest key vault
error.rs
desktop/ # Tauri desktop app
src/ # frontend (HTML/JS, to be upgraded to a framework)
src-tauri/ # Rust backend + Tauri config
src/
commands.rs # Tauri commands exposed to the frontend
state.rs # shared app state (vault, known_hosts, passphrase)
main.rs
mobile/ # planned: iOS / Android (see mobile/README.md)
docs/
ARCHITECTURE.md
- Rust (stable, via rustup) — not yet installed in
this environment; install before building:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
- Node.js 18+ and npm
- Tauri v2 system dependencies:
- macOS:
xcode-select --install - Linux (Debian):
sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev - Windows: Microsoft C++ Build Tools + WebView2
- macOS:
# from repo root
cd desktop
npm install
npm run tauri dev # launches the app with hot reload
npm run tauri build # produces installers in src-tauri/target/release/bundleClavyn is not yet signed with an Apple Developer ID or a Windows code-signing certificate, so the OS may complain when you open a downloaded build for the first time:
- macOS: Gatekeeper may report the app as "damaged" or "unidentified
developer." This is expected for unsigned builds, not actual corruption. To
run it, strip the quarantine attribute:
xattr -cr /Applications/Clavyn.app
- Windows: SmartScreen may show "Windows protected your PC." Click More info → Run anyway.
This is temporary. Proper code signing and notarization are planned for a future release, after which these warnings will disappear. No worries — for now just tell your OS it's fine to open Clavyn. :)
| Asset | At rest | In memory |
|---|---|---|
| Private keys | AES-256-GCM in vault.json |
Zeroizing wrappers |
| Vault passphrase | OS keychain (UI-managed) | Zeroizing<String> |
| Host passwords | OS keychain only | never in core state |
| known_hosts | plaintext JSON (public keys) | n/a |
A server key that differs from the pinned one fails the connection with
CoreError::HostKeyMismatch, which carries the pinned and the presented
fingerprint. The presented key is held in memory and listed under Known Hosts,
where replacing the pin requires confirming the fingerprint that was shown.
Removing a host hides it from the list but keeps its key as a tombstone, so the
next connection with a different key is still reported as a change rather than
accepted as a first contact. Removed hosts stay visible under their own heading
with the key they are still remembered by, and can be forgotten permanently from
there, which erases the key and puts the host back on first-use.
The two commands that can end a pin — forgetting a retained key, and trusting a
key the server presented in its place — confirm in a native OS dialog that
prints the fingerprint as the backend holds it. A page-level confirm() is not
a control, because code calling the command directly never renders one; an
OS-drawn dialog cannot be read, clicked or dismissed from the webview. A
declined dialog also suppresses the next one for half a minute, so a caller
cannot stack prompts until one is clicked through.
Clavyn is open source and contributions are welcome. The project is already heavily used internally by CodeAny employees and is actively maintained — it will continue to be improved consistently over time. There is no published roadmap; instead, development is driven by real usage and by the issues and pull requests the community opens.
- Bugs: Open an issue with the steps to reproduce, your OS, the Clavyn
version (
Settings → Aboutornode scripts/verify/control-clavyn.mjs info), and any relevant logs. Do not include private keys, passphrases, or vault contents in reports. - Feature requests: Open an issue describing the problem you are trying to solve and your proposed approach. Keep scope focused — small, well-defined proposals are easier to review and merge.
- Security vulnerabilities: Do not open a public issue. See SECURITY.md for responsible disclosure.
See Prerequisites and Build & run (desktop) above to get the app running locally. For the full development workflow, conventions, and verification steps, read AGENTS.md — it is the single source of truth for how the project is built, tested, and released.
- Open an issue first for anything beyond a small fix or typo. Discussing the approach before writing code saves everyone time and avoids rework.
- Fork and branch from
main. Use a descriptive branch name (fix/vault-lock-race,feat/sftp-sort, notpatch-1). - Keep changes focused. One logical change per PR. Mixing unrelated refactors with a bug fix makes review harder and risks the whole PR being blocked by one part.
- Follow the conventions in AGENTS.md:
- All SSH/crypto logic lives in
core/, never in shells. - Private key material is wrapped to
Zeroizeon drop. - Host key mismatches never auto-accept; surface to the user.
- No secrets in logs; no plaintext keys on disk; vault is the only persisted form.
- Pin dependency versions (no floating
latest/*).
- All SSH/crypto logic lives in
- Verify before requesting review:
The comment-hygiene check enforces that code comments document the code as it exists now — never narrate history or attribute work. See AGENTS.md "Comment hygiene (enforced)" for the policy.
cargo check --workspace # after core changes cargo test -p clavyn-core # core tests cd desktop && npx vue-tsc --noEmit # frontend typecheck cd desktop && npm test # Vitest unit tests cd desktop/e2e && npm test # Playwright regression suite node scripts/verify/control-clavyn.mjs doctor --pretty # UI verification node scripts/verify/check-comments.mjs --pretty # comment hygiene
- Write good commit messages. Focus on why, not what. Keep commits atomic and logically ordered. Squash WIP commits before requesting review.
- Reference the issue in the PR description (
Closes #123). Include a Summary, what changed, and how you verified it.
PRs are reviewed by CodeAny maintainers. Expect feedback on security, correctness, and adherence to conventions. Please be patient and responsive — review is a collaboration, not a gate. Small, well-scoped PRs with clear descriptions and verification evidence are reviewed fastest.
Releases are automated via GitHub Actions (triggered by a version tag) and the
local scripts/release.sh / scripts/version.sh helpers. See
AGENTS.md for the full release process, version management, and
auto-update architecture.
GPL-3.0-or-later (see LICENSE). Inspired by but unaffiliated with Termius.