Skip to content

2241812/OPA_Flutter

Repository files navigation

OPA Logo

⬡ OPA — OpenSSH Pocket Agent

Your server in your pocket. One tap to connect, swipe to command, everything encrypted.

Flutter Dart Platform License


What's New — v0.4

Port Forwarding & Tunnels

Fully integrated SSH tunneling support. Set up Local, Remote, and Dynamic (SOCKS5) port forwarding directly from the new Tunnels screen. Tunnels can be set to auto-start when the connection opens, allowing seamless background networking.

Premium "Deep Space" Redesign

The entire app has been redesigned with a premium aesthetic featuring layered midnight navy surfaces, glowing neon accents, and frosted glass components. The new ConnectionTile is taller, more legible, and features a smooth swipe-to-reveal action menu.

Enhanced Security

Passwords are now stored exclusively in the hardware-backed Android Keystore alongside private keys, completing the migration away from plaintext local storage. The biometric lock has also been rewritten at the routing layer for instant, secure enforcement.


Previous Versions

v0.3

  • Swipe-to-Reveal Actions: Compact swipeable tiles for instant SFTP, Config, and Quick Commands.
  • Built-in Tailscale: Embedded tsnet networking. Join your tailnet from inside OPA without a separate VPN app.

How It Works

One-Tap Connections

Add a server once — host, port, username, auth method — and it's saved forever. Your connection list becomes a launchpad. Tap any tile and you're in a full SSH session before the thought finishes.

Each connection gets a color-coded accent bar so you can spot production, staging, and dev at a glance.

Swipe to Command

Swipe left on any connection tile and three buttons slide in:

  • SFTP — browse remote files
  • Config — edit connection details
  • QCMD — launch quick commands against this server

Release and the tile snaps back. No accidental triggers, no friction.

Terminal, Reimagined for Mobile

The terminal is a first-class mobile experience:

  • Auto-fit font — 80+ columns in portrait, 120+ in landscape
  • Rotate to immersive — landscape hides everything but the shell
  • Smart keyboard bar — TAB, ESC, arrows, Ctrl+C always one tap away
  • VT100/256-color — full terminal emulation via xterm.dart
  • Scrollback — never miss output that scrolls off screen

Your Keys, Your Way

Generate Ed25519 key pairs in the app, or import existing ones. Private keys never leave your device — stored encrypted in Android Keystore.

Agent Presets — Launch Anything

20+ pre-built quick commands for the tools you actually use:

  • AI Agents: Claude Code, opencode, aider, Gemini CLI, Codex
  • Dev Tools: htop, lazygit, tmux, nvim, btop, fastfetch
  • System: journalctl, docker ps, df -h, free -m, ss -tulpn
  • Network: iperf3, mtr, nmap, tcpdump, traceroute

Architecture

Architecture section: Home Screen (ConnectionTile) to Terminal Screen (xterm.dart)

OPA App
  Home Screen (ConnectionTile) --> Terminal Screen (xterm.dart)
    --> dartssh2 (SSH via password, key, or both)
      --> Tailscale (embedded tsnet: WireGuard, MagicDNS, DERP)
        --> Target server

Persistent storage:
  Hive DB --> profiles, quick commands
  Android Keystore --> private keys (hardware-backed)
  SharedPrefs --> onboarding state

Key Decisions

Decision Why
Flutter + Dart Cross-platform, native perf, mature ecosystem
dartssh2 Pure-Dart SSH -- no native bindings, full control
xterm.dart VT100/256-color terminal widget with scrollback
Tailscale (embedded) Per-process tsnet, no VPN app or root needed
ConnectionTile (swipe) GestureDetector + AnimationController, no extra deps
Hive Fast local NoSQL, no SQLite boilerplate
Riverpod Compile-safe state, context-independent
Android Keystore HW-backed storage, keys never leave secure enclave

Project Structure

lib/
+-- main.dart                       # App entry -- Hive init, theme, routing
+-- app_theme.dart                  # Dark glassmorphism theme
+-- app_router.dart                 # GoRouter + onboarding guard
+-- models/
|   +-- connection_profile.dart     # SSH profile (host, port, auth)
|   +-- ssh_key_pair.dart           # Ed25519 key metadata
|   +-- quick_command.dart          # Saved command + presets
+-- services/
|   +-- ssh_service.dart            # dartssh2 wrapper
|   +-- key_service.dart            # Key gen + Keystore CRUD
|   +-- onboarding_service.dart     # First-launch detection
|   +-- update_service.dart         # GitHub Releases update check
|   +-- profile_storage_service.dart # Hive persistence
|   +-- hive_adapters.dart          # Hive type adapters
+-- screens/
|   +-- home_screen.dart            # Connection tiles + commands
|   +-- onboarding_screen.dart      # 4-slide welcome flow
|   +-- terminal_screen.dart        # xterm.dart + auto-fit + keyboard bar
|   +-- profile_editor_screen.dart  # Add/edit connections
|   +-- key_management_screen.dart  # Generate/import/delete keys
|   +-- quick_commands_screen.dart  # Preset browser + custom
+-- widgets/
|   +-- connection_tile.dart        # Swipeable tile -- tap/swipe actions
|   +-- key_card.dart               # Glassmorphism key card
+-- utils/
    +-- constants.dart              # Colors, spacing, constants
    +-- agent_presets.dart          # 20+ agent/tool presets
    +-- ssh_key_encoder.dart        # Ed25519 wire format encoding

Getting Started

Install

Download the latest APK from GitHub Releases. Auto-updates are built in -- OPA checks for new versions on launch.

Build from Source

Prerequisites: Flutter SDK >= 3.0, Go >= 1.26 (for Tailscale native compilation), Android NDK.

git clone https://github.com/2241812/OPA_Flutter.git
cd OPA_Flutter
flutter pub get
flutter run             # Run on connected device
flutter build apk --release  # Release APK

First-Time Setup

  1. Swipe through the 4-slide onboarding or tap Skip.
  2. Tap + to add your first server (host, port 22, username, auth method).
  3. Set up key-based auth: SSH Keys -> + -> Generate Ed25519 Key -> Copy. On your server: echo "ssh-ed25519 AAAAC3... opa" >> ~/.ssh/authorized_keys
  4. Tap any connection tile to open the terminal instantly.
  5. Swipe left for SFTP, Config, or QCMD quick commands.

Setting Up a Target Server

Windows (OpenSSH Server)
# Install (run as Administrator)
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
# Start and enable
Start-Service sshd
Set-Service -Name sshd -StartupType Automatic
# Find your IP
ipconfig
Linux
sudo apt install openssh-server
sudo systemctl enable --now ssh
macOS System Settings -> General -> Sharing -> toggle Remote Login ON.

Tailscale Networking

OPA embeds package:tailscale - userspace Tailscale networking powered by upstream Go tsnet. No separate Tailscale app needed.

  • Join your tailnet from inside OPA - authenticate once, connect forever
  • MagicDNS - reach servers by .ts.net hostname, no IP wrangling
  • WireGuard encryption - every byte between you and your server
  • DERP relay fallback - works through restrictive NATs
  • Per-process - no system-wide VPN, no root, no VPN profile

Requirements

  1. A Tailscale or Headscale tailnet
  2. An auth key from your tailnet admin
  3. Enable Tailscale in OPA Settings and enter your auth key

The node identity is persisted in the app support directory (excluded from cloud backups).


Tech Stack

Package Purpose
dartssh2 Pure-Dart SSH client - auth, shell, exec, SFTP
xterm Terminal emulator - VT100, 256-color, scrollback
tailscale Embedded WireGuard tailnet via Go tsnet FFI
pinenacl Ed25519 key pair generation
flutter_secure_storage Encrypted on-device key storage
hive + hive_flutter Local NoSQL profiles and commands
flutter_riverpod Compile-safe state management
go_router Declarative routing with transitions
google_fonts Inter (UI) + JetBrains Mono (terminal)
flutter_animate Spring/fade/slide animations
url_launcher APK download links
package_info_plus Runtime version for update checks
local_auth Biometric app lock

Security Model

Layer How OPA Protects You
Private keys Android Keystore - hardware-backed, never exposed as plaintext
Passwords Hive database - local only, never sent externally
SSH transport Direct socket, encrypted by SSH protocol, no MITM
Tailscale WireGuard end-to-end, DERP relayed only when necessary
Network Fully offline - zero telemetry, zero cloud, zero third-party
App access Optional biometric lock (fingerprint or face)
Backup Tailscale state dir excluded from cloud backups

Roadmap

  • SFTP file browser - upload, download, manage remote files
  • Port forwarding UI - local, remote, dynamic (SOCKS5) tunnels
  • Jump host / bastion - chain through servers
  • SSH agent forwarding - use local keys remotely
  • Session recording and replay
  • Profile import and export
  • Custom preset editor
  • iOS support
  • Split APKs by ABI for smaller downloads
  • Tailscale Taildrop - P2P file transfers over tailnet

License

MIT Built with love by Renzo Javier

OPA is not affiliated with OpenSSH, Tailscale, or any referenced tool.

About

Your server in your pocket. One tap to connect, swipe to command, everything encrypted.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors