I built Termiaxial - a SSH/SFTP client that replaces Termius, PuTTY, and WinSCP with a single, fast, and secure application.
Why?
I was frustrated with existing SSH clients:
- Electron apps (Termius, Royal TSX) eat 200MB+ RAM
- Slow startup times (5s+)
- Heavy CPU usage even when idle
- Proprietary software (can't audit code)
- Expensive licensing ($100+/year)
The Solution: Rust + Tauri v2
Tauri v2 uses the OS's native webview instead of bundling Chromium. Combined with Rust backend, this achieves:
- 50MB idle RAM (vs 200MB+ for Electron apps)
- <1.5s startup (vs 5s+ for competitors)
- Native performance with React + TypeScript frontend
- Fully open source (MIT license)
Tech Stack
Framework: Tauri v2
Frontend: React 18 + TypeScript + Tailwind CSS
Backend: Rust (russh, tokio)
Terminal: Xterm.js v5
Crypto: ring (AES-GCM-256) + argon2
Database: SQLite
Features
Core
- ✅ SSH authentication (password + private key: RSA, ED25519)
- ✅ Full terminal emulator (Xterm.js, 256 colors, 5000-line scrollback)
- ✅ SFTP file explorer with drag-drop upload/download
- ✅ Multi-tab sessions with auto-reconnect
Security
- ✅ Master Password with Argon2id hashing
- ✅ AES-GCM-256 encrypted credential vault
- ✅ Local SQLite storage (no cloud by default)
AI & Productivity
- ✅ AI Assistant (OpenAI, Ollama, Anthropic)
- ✅ Terminal analysis with Ctrl+Space shortcut
Performance Benchmarks
| Metric | Termiaxial | Termius | PuTTY |
|---|---|---|---|
| Idle RAM | 50MB | 200MB+ | 30MB |
| Startup Time | 1.5s | 5s+ | 0.3s |
| CPU Usage | <1% | 3-5% | <1% |
| Bundle Size | 8MB | 120MB+ | 1MB |
Current Status
Repository is 85% ready for open source launch:
- ✅ 7 GitHub Actions workflows (CI/CD, Security, Release)
- ✅ Multi-platform builds (macOS Intel/ARM, Linux AMD64/ARM64)
- ✅ Comprehensive documentation
- ✅ Professional templates for issues/PRs
Roadmap
- v1.5: SSH Tunneling + Snippet Manager
- v2.0: Session Recording + Cloud Sync
- v2.5: Team Collaboration + Enterprise features
GitHub
github.com/angga30/termiaxial
⭐ Star if you like the project
🍴 Fork if you want to contribute
🐛 Report issues on GitHub
For Rust Developers
This project showcases:
- Tauri v2 for cross-platform desktop apps
- Rust + React integration
- AES-GCM-256 encryption with
ring - SSH implementation with
russh - SQLite with
rusqlite - AI integration with OpenAI/Ollama/Anthropic
Would love to get feedback from the Rust community! Especially interested in:
- Performance optimizations
- Security improvements
- Feature suggestions
- Architecture feedback
Built with ❤️ by developers, for developers.
Top comments (5)
Great project! I'm also building macOS apps with Tauri v2 + Rust and the RAM difference vs Electron is genuinely impressive in practice. One thing I ran into — have you tested the russh connection stability on long-running sessions (24h+)? Curious how you handle reconnect edge cases internally.
Thanks! Great question — fellow Tauri+Rust dev knows exactly what to ask 😄
Keep-alive: We run a 30s SSH keep-alive loop via
russh's built-inkeepalive_intervalconfig (SSH_MSG_IGNORE packets). If the server doesn't respond after 3 missed pings (keepalive_max: 3), the session is marked dead.Detection: Our background tokio task per session uses
select!across three channels — data from server, commands from frontend, and a 30s keep-alive tick that checkshandle.is_closed(). The moment any signal indicates the connection dropped, we emit aSessionEvent::Disconnectedthrough our event bus so the UI reacts immediately.Edge cases we handle:
Handleis dropped or closed, cleanup removes it from ourDashMapatomically (we useArc::ptr_eqto avoid race conditions with re-connections)What we don't do yet (honest answer): Auto-reconnect with session resume isn't shipped yet. When a long-running session drops, we notify the user and they reconnect manually. SSH protocol doesn't natively support session resume (unlike Mosh), so true transparent reconnect would require a proxy layer or Mosh-style approach — that's on our roadmap but not trivial to get right.
For 24h+ sessions in practice, the keep-alive mechanism has been solid. The main failure mode we've seen is aggressive NAT timeouts on some corporate networks (<60s), which our 30s interval handles well.
Would love to hear what edge cases you've hit with russh — always looking to harden this further! 🚀
Thanks for the thorough breakdown — the three-channel select! approach is really clean, and using Arc::ptr_eq to avoid race conditions on reconnect is exactly the kind of detail that's easy to miss until it bites you.
The corporate NAT timeout point is interesting too. 30s feels like a solid sweet spot — aggressive enough to stay alive, but not noisy.
I'm also on Tauri v2 + Rust + tokio for my macOS tools, and I've run into similar reconnect edge cases with persistent ADB over Wi-Fi connections — the "connection looks alive but isn't" problem is surprisingly tricky to detect reliably.
Looking forward to the auto-reconnect feature — and agreed, the Mosh-style proxy approach sounds like the right way to do it properly. Not trivial, but worth it for long-running sessions!
Thanks! Yeah, Arc::ptr_eq saved me from quite a few headaches when dealing with rapid reconnect states.
Regarding that ADB over Wi-Fi issue you mentioned—man, 'zombie sockets' are the worst. It’s exactly why TCP keepalives alone often fail us in corporate environments or flaky Wi-Fi, and why an application-level heartbeat becomes mandatory.
For the upcoming auto-reconnect feature, the plan is to robustly handle that specific 'looks alive but dead' state before moving into the full Mosh-style proxy architecture.
Appreciate the insights, and it’s awesome to connect with a fellow Tauri v2 + Rust developer on macOS. Will keep you posted on the progress!
"Zombie sockets" is exactly the right term for it — the connection reports as open but any actual I/O just silently fails. Application-level heartbeat is the only reliable way to catch that, agreed.
With ADB over Wi-Fi I ended up having to treat every "connected" state as unverified until a real command round-trips successfully. Sounds like you're hitting the same fundamental problem, just over SSH.
The approach of hardening the "looks alive but dead" detection before tackling full session resume makes a lot of sense — getting that state machine right is probably 80% of the work anyway.
Looking forward to seeing how the auto-reconnect lands. And likewise — always good to find another Tauri v2 + Rust dev in the wild!