Backend Development
Backend code lives in src-tauri/src/ and is written in Rust. It is the runtime core of NyaTerm: session management, SSH/SFTP, recording, translation, tunnels, authentication, and config persistence all land here.
Command entry points and module organization
Backend command registration is centralized in src-tauri/src/lib.rs:
- Shared manager state is created there
- Tauri plugins are mounted there
- Commands are registered there through
tauri::generate_handler![]
Command modules live in:
src-tauri/src/cmd/
├── session.rs
├── sftp.rs
├── connection.rs
├── settings.rs
├── watcher.rs
├── translate.rs
├── stats.rs
├── tunnel.rs
├── proxy.rs
├── otp.rs
├── importer.rs
├── cloud_sync.rs
├── clipboard.rs
└── log.rs
When adding a new command, the usual flow is:
- Define a
#[tauri::command]in the appropriatecmd/*.rsfile - Reuse existing logic in
core/orconfig/where possible - Register the command in
src-tauri/src/lib.rs - Call it from the frontend through
src/lib/invoke.ts
Shared runtime state
src-tauri/src/lib.rs injects these shared objects into Tauri state:
SessionManagerTunnelManagerRecordingManagerPendingAuthManagerCloudSyncManager
Their roles are:
- Active session lifecycle and command history
- SSH tunnel state
- Recording state
- Pending keyboard-interactive / OTP authentication requests
- Cloud sync / backup state, remote snapshot operations, and conflict handling
SessionManager
src-tauri/src/core/session.rs contains SessionManager, the center of session runtime behavior. It is responsible for:
- Registering and removing active sessions
- Sending
Write,Resize,Close, andAttachcommands into session I/O loops - Managing command history and fuzzy search storage
- Emitting events such as
sessions-changedandcommand-history-changed
The session metadata exposed to the frontend also includes injection_active, which indicates whether the current session supports shell-integration features such as terminal path tracking.
Session implementations
Concrete session types are implemented under src-tauri/src/core/:
ssh/— SSH connections, authentication, OSC/CWD tracking, SFTP, tunnelspty.rs— local terminal sessionstelnet.rs— Telnet sessionsserial.rs— serial sessionsrecording.rs— session recordingwatcher.rs— local file watching and auto-upload flowsimporter.rs— external client session import
SSH modules
src-tauri/src/core/ssh/ is the most central backend area:
client.rs— russh client setup, known-host verification, proxy-aware connection setupauth.rs— loading saved authentication data and handling keyboard-interactive / OTP flowsio.rs— terminal I/O and cwd update eventssftp.rs— remote file operations and transfer queue handlingtunnel.rs— local / remote / dynamic tunnelssession.rs— SSH session lifecycle coordination
A typical SSH flow is:
- Read the connection configuration
- Decrypt passwords, private keys, or other credentials
- Establish the TCP or proxy connection
- Apply host-key policy verification
- Complete authentication, possibly entering OTP / interactive flow
- Open the PTY channel and enter the async I/O loop
- Inject OSC/CWD tracking when supported
SFTP and the transfer queue
src-tauri/src/core/ssh/sftp.rs is responsible for:
- Listing directories
- Uploading / downloading files and directories
- Delete / rename / mkdir / symlink / stat operations
- Transfer queue control such as pause / resume / cancel
- Emitting
transfer-eventfor the frontend
The frontend transfer panel and TransferContext are built on top of these events.
Watcher and auto-upload
src-tauri/src/core/watcher.rs handles local file watching.
A typical flow is:
- The frontend chooses Open on a remote file from the file explorer
- The backend downloads it into a local temp directory and starts watching it
- After the local file is saved, a
file-modifiedevent is emitted - The frontend decides whether to open the auto-upload window or upload immediately when the user previously chose an always-upload behavior
This flow involves:
cmd/watcher.rscore/watcher.rs- Frontend
FileUploadPage.tsx
Cloud sync / portable snapshot
src-tauri/src/core/cloud_sync.rs owns the runtime behavior for this capability, including:
- startup sync checks
- manual push / pull
- debounced auto-push
- scheduled backups
- remote backup listing and restore
- conflict detection and event emission
The frontend reaches it through src-tauri/src/cmd/cloud_sync.rs, which exposes commands such as:
test_cloud_sync_connectionget_cloud_sync_statussync_push_nowsync_pull_nowrun_cloud_backup_nowlist_cloud_sync_historylist_remote_backupsrestore_remote_backupresolve_cloud_sync_conflict
src-tauri/src/core/portable_snapshot.rs defines which data belongs in a portable snapshot. That matters because it controls:
- which settings are suitable for cross-device sync
- which data should remain local to the device
- how backup snapshots differ in scope from sync snapshots
In the current implementation, portable snapshots cover connections, credential config, OTP, proxies, tunnels, quick commands, and most application settings; they do not blindly roam all live UI state.
Configuration and encryption
Configuration and records are stored in ~/.nyaterm/nyaterm.redb and are mainly managed by src-tauri/src/storage.rs and src-tauri/src/config/. When upgrading from Dragonfly, NyaTerm copies ~/.dragonfly/dragonfly.redb; if the old environment only has .dragonfly JSON / text files, they are copied and imported into redb. The old directory is not deleted.
Primary redb documents include:
- JSON documents:
settings,sessions,keys,passwords,otp,quick-command,tunnels,proxies,history,cloud-sync-state - Text documents:
known_hosts,master.key
Sensitive fields are encrypted before being written, so when adding new configuration you should verify whether it crosses a sensitive-data boundary.
For cloud sync specifically, also pay attention to:
- provider credential fields going through encrypt / mask / merge handling
- runtime state being stored separately in the
cloud-sync-statedocument - history mainly being reconstructed from structured logs and then exposed through
list_cloud_sync_history
Event model
The backend relies heavily on Tauri events to notify the frontend. Typical events include:
| Event | Description |
|---|---|
terminal-output-{id} | Terminal output |
cwd-changed-{id} | Working directory changed |
session-closed-{id} | Session closed |
sessions-changed | Session list changed |
connections-changed | Saved connections changed |
transfer-event | Transfer progress |
otp-request | OTP / keyboard-interactive authentication requested |
cloud-sync-status-changed | Cloud sync / backup status changed |
cloud-sync-history-changed | Sync / backup history changed |
cloud-sync-conflict | Cloud sync conflict preview |
When designing new backend features, prefer exposing them through the existing event flow where appropriate rather than introducing extra polling APIs.