8000 GitHub - wrolp/wrolp: A Rust-powered desktop SSH terminal and server-ops tool — multi-tab, SFTP, remote editor, session recording, Docker analysis & AI assistant · GitHub
[go: up one dir, main page]

Skip to content
wrolpPublic

About

A Rust-powered desktop SSH terminal and server-ops tool — multi-tab, SFTP, remote editor, session recording, Docker analysis & AI assistant

Topics

Resources

Stars

9 stars

Watchers

0 watching

Forks

Repository files navigation

Wrolp Terminal

Wrolp Terminal

A Rust-powered desktop SSH terminal and server-ops tool

Release License Platform Built with Tauri

中文文档 · English

Wrolp Terminal is a Tauri 2 + React 19 + TypeScript desktop terminal client for SSH, Telnet and serial (COM) ports. The native backend is written in Rust and connects directly to remote servers using the pure-Rust async russh library. File transfer and remote editing use russh-sftp. Windows is the primary target — the release bundle target is MSI only — but the app runs and can be developed on Linux/macOS too.

Note: This README tracks the current state of the code, not a roadmap. When in doubt, trust the code.

✨ Highlights

  • 🖥️ Multi-tab SSH terminal with xterm.js, password/key auth, and a keepalive-driven health indicator
  • 🔌 Telnet & serial (COM) — plain-TCP sessions with IAC negotiation, and serial ports with auto-detected baud rate
  • 🔀 SSH tunnels — save local port-forwarding rules per connection and start/stop them from the sidebar
  • 💻 Local terminal — open shells on your own machine and browse local files, side by side with remote tabs
  • 📂 SFTP file manager — upload/download with pause & resume, remote file tree
  • ✍️ Remote file editor (Monaco) with UTF-8/GBK encoding auto-detect
  • 🔍 Hex & image viewer — inspect binary files as a hex dump or preview images directly
  • 🎬 Session recording to per-session NDJSON files, replayable from the bottom panel
  • 🌐 Built-in FTP / HTTP / TFTP tools — serve or fetch files without leaving the app
  • 🐳 Docker & host analysis — inspect containers, stream logs, analyze servers
  • ☸️ Kubernetes panel — contexts and namespaces, ten resource kinds, pod logs and exec, port-forwards, Helm releases
  • 🌿 Git panel — status, diffs, history graph, branches, fetch / pull / push, conflicts, stash, blame, clone and repository scan
  • 🤖 AI assistant with tool-calling agent mode, multimodal input, and encrypted API-key storage
  • 🗄️ Portable data folder — move all app data anywhere and monitor / shrink wrolp.db from Settings
  • 🪟 Floating panes & split layout — split the terminal area any way you like and pop panes out into independent floating windows
  • 🪟 Polished UX — custom titlebar, window geometry persistence, auto-updater

📸 Screenshots

Home

Wrolp Terminal - Home tab with connections, recent hosts and tools

SSH session

Wrolp Terminal - SSH session on Ubuntu 24.04

SFTP file browser

Wrolp Terminal - SFTP file panel beside the terminal

New connection dialog

Wrolp Terminal - New connection dialog

Features

SSH terminal

  • Connection management: CRUD connection profiles, grouping, drag-to-reorder, rename groups. Right-click a connection for connect / edit / delete and split-pane open (right / below); deletes use an in-app confirmation dialog (ConfirmDialog), not a browser confirm().
  • Interactive terminal: xterm.js rendering per tab, multi-tab switching.
  • Authentication: password and SSH key authentication.
  • PTY: xterm-256color PTY + shell, resize support.
  • Connection health: an SSH-level keepalive (interval + max retries, configurable in Settings) drives the tab status dot — green → yellow (connection-suspect) on a failed probe, red (connection-closed) once the retries are exhausted. A Reconnect button re-uses the same tab instance; a stale-task guard (session_id monotonic counter) prevents a superseded background task from corrupting state.
  • Working directory sync: SFTP operations stay in sync with cd typed in the shell (poll_working_dir runs pwd on a throwaway exec channel).
  • cd directory suggestions: while the input line reads cd <partial path>, a dropdown under the caret lists the path's real subdirectories (read through the session itself — SFTP / local FS / docker exec / WSL). ↑↓ move, Tab drills one level deeper, Enter completes without submitting (a second Enter actually runs cd), Esc closes. cd C: on a local Windows shell lists drives. Toggle in Settings → Terminal or the terminal's right-click menu; sessions without a filesystem (Telnet, serial) stay excluded.
  • Network scanning: scan a subnet for hosts with an open SSH or Telnet port and create a connection straight from the results (network_scan.rs).

SSH tunnels

  • Save local port-forwarding rules on a connection (TunnelConfig) and manage them from the sidebar — add, edit, delete, start, stop.
  • Each saved rule shows its local address and remote target and is marked active while forwarding.
  • The backend emits tunnel-changed whenever a tunnel starts, stops or dies, so the sidebar stays in sync (including after a tab disconnects).

Telnet

  • Plain-TCP sessions (connect_telnet) with a small built-in IAC negotiation state machine (ECHO / SGA / TERMINAL-TYPE / NAWS).
  • Window resizes are reported to the server through the NAWS sub-option (Telnet has no PTY).
  • Optional best-effort auto-login that matches login: / Password: prompts — off by default, since Telnet is unencrypted.

Serial port (COM)

  • Enumerates available ports with friendly names (USB manufacturer / product, VID:PID); pick one from the list or type a custom port name.
  • Configurable baud rate, data bits, stop bits, parity and flow control; the baud rate can also be picked from a dropdown of common values.
  • Baud-rate auto-detection: UART has no clock line and no negotiation, so the peer's real rate cannot be read. The backend instead probes each common rate, listens (nudging silent devices with a newline) and scores how much the received bytes look like terminal text — results come back ranked with a confidence score and a sample preview.

SFTP file management

  • Remote file tree browser (sidebar FilePanel).
  • List / read / write / rename / delete / create directories.
  • Upload and download (file or raw bytes), with pause / resume support and transfer-progress events.
  • Transfer queue (transferQueue.ts): every file has its own row with bytes done / total and a live speed, in the file panel and in the bottom drawer. Directory and drag-dropped uploads are scanned once with walkdir on the Rust side and stream over one shared SFTP connection, ticking progress per 4 MiB chunk — so a single multi-GB file shows a moving bar and speed instead of jumping from 0 % to done.
  • Cancelling an upload removes the half-written files it created on the remote, so the directory does not fill up with unusable truncated copies. Files that finished before the cancel are kept, and a destination that already existed is never deleted (the upload truncated it, so deleting it would destroy the original).
  • Switching the SFTP user (switch_sftp_user / revert_sftp_user) to operate as a different account.

Remote file editor

  • Monaco-based inline editor for remote files, shown as a split-tree pane or a floating window.
  • Encoding auto-detect: UTF-8 → GBK (encoding_rs); non-UTF-8 files are flagged and must be re-saved in the same charset.

Local terminal & local files

  • Open a local shell as a top-level tab or as a split pane inside an existing workspace (openLocalShellTab / handleOpenLocalSplit); runs a native shell on your own machine.
  • Local file browser: navigate and edit files on the local machine through the same FilePanel / FileEditor UI. A LocalFs (local_fs.rs) implements the same RemoteFs trait as SFTP, so local and remote targets share one code path. On Windows the local root maps to the current drive's root.

Hex & image viewer

  • Binary files opened in the editor can be viewed as a hex dump (hex_base64 + HexViewer.tsx).
  • Image files are previewed inline; the backend reports the MIME type via image_mime / detect_image_mime.

Network file tools

  • Opened from the Network tools mode in the activity rail (or the Network file tools button in the titlebar); it docks in the mode column rather than floating over the window, so it can stay open next to a terminal. Everything runs inside the app, so no external client is needed.
  • FTP server — share a local folder over FTP (PASV / EPSV).
  • HTTP/HTTPS file server — serve a folder with a built-in page for browsing and uploading; HTTPS can use a self-signed certificate generated with one click.
  • TFTP server — minimal TFTP serving for legacy / PXE equipment.
  • FTP client — connect to a remote FTP server (no TLS, explicit or implicit) and browse, upload and download files.
  • TFTP client — get / put single files over TFTP.

Floating panes & split layout

  • The terminal area is a split-tree layout (splitTree.ts): tabs can be split horizontally or vertically, and each leaf shows a terminal, a docker-log, or an open file editor.
  • Any pane can be popped out into a floating window (floatPane / FloatingWindow.tsx, position: fixed, z-index starting at 1000). Terminal floats detach the leaf from the tree (the session stays alive); file-editor / docker-log floats render as an overlay above the still-mounted shell and restore shellView on close.
  • Per-session view state (shellView / activeEditorKey are Record<number, ...>) keeps each tab's open files and docker logs isolated — files opened in one session don't appear in another.

Session recording

  • Recording is off by default. Turn on auto-recording in Settings, or force it globally with the env var WROLP_RECORDING=1 / true (0 / false forces it off).
  • Events are buffered in memory and appended every 5s (and on disconnect) to one NDJSON file per session: <data dir>/recordings/<workspace>/<group>/<connection>/<YYYYMMDD-HHMMSS>_<session8>.jsonl. The SQLite sessions table only keeps the index (events_file, event_count, plus a workspace/group snapshot), which keeps wrolp.db small.
  • Two event kinds: input (raw keystrokes) and command (full command line captured on Enter, preserving tab-completed text).
  • Browser in the bottom panel (SessionListPanel / SessionViewer): each row shows its workspace / group breadcrumb, can be revealed in the file manager, exported as asciinema v2 (.cast), replayed or deleted.
  • Maintenance actions: one-click migration of legacy recordings still 8000 stored in session_events, and rescan which rebuilds the index from the recordings/ folder (dropping empty orphan files).

Command sets

  • Save reusable groups of commands (optionally scoped to a connection) in SQLite.
  • Managed via CommandSetPanel in the bottom panel.

Docker & host analysis

  • Two daemons, one command surface. Every Docker feature runs against a DockerHostRef: either {kind:'ssh', jumpTabId} — a container on the jump host of a connected SSH session, reached with docker exec over the exec channel — or {kind:'local'}, this machine's own daemon, reached by spawning the CLI directly (no shell, so --format templates and container names need no quoting). probe_local_docker decides whether the local half exists at all: it tries docker, then podman, and distinguishes "not installed" from "installed but the daemon is not running"; with DOCKER_HOST set only docker is tried, since podman would answer for a different endpoint. The sidebar has one Docker group, and its host follows the focused terminal: a local shell — or no terminal at all — reads this machine, a connected SSH / Telnet session reads that host. Serial has no shell to exec in, so the group is absent there.
  • List, start / stop / restart / remove, one-shot and streaming logs, the three-layer analysis report, container file browsing and entering a container's shell all work on both hosts. The shells get there differently: a jump-host container opens a new pane of that session with docker exec -it … typed into it (persisted as postConnectCmd, so a reconnect re-sends it), while a local one runs the exec as its own PTY (open_local_docker_shell, which picks bash when the image has it and sh otherwise).
  • A log view normally rides the focused pane and the Files panel is normally a session section, but the group needs no session when its host is this machine — so neither action asks for one. With no pane on screen 「View Logs」 opens the log as a tab-bar entry that takes the main area (like a Settings tab), and opening a container's files shows the Files section over an empty workspace (only the Docker mode is offered there; SSH and ProxyJump point at a session).
  • analyze_host: read-only analysis of a connected server (OS, kernel, arch, packages, installed tools).
  • analyze_docker_container + docker_container_logs: inspect containers and stream their logs (docker_logs_stream_start / poll_docker_logs / stop_docker_logs_stream).
  • Docker log tabs & floating: a container's logs can be opened as a dedicated log tab and popped out into a floating window. When a tab reconnects, its postConnectCmd (e.g. the original docker exec) is re-sent automatically so the pane stays consistent across reconnects.
  • command_help: look up man-page / help text for a command on a connected server.
  • UI panels: DockerPanel, DockerLogViewer, DockerAnalysisPanel, HostAnalysisPanel.

Kubernetes

  • The K8s mode in the activity rail follows the focused terminal the same way Docker does: a K8sHostRef is either {kind:'ssh', jumpTabId} — kubectl runs on the jump host of a connected SSH session — or {kind:'local'}, this machine's own CLI and kubeconfig. Context and namespace are pickers at the top of the panel, and the row list is filtered by a search box. All namespaces is the default (switching contexts resets to it), so trouble in a namespace the kubeconfig does not name is visible immediately. In that mode the namespace label under each name is tinted with a stable colour derived from the namespace, so rows from different namespaces can be told apart at a glance.
  • Ten resource kinds share one generic row shape (K8sResource) in src-tauri/src/k8s_host.rs: pods, deployments, statefulsets, daemonsets, services, ingresses, jobs, cronjobs, configmaps and secrets. Each row carries its status chip, ready/total, restart count and a one-line summary; a pod's summary is its image and the node sits on its own line underneath.
  • Per row: view / edit the manifest YAML and apply it (k8s_apply_yaml), scale deployments and statefulsets, delete with an in-app confirmation, and open pod logs (one-shot or streaming with ANSI colour) or a shell inside the pod — locally as its own PTY shell, on an SSH host as a split pane that types kubectl exec for you.
  • Port-forwarding: forward a pod/service port, see live forwards in the panel and reuse saved rules; the backend reports forwards over the same event channel the terminal uses, so a closed tab cannot leave an orphan forward behind.
  • Helm: helm_probe says whether the CLI exists; the Helm tab lists releases in the namespace, shows values and revision history, and rolls back or uninstalls a release.

Git panel

  • The Git mode in the activity rail manages one repository at a time on the focused host — an SSH session through its exec channel, or this machine when no session is focused — with one UI and one command surface (src-tauri/src/commands/git.rs).
  • Everything is the real git CLI (no bundled library): remote calls run env LC_ALL=C GIT_TERMINAL_PROMPT=0 … bash -lc '<quoted command>' over a fresh exec channel, local calls spawn git directly with HideConsole. git_probe finds the binary, including the usual Windows install paths.
  • Status (porcelain v2), diffs (2 MB cap), paged history, branches and remotes; stage / unstage / discard / commit (with amend), branch create / switch / delete, abort merge or rebase, and git init for a plain folder.
  • Fetch / pull / push stream git-progress events, can be cancelled with git_cancel, and pull is --ff-only — a non-fast-forward ends as git_not_fast_forward with a hint to merge in the terminal. A forced push exists only as --force-with-lease and always asks first.
  • History shows a commit-graph lane column; expanding a commit lists its changed files, and a file opens its commit-scope diff. A read-only blame view is available per tracked file.
  • Conflicts: the panel lists unmerged paths, offers ours / theirs / mark-resolved, a read-only three-way view (base / ours / theirs), and aborts an in-progress merge, rebase, cherry-pick or revert.
  • Stash (push / pop / apply / drop), clone with progress, remote add / remove, git init, a bounded repository scan from the picker, and local ignore that appends to .git/info/exclude instead of editing the tracked .gitignore.
  • git.localBin (Settings registry) pins the local executable when a GUI process has no Git in PATH; the picker's "git not installed" state accepts the path inline.
  • Paths never reach a shell: remote arguments are quoted one by one, and the backend rejects absolute paths, drive letters, backslashes and ...

AI assistant

  • Chat panel (AiChatPanel) with two modes:
    • Chat (non-streaming ai_chat_sync).
    • Agent (streaming with tool calling, run_agent_stream) — a full agent loop that can call tools on the connected servers.
  • Two separate chats: the inspector column's AI tab is the app-level conversation — it belongs to no terminal, opens with zero sessions running, and the backend refuses every shell tool for its runs. Terminal-bound help lives in each pane's own docked AI, where run_command, file reads and Send to terminal are available.
  • Multimodal input: attach images to a message (the backend accepts content as structured multi-part via openai_content), so the model can reason about screenshots, diagrams, etc. Images can also be pasted straight into the chat input; click a thumbnail for a full-size preview.
  • Send to terminal: send AI-generated code blocks or selected text to the active pane, routed by connection type (SSH, local shell, serial, Telnet). The text is inserted without being executed, so you can review it first.
  • Templates & re-send: insert prompts from a template dropdown next to the image button; edit and re-send any previous message (re-runs from the edited content).
  • Pause: abort an in-flight agent/chat generation with cancel_ai_chat and continue from where it stopped.
  • Multiple API endpoints: save several AiEndpointProfiles, each with its own encrypted API key, endpoint URL, model, and system prompt. Select/apply one active profile. Legacy single-endpoint configs are migrated automatically.
  • Model fetching: list_ai_models calls {endpoint}/v1/models to populate the model dropdown; manual entry is always available.
  • Agent tools (dispatched to the Rust backend, which has AppState access): run_command, analyze_server, list_directory, read_file, list_connections, search_help, and more. Tool calls are grouped under their assistant message and surfaced as tool cards with lifecycle events (pending → executing → done/error). Bash code blocks in assistant messages get a one-click copy button.
  • Security: API keys are encrypted at rest via an AES-256-GCM file vault (encrypt_api_key / decrypt_api_key). The encryption key is a machine-specific file (vault.key); no OS keyring is used.

Data folder & database

  • Relocatable data folder: pick any directory in Settings → Data and wrolp.db, recordings/, connections.json and the window config all move there. The choice is stored in a data_root.json anchor (kept in the default location) and applied on the next launch, which copies the data over when the target is empty and otherwise uses what is already there — nothing is overwritten.
  • Vault key option: optionally carry vault.key along with the data folder on the next migration, making the folder portable as a whole. Off by default, so the key stays machine-anchored.
  • Database maintenance: Settings shows the current wrolp.db size and how much of it is reclaimable, with a Shrink now action (VACUUM). Deleting sessions or migrating legacy recordings also releases the freed pages automatically once the freed space is worth a rewrite, so the database no longer keeps its old size after data is removed.

Window & shell integration

  • Custom titlebar (window decorations: false); window geometry/opacity persisted (window.json).
  • Auto-updater (GitHub release endpoint — set a real pubkey in tauri.conf.json before shipping).
  • Persistent connection configs (connections.json, encrypted — it also stores workspaces) and SQLite DB (wrolp.db, WAL mode) under the OS config dir + wrolp-terminal/.

Keyboard shortcuts

  • Every combination key the app binds lives in one table (src/lib/keybindings.ts), and Settings → Shortcuts edits it: click a row's key, press a new combination, and the next keystroke obeys it. Search matches either the action or the combo.
  • A binding matches exactly, modifiers included — Ctrl+B does not also fire on Ctrl+Alt+B. Each row can be unbound, restored on its own, or reset as a whole; overrides persist in localStorage.
  • Keys the shell or the system cannot do without (Tab, Enter, Ctrl+C/V/X/Z/D/W) are refused, and readline's other control keys bind with a visible warning that they stop reaching the shell. Tab in particular stays the shell's completion key everywhere.
  • Defaults: Ctrl+K palette · Ctrl+Shift+P snippet list · Ctrl+Shift+H command history · Ctrl+Shift+F dual-pane files · Ctrl+B / Ctrl+Alt+B sidebar · Ctrl+J / Ctrl+Alt+J panel · Ctrl+Alt+I inspector · Ctrl+\ split · Alt+/ completion · Shift+PgUp/PgDn/Home/End scrollback · Ctrl+S save · Esc close pop-up.

System Dependencies

Linux (Debian/Ubuntu)

sudo apt-get install -y pkg-config libdbus-1-dev libssl-dev libgtk-3-dev libjavascriptcoregtk-4.1-dev libsoup-3.0-dev libwebkit2gtk-4.1-dev

macOS / Windows

No extra dependencies.

Installation

1. Install Rust Toolchain

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

2. Install Frontend Dependencies

yarn.lock is committed, so prefer yarn:

yarn        # or: npm install

Development

yarn tauri dev      # or: npm run tauri dev

Tauri 2 auto-starts the Vite dev server via beforeDevCommand before loading the frontend.

Frontend-only dev server (no Rust/SSH — useful for UI work):

yarn dev

Debugging the Rust backend

  • Logging: backend diagnostics use eprintln! to stderr (visible in the yarn tauri dev terminal). Add eprintln!("[module] ...") where needed.
  • Static checks / tests:
    cd src-tauri
    cargo check                 # type-check
    cargo build                 # debug build
    cargo clippy                # lints
    cargo test                  # all Rust unit tests
    cargo run --bin ssh_test    # standalone russh connectivity probe (src/ssh_test.rs)
  • Breakpoints: a .vscode/launch.json (Debug Tauri (dev), CodeLLDB extension) builds and launches the binary with RUST_BACKTRACE=1. Note it launches a standalone process — don't also run yarn tauri dev simultaneously. For most backend work, eprintln! logging via yarn tauri dev is the usual workflow.
  • Gotchas: terminal output is polled (poll_output) not event-streamed; new #[tauri::command]s require a backend rebuild (restart yarn tauri dev).

Build

yarn build:clean     # cleans its own target dir first, then builds — use this for a shippable bundle
yarn tauri build     # incremental dev build into src-tauri/target/

build:clean builds into src-tauri/target-release/ (bundle at src-tauri/target-release/release/bundle/), so cleaning never fights rust-analyzer or a running dev build over files in src-tauri/target/ — on Windows that lock makes cargo clean fail with os error 5. Bundle target is ["msi"] only.

After a successful build only target-release/release/ is kept: debug/, tmp/ and cargo's .fingerprint cache are deleted to reclaim disk, so the next release compiles the dependency tree again. Set RELEASE_KEEP_TARGET=1 to keep them (useful while iterating on the packaging steps).

Clean Rebuild

yarn clean           # dev output: cargo clean + remove dist/
yarn tauri build

yarn clean is the dev-side clean and needs src-tauri/target/ to be unlocked (close the app, or restart rust-analyzer, if Windows reports access denied). Releases never touch that directory.

Release

gh auth login -h github.com

yarn run publish

publish wipes its own target dir (src-tauri/target-release) and only then builds, so a release bundle never inherits objects — icons above all — from an earlier build, and the clean cannot be blocked by locks in the dev target. Once the build succeeds, everything under that dir except release/ is pruned to reclaim disk. Set RELEASE_SKIP_CLEAN=1 to reuse the existing output while iterating on the packaging steps.

Testing

Rust unit & integration tests

cd src-tauri
cargo test                 # run all Rust unit tests (#[cfg(test)] in local_fs, ai_term, …)
cargo run --bin ssh_test   # standalone russh connectivity probe binary
  • Backend unit tests live inside each module (e.g. local_fs.rs, ai_term.rs) using #[cfg(test)] + #[tokio::test], covering pure logic (path parsing, protocol (de)serialization, RemoteFs adapters, config validation, …).
  • Prefer adding unit tests for pure-logic features; for real network/process behaviour use a standalone binary such as ssh_test as a smoke probe.

Frontend E2E (Playwright + mocked IPC)

E2E is powered by Playwright, Phase 1: the Vite frontend (yarn dev) runs in a real browser, and the Tauri backend is stubbed by injecting a fake window.__TAURI_INTERNALS__ (see e2e/ui/helpers/tauriMock.ts) — no Rust build required to verify the UI.

# install Playwright browsers on first run
npx playwright install

# run all E2E
yarn test:e2e              # equivalent to npx playwright test

# custom port (CI, or when 1420 is already taken locally)
E2E_PORT=1430 yarn test:e2e
  • Specs live in e2e/ui/ (e.g. terminal.spec.ts, connections.spec.ts, command-list.spec.ts, app-boot.spec.ts).
  • The backend stub lives in e2e/ui/helpers/tauriMock.ts: it returns fixed/parameterised responses keyed by the invoke command name, so frontend behaviour can be verified without a real SSH server / file server.

Tech Stack

  • Frontend: React 19 + TypeScript + xterm.js + Monaco editor + Vite + SCSS
  • Backend: Tauri 2 + Rust (tokio) + russh / russh-sftp
  • SSH: pure-Rust russh async SSH client
  • IPC: Tauri invoke commands + frontend polling for terminal output (Windows background-task workaround). Tauri events are used only for the few push notifications the UI cannot poll: connection-closed, connection-suspect, connection-ok, transfer-progress, tunnel-changed, ai-term-mark, native-drag-drop, baud-detect-progress.
  • Storage: everything lives under one relocatable data folder — window.json (window geometry, opacity, recording and keepalive settings), an encrypted connections.json (connections and workspaces), wrolp.db (SQLite, WAL: session index, command sets, snippets) and recordings/ (per-session NDJSON event files); encrypted secrets via an AES-256-GCM file vault (no OS keyring).

Conventions

  • Types shared with Rust use #[serde(rename_all = "camelCase")] on the Rust side and matching camelCase interfaces in src/types.ts.
  • Frontend formatting is enforced by Prettier (.prettierrc: singleQuote, no semi, printWidth 100) — run yarn format.
  • Backend commands live in focused submodules under src-tauri/src/commands/ (e.g. serial.rs); a new command must also be registered in the generate_handler! list in src-tauri/src/lib.rs, and its frontend wrapper goes in src/commands.ts.

License

Released under the MIT License (Copyright (c) 2026 Wrolp). In short:

  • You may freely use, copy, modify, merge, publish, distribute, sublicense and sell copies of this software, including for commercial purposes.
  • The copyright notice and this license notice must be included in all copies or substantial portions of the software.
  • The software is provided "as is", without warranty of any kind, express or implied; the authors or copyright holders are not liable for any claim, damages or other liability.

Acknowledgements

  • russh — pure-Rust async SSH client
  • Tauri — the app framework
  • React — UI library
  • xterm.js — terminal rendering
  • Monaco Editor — code editor
  • …and many other open-source libraries that make this project possible.

About

A Rust-powered desktop SSH terminal and server-ops tool — multi-tab, SFTP, remote editor, session recording, Docker analysis & AI assistant

Topics

Resources

Stars

9 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

0