ctty Logo

# πŸš€ ctty - Connection Manager [English](README.md) | [δΈ­ζ–‡](README_CN.md) [![Go](https://img.shields.io/badge/Go-1.23+-00ADD8?style=for-the-badge&logo=go)](https://golang.org/) [![Release](https://img.shields.io/github/v/release/zsuroy/ctty?style=for-the-badge)](https://github.com/zsuroy/ctty/releases) [![License](https://img.shields.io/github/license/zsuroy/ctty?style=for-the-badge)](LICENSE) [![Platform](https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20Windows-lightgrey?style=for-the-badge)](https://github.com/zsuroy/ctty/releases) > **A lightweight, all-in-one connection manager β€” SSH, serial, telnet, SFTP, FTP, WebDAV, and S3 in a single TUI** πŸ”₯ ctty is a fast, native terminal tool for managing all your connections β€” SSH hosts, serial devices, telnet endpoints, SFTP file transfers, FTP sites, WebDAV servers, and S3 object storage β€” without the overhead of Electron apps. Built with Go and featuring an intuitive TUI interface, it brings the convenience of GUI connection managers like Tabby to the terminal, with zero bloat. **Why ctty?** - **Tabby too heavy?** ctty is a single ~5MB binary, no Electron, no browser engine β€” just pure Go - **Need serial + telnet + SFTP + FTP + WebDAV + S3 + SSH in one tool?** Most terminal emulators only do SSH; ctty covers them all in a single binary β€” serial/telnet/FTP/WebDAV/S3/SFTP are built in, SSH reuses your system OpenSSH - **Want to stay in the terminal?** No context switching between apps β€” everything is keyboard-driven

Demo ctty Terminal
πŸ–±οΈ Click on the image to view in full size

## ✨ Features ### πŸš€ **Core Capabilities** - **🎨 Beautiful TUI Interface** - Navigate your SSH hosts with an elegant, interactive terminal UI and zero vertical layout jitter - **⚑ Quick Connect & Health Peek** - Connect instantly with `Enter` or inspect real-time system metrics (uptime, CPU load, memory bar, root disk space) via **Quick Peek** (`v` / `P`) without opening a full shell - **πŸ“¦ Multi-Select & Batch Exec** - Press `Space` to multi-select hosts with visual `[ ]` / `[βœ“]` checkboxes, `Ctrl+A` to select all, `p` to probe selected hosts, `y` to copy commands, and `x` to batch-execute remote snippets in parallel with an aggregated scrollable results modal - **πŸ”„ Unified Cross-Protocol Navigation** - Switch between SSH, Serial (`t`), Telnet (`T`), FTP (`F`), WebDAV (`W`), S3 (`O`), and Local File Browser (`b`) directly via hotkeys or `[` / `]` tabs without leaving your current view - **🏷️ Tag Organization & Quick Drawer** - Organize hosts with automatic color-coding (e.g., `#prod` in red, `#dev` in green); press `w` to open an interactive Tag Drawer with host counts and 1-key filtering (`1`-`9`), or use `hidden` tag to hide sensitive hosts - **πŸ“ Direct Config Editing** - Press `E` to open your active SSH configuration directly in `$EDITOR` / `$VISUAL` (vim, nano, notepad) with automatic live config reload upon exit - **πŸ“‹ Universal Clipboard** - Copy commands (`y`) seamlessly across local terminals, remote SSH sessions, and tmux via OSC 52 fallback - **πŸ”„ Port Forwarding** - Easy setup for Local, Remote, and Dynamic (SOCKS) forwarding with history persistence - **πŸ“ Easy Management** - Add, edit, move, and manage SSH configurations seamlessly; typing in search and pressing `a` auto-fills the host name - **πŸ” Smart Search** - Find hosts quickly with real-time filtering across names, addresses, and `#tags` - **πŸ“ Real-time Status** - Live SSH connectivity indicators with latency gradient colors (🟒 <100ms, 🟑 100-300ms, πŸ”΄ >300ms / offline) - **πŸ”Œ Serial Connections** - Manage and connect to serial devices (mcu, console, switch, router) with configurable baud rate, data bits, parity, and stop bits; auto-detected ports appear in the list instantly - **πŸ“‘ Telnet Connections** - Native RFC 854 telnet client (no system telnet needed): save and manage lab equipment, console servers, and legacy devices; reachability probe with one keypress - **πŸ“‚ SFTP File Transfer** - Full-featured SFTP browser (`o` key) with remote browsing, upload/download queue with progress and cancel, transfer bell (`\a`), search, mkdir/delete, plus headless CLI transfers (`put`/`get`/`scp` + `sftp ls/mkdir/rm/rmdir/rename`) - **πŸ“ FTP Site Manager** - Plain-FTP support (`F` key) for hosts without SSH: tagged site inventory, dual-pane local|remote browser, mkdir/delete/rename in both panes, single/dual layout toggle, passwords in the encrypted vault, plus headless CLI transfers (`ftp ls/get/put/mkdir/rm/rmdir/rename`) - **🌐 WebDAV Site Manager** - WebDAV support (`W` key) for cloud storage (Nextcloud, ownCloud, NAS, Apache/Nginx WebDAV): tagged site inventory, dual-pane browser, directory recursion, single/dual layout toggle, passwords in the encrypted vault, plus headless CLI operations (`webdav ls/get/put/mkdir/rm/rmdir/rename`) - **☁️ S3 Object Storage** - S3 & S3-compatible object storage support (`O` key) for AWS S3, MinIO, Cloudflare R2, Aliyun OSS, and Ceph: tagged site inventory, dual-pane browser, bucket/prefix navigation, mkdir/delete/rename in both panes, upload/download queue with progress, single/dual layout toggle, secret keys in the encrypted vault, plus headless CLI operations (`s3 ls/get/put/mkdir/rm/rename`) - **πŸ—‚οΈ Local File Browser** - Standalone local filesystem manager (`b` key or `ctty browse [path]`): navigate, search, sort, mkdir/delete/rename with confirms, file details, open-with-default-app, reveal in file manager - **πŸ”‘ Password Storage & Zero-Touch Auto-Login** - Save SSH passwords securely in a local AES-256-GCM encrypted vault (`~/.config/ctty/credentials.json`, `0600` permissions) with native OpenSSH `SSH_ASKPASS` protocol bridge (zero third-party dependencies, works on macOS, Linux, Windows, and Termux) - **πŸ–₯️ Split-Pane & Small Terminal Friendly** - All forms and dialogs (Add/Edit Host, Port Forwarding, Host Info, Help Menu, Quick Peek, Batch Exec) feature focus-following dynamic viewport scrolling with fixed headers/footers. Works flawlessly in tmux/Zellij splits, VS Code/JetBrains embedded terminals, and tiling WMs (i3/Sway) down to 8~12 lines with zero height blocking or truncation - **🌐 Bilingual i18n & Settings UI** - Full English and Simplified Chinese support with automatic OS detection (macOS, Windows, Linux, Termux) and interactive in-TUI Settings menu (`S` key) to configure language, updates, and keybindings ### πŸ› οΈ **Technical Features** - **πŸ”’ Secure** - Works directly with your existing `~/.ssh/config` file (credentials stored separately, never pollutes standard SSH configs) - **πŸ“ Custom Config Support** - Use any SSH configuration file with the `-c` flag - **πŸ€– Agent Skill & Headless CLI** - Agent skill for Cursor, Claude Code, and Codex; every operation available from the CLI without the TUI, with JSON output for scripts and agents - **πŸ“¦ Multi-App Host Import** - Migrate SSH profiles from Tabby, Termius, FinalShell, or generic JSON with `ctty import --from ` - **πŸ’Ύ Backup & Cross-Device Migration** - Back up and restore all configurations, sites, and credentials with AES-256-GCM encryption (`ctty backup` / `ctty restore`), or export connections with `ctty export` - **πŸ“‚ SSH Include Support** - Full support for SSH Include directives to organize configurations across multiple files - **βš™οΈ SSH Options Support** - Add any SSH configuration option through intuitive forms - **πŸ”„ Automatic Conversion** - Seamlessly converts between command-line and config formats - **πŸ”„ Automatic Backups** - Backup configurations automatically before changes - **βœ… Validation** - Prevent configuration errors with built-in validation - **πŸ”— ProxyJump/ProxyCommand Support** - Secure connection tunneling through bastion hosts - **⌨️ Keyboard Shortcuts** - Power user navigation with vim-like shortcuts and universal `Tab`/`Shift+Tab` focus cycling - **🌐 Cross-platform** - Supports Linux, macOS (Intel & Apple Silicon), Windows, and Android (Termux) - **⚑ Lightweight** - Single binary with no dependencies, zero configuration required ## πŸš€ Quick Start ### Agent Skill Teach Cursor, Claude Code, Codex, and other agents to **use** ctty (search hosts, run remote commands, list serial/telnet devices) without opening the TUI. This is separate from installing the `ctty` binary below. ```bash # Preview skills in this repo npx skills add zsuroy/ctty --list # Install into the current project (committed under .agents/skills/) npx skills add zsuroy/ctty -y # Install globally so every project can use it (recommended) npx skills add zsuroy/ctty -g -y ``` `-y` skips prompts. `-g` installs to your user global skills dir. Default without `-g` is project-local. ```bash npx skills list # see what is installed npx skills remove ctty # uninstall npx skills update ctty # pull the latest SKILL.md ``` The skill lives at [`skills/ctty/`](skills/ctty/) in this repository. ### Installation **Homebrew (Recommended for macOS):** ```bash brew install zsuroy/ctty/ctty ``` **Unix/Linux/macOS (One-line install):** ```bash curl -sSL https://raw.githubusercontent.com/zsuroy/ctty/master/install/unix.sh | bash ``` **Termux (Android):** ```bash curl -sSL https://raw.githubusercontent.com/zsuroy/ctty/master/install/unix.sh | bash ``` The installer auto-detects Termux (via `$PREFIX`/`$TERMUX_VERSION`) and installs to `$PREFIX/bin` without `sudo`. On Termux it picks the cgo Android build, whose DNS goes through the system resolver (pure-Go builds fail on devices with Private DNS or stub resolvers); releases without Android assets fall back to the Linux build. **Windows (PowerShell):** ```powershell irm https://raw.githubusercontent.com/zsuroy/ctty/master/install/windows.ps1 | iex ``` **Alternative methods:** *Linux/macOS:* ```bash # Download specific release wget https://github.com/zsuroy/ctty/releases/latest/download/ctty_Linux_x86_64.tar.gz # Extract and install tar -xzf ctty_Linux_x86_64.tar.gz # contains the single "ctty" binary sudo mv ctty /usr/local/bin/ctty ``` *Windows:* ```powershell # Download and extract Invoke-WebRequest -Uri "https://github.com/zsuroy/ctty/releases/latest/download/ctty_Windows_x86_64.zip" -OutFile "ctty_Windows_x86_64.zip" Expand-Archive ctty_Windows_x86_64.zip -DestinationPath C:\tools\ # Add C:\tools to your PATH environment variable ``` **From source (requires Go 1.23+):** ```bash git clone https://github.com/zsuroy/ctty.git cd ctty go build -o ctty . sudo mv ctty /usr/local/bin/ ``` ## πŸ“– Usage ### Interactive Mode Launch ctty without arguments to enter the beautiful TUI interface: ```bash ctty ``` **Navigation & Host Actions:** - `↑/↓` or `j/k` - Navigate hosts - `Enter` - Connect to selected host - `v` or `P` - **Quick Peek** host health stats (uptime, CPU load, memory %, disk % progress bars) - `Space` - **Multi-Select** toggle (auto-advances cursor down by 1 row) - `Ctrl+A` - Select all / deselect all visible hosts - `Esc` - Clear multi-selection (when active) or cancel/exit mode - `y` - Copy SSH command to clipboard (copies newline-separated commands for all selected hosts when multi-selection is active) - `x` - Remote command snippet execution (runs in parallel across all selected hosts when multi-selection is active) - `p` - Ping hosts to test latency (pings only selected hosts when multi-selection is active) - `w` - Open interactive **Tag Filter Drawer** (`1`-`9` or `Enter` to filter, `c` to clear) - `c` - Clear active tag filter - `E` - Open active SSH configuration file directly in `$EDITOR` (vim/nano/notepad) - `[` / `]` - Switch to previous / next protocol tab (SSH ⇄ Serial ⇄ Telnet ⇄ FTP ⇄ WebDAV ⇄ S3 ⇄ Local Browser) - `g` / `Home` - Jump to first row - `G` / `End` - Jump to last row - `1`-`9` - Quick jump to row - `a` - Add new host (auto-fills search query if typing) - `e` - Edit selected host - `d` - Delete selected host - `m` - Move host to another config file (requires SSH Include directives) - `i` - Show host configuration info - `f` - Setup port forwarding - `t` - Open serial device manager - `T` - Open telnet device manager - `o` - Open SFTP file browser for selected host - `F` - Open FTP site manager - `W` - Open WebDAV site manager - `O` - Open S3 object storage manager - `b` - Open local file browser - `S` - Open Settings & Preferences (Language, Updates, ESC behavior) - `U` - Open self-update modal (when an update is available) - `H` - Toggle hidden hosts visibility - `h` - Open help screen - `q` - Quit - `/` - Search/filter hosts **Real-time Status Indicators:** - 🟒 **Online** - Low latency (<100ms) - 🟑 **Moderate / Connecting** - Moderate latency (100-300ms) or checking connectivity - πŸ”΄ **Offline / High Latency** - Host unreachable, timeout, or latency >300ms - ⚫ **Unknown** - Connectivity status not yet determined **Sorting & Filtering:** - `s` - Cycle through all sort modes (**Name** βž” **Hostname** βž” **Tags** βž” **Last Login**) - `n` - Sort by **name** (alphabetical) - `r` - Sort by **recent** (last login time) - `Tab` - Switch focus between search input and table - Type to search - Real-time filtering across name, hostname, and `#tags` The interactive forms will guide you through configuration: - **Hostname/IP** - Server address - **Username** - SSH user - **Port** - SSH port (default: 22) - **Identity File** - Private key path - **ProxyJump** - Jump server for connection tunneling - **ProxyCommand** - Jump command for connection tunneling - **SSH Options** - Additional SSH options in `-o` format (e.g., `-o Compression=yes -o ServerAliveInterval=60`) - **Tags** - Comma-separated tags for organization ### Serial Connections Press `t` from the main TUI to enter the serial device manager. Available serial ports are auto-detected and listed immediately β€” no manual setup required for quick access. **Serial device list:** - Detected ports appear automatically with default settings (115200 8N1) - Saved devices (with custom names and settings) appear at the top - `Enter` - Connect to selected serial device - `i` - Show device info (name, port, baud, parity, etc.) - `a` - Add a new serial device with custom settings - `d` - Delete a saved serial device - `/` - Search/filter devices by name or port path - `Esc`/`q` - Return to SSH host list **Device info view:** - `e` or `Enter` - Edit parameters (baud rate, data bits, parity, stop bits) before connecting - `Esc`/`i` - Back to device list **Adding a serial device:** - **Name** - Friendly alias (e.g., `Switch-Console`) - **Device** - Port path (e.g., `/dev/cu.usbserial-1420`); use `←/β†’` to pick from detected ports - **Baud Rate** - Default: 115200 - **Data Bits** - 5, 6, 7, or 8 (default: 8) - **Parity** - `none`, `even`, or `odd` (default: `none`) - **Stop Bits** - 1 or 2 (default: 1) **Editing parameters before connect:** - Baud rate can be typed directly or cycled via `←/β†’` through presets (9600/19200/38400/57600/115200/230400/460800/921600) - Press `Enter` to connect with the modified parameters **Connecting:** The TUI suspends and bridges your terminal directly to the serial port. Press `Ctrl+]` to disconnect and return to the TUI. You can also launch the serial manager directly: ```bash ctty serial # Skip the SSH host list, go straight to serial devices ``` ### Telnet Connections Press `T` (Shift+T) from the main TUI to open the telnet device manager β€” for lab equipment, console servers, and legacy network gear that expose a telnet service. > ⚠️ **Cleartext protocol** β€” Telnet transmits everything, including passwords, unencrypted. Prefer SSH wherever the device supports it. **Telnet device list:** - `Enter` - Connect to selected telnet device - `i` - Show device info (name, host, port, user, tags) - `a` - Add a new telnet device - `e` - Edit the selected device - `d` - Delete a saved telnet device - `p` - Probe reachability of all saved hosts (TCP dial with 3s timeout; 🟒 up / πŸ”΄ down) - `/` - Search/filter devices by name, host, or tags - `Esc`/`q` - Return to SSH host list **Automatic login:** `a` / `e` can store a user name and password (password in the encrypted credential vault, same as SSH/FTP/WebDAV/S3). On connect, ctty auto-answers `login:` / `Username:` / `user:` / `login as:` and `Password:` / `passwd:` prompts (user name optional). It only matches real prompts at line end, answers each at most once with no retries, and falls back to manual input when unrecognized. Telnet is cleartext β€” this saves typing, not security. **Connecting:** The TUI suspends and bridges your terminal directly to the telnet session. Press `Ctrl+]` (classic telnet escape) to disconnect and return to the TUI. The client negotiates conservatively: it accepts ECHO / SGA / BINARY, refuses other options, and answers window-size queries with 80Γ—24. You can also connect without opening the manager: ```bash ctty telnet # Telnet device manager TUI ctty telnet core-sw # Connect to a saved device by name ctty telnet 192.168.1.1 # Direct connection (port 23) ctty telnet 10.0.0.5:2001 # Direct connection with explicit port ``` Saved devices live in `~/.config/ctty/telnet.json`, separate from your SSH config. ### SFTP File Transfer While selected an SSH host, press `o` to open the SFTP file browser. The SFTP interface provides a full-featured file transfer experience directly in your terminal: **SFTP Browser Features:** - Remote and local file browsing - Upload/download with progress and cancel - Search functionality (/ key) for both remote and local files - Two-line help for better readability - Clear [LOCAL] and [REMOTE] labels (no confusing emoji) - Error handling with friendly messages **SFTP Navigation:** - `↑/↓` or `j/k` - Navigate files - `β†’/l` or `Enter` - Enter directory / download file (remote) / upload file (local) - `←/h` or `Backspace` - Go to parent directory - `u` - Switch to local file browser for upload - `d` - Delete selected file (remote only) - `n` - Create new directory (remote only) - `r` - Refresh file list - `/` - Search/filter files - `Esc` - Cancel current operation / return to SSH session **Uploading Files:** 1. Press `u` to switch to local file browser 2. Navigate to the file you want to upload 3. Press `Enter` to upload to the current remote directory 4. Monitor progress in the status bar 5. Press `Esc` to cancel upload (returns to remote file list) **Downloading Files:** 1. Navigate to the file you want to download 2. Press `Enter` to download to your local download directory (`~/Downloads/ctty`) 3. Monitor progress in the status bar 4. Press `Esc` to cancel download (returns to remote file list) **Searching Files:** - Press `/` to enter search mode - Type to filter files by name (real-time filtering) - Press `Enter` or `Tab` to confirm selection - Press `Esc` to cancel search and restore full file list **Error Handling:** - If SFTP fails to start, you'll see a friendly error message: `❌ SFTP Error: failed to start SFTP session.` - Press `Esc` to return to the SSH session - Your SSH connection remains active for other operations You can also launch the SFTP file browser directly from the command line: ```bash ctty sftp prod-server # Open SFTP browser directly for a host ``` **Headless SFTP file ops:** ```bash ctty sftp ls prod-server # List remote directory ctty sftp ls prod-server /var/log --format json ctty sftp mkdir prod-server /tmp/newdir ctty sftp rm prod-server /tmp/file.txt ctty sftp rmdir prod-server /tmp/olddir ctty sftp rename prod-server /tmp/old.txt /tmp/new.txt # Transfers remain at root level: ctty put prod-server ./app.tar.gz /srv/app.tar.gz ctty get prod-server /var/log/app.log ./app.log ``` ### FTP File Transfer Press `F` (Shift+F) from the main TUI to open the FTP site manager β€” for plain-FTP hosts that don't speak SSH/SFTP (lab NAS boxes, legacy file servers, appliance uploads). > ⚠️ **Cleartext protocol** β€” FTP transmits everything, including passwords, unencrypted. Prefer SFTP wherever the server supports it. **FTP site manager:** - `Enter` - Open the dual-pane browser for the selected site - `a`/`e` - Add / edit a site (name, host, port, user, password, tags) - `d` - Delete the selected site (also removes its saved password) - `i` - Show site details (`e`/`Enter` jumps to edit) - `/` - Search/filter sites - `r` - Refresh the list - `Esc` - Back Saved sites live in `~/.config/ctty/ftp.json` (0600). Passwords are encrypted in the shared credentials vault (`~/.config/ctty/credentials.json`, FTP entries under `ftp:` names) β€” the same AES-256-GCM vault SSH passwords use. **FTP browser (dual-pane local | remote):** - `Tab`/`u` - Switch focus between local and remote panes - `↑/↓` or `j/k` - Navigate files - `β†’/l` or `Enter` - Enter directory / download file (remote downloads confirm first) - `←/h` or `Backspace` - Go to parent directory - `d` - Delete selected file (with confirm) - `n` - Create new directory - `R` - Rename selected file/directory - `i` - Show details of the selected file/directory - `v` - Toggle single/dual pane layout (persisted) - `r` - Refresh current directory - `/` - Search/filter files - `Esc` - Cancel transfer / go back File management (`n`/`d`/`R`) works in both panes and mirrors SFTP keybindings. The pane layout can also be set persistently via `S` Settings β†’ FTP browser layout. Narrow terminals (under 80 columns) always use the single pane. You can also open the site manager or a site browser directly: ```bash ctty ftp # FTP site manager TUI ctty ftp lab-nas # Open browser directly for a saved site ``` **Headless FTP transfers:** ```bash ctty ftp ls lab-nas # List remote directory ctty ftp ls lab-nas /pub --format json # Machine-readable listing ctty ftp get lab-nas /pub/file.txt ./file.txt ctty ftp put lab-nas ./file.txt /pub/file.txt ctty ftp mkdir lab-nas /pub/newdir ctty ftp rm lab-nas /pub/file.txt ctty ftp rmdir lab-nas /pub/olddir ctty ftp rename lab-nas /pub/old.txt /pub/new.txt ``` Progress is on stderr; directories are recursive; passwords are reused from the encrypted vault (`ftp:` names) or anonymous. ### WebDAV File Transfer Press `W` (Shift+W) from the main TUI or cycle tabs with `[` / `]` to open the WebDAV site manager β€” connect to Nextcloud, ownCloud, NAS servers, Apache/Nginx WebDAV, or any RFC 4918 compliant endpoint. **WebDAV site manager:** - `Enter` - Connect and open browser - `a` - Add WebDAV site (name, URL, username, optional password, insecure TLS toggle, tags) - `e` - Edit site - `d` - Delete site (with confirmation modal) - `Space` / `Ctrl+A` - Multi-select sites for batch deletion - `y` - Copy URL - `i` - Inspect site details - `p` - Probe connectivity - `w` - Filter by tag - `/` - Search sites Saved sites live in `~/.config/ctty/webdav.json` (0600). Passwords are encrypted in the shared vault (`~/.config/ctty/credentials.json`, WebDAV entries under `webdav:` names) using AES-256-GCM. **WebDAV browser (dual-pane local | remote):** - `Tab` / `Shift+Tab` - Toggle focus between local and remote pane - `Enter` / `l` / `β†’` - Open directory or start download/upload - `h` / `←` / `Backspace` - Navigate up to parent directory - `v` - Toggle between dual-pane and single-pane layout (persisted) - `i` - Inspect entry details (size, modified, path) - `n` - Create new directory (in focused pane) - `d` - Delete file or directory (in focused pane, with confirm) - `R` - Rename file or directory (in focused pane) - `r` - Refresh listing - `/` - Search/filter files - `Esc` - Cancel transfer / go back File management (`n`/`d`/`R`) works in both panes. Narrow terminals (under 80 columns) automatically adapt to single-pane layout. You can also open the site manager or browser directly from CLI: ```bash ctty webdav # WebDAV site manager TUI ctty webdav nextcloud # Open browser directly for a saved site ``` **Headless WebDAV operations:** ```bash ctty webdav ls nextcloud # List remote directory ctty webdav ls nextcloud /Documents --format json # Machine-readable listing ctty webdav get nextcloud /Documents/report.pdf ./report.pdf ctty webdav put nextcloud ./backup/ /RemoteBackup/ ctty webdav mkdir nextcloud /Documents/Archive ctty webdav rm nextcloud /Documents/old.pdf ctty webdav rmdir nextcloud /Documents/TempDir # Recursive directory deletion ctty webdav rename nextcloud /Documents/a.pdf /Documents/b.pdf ``` Progress is on stderr; directories are recursive; passwords are encrypted in the vault. ### S3 Object Storage Press `O` (Shift+O) from the main TUI or cycle tabs with `[` / `]` to open the S3 object storage manager β€” connect to AWS S3, MinIO, Cloudflare R2, Aliyun OSS, Ceph, or any S3-compatible object storage endpoint. **S3 site manager:** - `Enter` - Connect and open browser (lists buckets or objects in configured default bucket) - `a` - Add S3 site (name, endpoint, bucket, region, access key, secret key, use SSL, path style, insecure TLS, tags) - `e` - Edit site - `d` - Delete site (with confirmation modal) - `Space` / `Ctrl+A` - Multi-select sites for batch deletion - `y` - Copy endpoint URL - `i` - Inspect site details - `p` - Probe connectivity / bucket access - `w` - Filter by tag - `/` - Search/filter sites - `Esc` - Back Saved sites live in `~/.config/ctty/s3.json` (0600). Secret keys are encrypted in the shared credentials vault (`~/.config/ctty/credentials.json`, S3 entries under `s3:` names) using AES-256-GCM. **S3 browser (dual-pane local | remote):** - `Tab` / `Shift+Tab` - Toggle focus between local and remote pane - `Enter` / `l` / `β†’` - Open bucket/directory or start download/upload - `h` / `←` / `Backspace` - Navigate up to parent directory or bucket list - `v` - Toggle between dual-pane and single-pane layout (persisted) - `i` - Inspect entry details (size, modified, ETag, path) - `n` / `a` - Create new bucket or directory marker (in focused pane) - `d` - Delete file or directory prefix (in focused pane, with confirm) - `R` - Rename / move file or directory prefix (in focused pane) - `r` - Refresh listing - `/` - Search/filter files - `Esc` - Cancel active transfer / go back File management (`n`/`d`/`R`) works in both panes. Narrow terminals (under 80 columns) automatically adapt to single-pane layout. You can also open the site manager or browser directly from CLI: ```bash ctty s3 # S3 site manager TUI ctty s3 minio # Open browser directly for a saved site ``` **Headless S3 operations:** ```bash ctty s3 list # List configured S3 sites ctty s3 list --format json # Machine-readable site list ctty s3 ls minio # List buckets or objects at root ctty s3 ls minio my-bucket/docs --format json # Machine-readable listing ctty s3 get minio my-bucket/docs/report.pdf ./report.pdf # Download file or recursive prefix ctty s3 put minio ./backup/ my-bucket/backup/ # Upload file or recursive directory ctty s3 mkdir minio my-bucket/Archive # Create bucket or directory marker ctty s3 rm minio my-bucket/old.pdf # Delete object ctty s3 rm minio my-bucket/TempDir -r # Recursive prefix deletion ctty s3 rename minio my-bucket/old.txt new.txt # Rename / move object ctty s3 mv minio my-bucket/olddir my-bucket/newdir # Rename / move prefix ``` Progress is on stderr; transfers support directory recursion; secret keys are loaded securely from the encrypted vault. ### Port Forwarding ctty provides an intuitive interface for setting up SSH port forwarding. Press `f` while selecting a host to open the port forwarding setup: **Forward Types:** - **Local (-L)** - Forward a local port to a remote host/port through the SSH connection - Example: Access a remote database on `localhost:5432` via local port `15432` - Use case: `ssh -L 15432:localhost:5432 server` β†’ Database accessible on `localhost:15432` - **Remote (-R)** - Forward a remote port back to a local host/port - Example: Expose local web server on remote host's port `8080` - Use case: `ssh -R 8080:localhost:3000 server` β†’ Local app accessible from remote host's port 8080 - ⚠️ **Requirements for external access:** - **SSH Server Config**: Add `GatewayPorts yes` to `/etc/ssh/sshd_config` and restart SSH service - **Firewall**: Open the remote port in the server's firewall (`ufw allow 8080` or equivalent) - **Port Availability**: Ensure the remote port is not already in use - **Bind Address**: Use `0.0.0.0` for external access, `127.0.0.1` for local-only - **Dynamic (-D)** - Create a SOCKS proxy for secure browsing - Example: Route web traffic through the SSH connection - Use case: `ssh -D 1080 server` β†’ Configure browser to use `localhost:1080` as SOCKS proxy - ⚠️ **Configuration requirements:** - **Browser Setup**: Configure SOCKS v5 proxy in browser settings - **DNS**: Enable "Proxy DNS when using SOCKS v5" for full privacy - **Applications**: Only SOCKS-aware applications will use the proxy - **Bind Address**: Use `127.0.0.1` for security (local access only) **Port Forwarding Interface:** - Choose forward type with ←/β†’ arrow keys - Configure ports and addresses with guided forms - Optional bind address configuration (defaults to 127.0.0.1) - Real-time validation of port numbers and addresses - **Port forwarding history** - Save frequently used configurations for quick reuse - Connect automatically with configured forwarding options **Troubleshooting Port Forwarding:** *Remote Forwarding Issues:* ```bash # Error: "remote port forwarding failed for listen port X" # Solutions: 1. Check if port is already in use: ssh server "netstat -tln | grep :X" 2. Use a different port that's available 3. Enable GatewayPorts in SSH config for external access ``` *SSH Server Configuration for Remote Forwarding:* ```bash # Edit SSH daemon config on the server: sudo nano /etc/ssh/sshd_config # Add or uncomment: GatewayPorts yes # Restart SSH service: sudo systemctl restart sshd # Ubuntu/Debian/CentOS 7+ # OR sudo service ssh restart # Older systems ``` *Firewall Configuration:* ```bash # Ubuntu/Debian (UFW): sudo ufw allow [port_number] # CentOS/RHEL/Rocky (firewalld): sudo firewall-cmd --add-port=[port_number]/tcp --permanent sudo firewall-cmd --reload # Check if port is accessible: telnet [server_ip] [port_number] ``` *Dynamic Forwarding (SOCKS) Browser Setup:* ``` Firefox: about:preferences β†’ Network Settings - Manual proxy configuration - SOCKS Host: localhost, Port: [your_port] - SOCKS v5: βœ“ - Proxy DNS when using SOCKS v5: βœ“ Chrome: Launch with proxy chrome --proxy-server="socks5://localhost:[your_port]" ``` ### Remote Command Execution Press `x` on a selected host to open the remote command execution interface. This allows you to run commands on remote hosts without opening an interactive SSH session. **Features:** - Built-in common command snippets: `docker ps`, `df -h`, `free -m`, `uptime`, `top`, `last`, `ps`, `du` - Add custom snippets with `n` key (saved to `~/.config/ctty/snippets.json` with `0600` permissions) - Delete custom snippets with `d` key - User snippets marked with β˜… in the list - `Tab` to fill input with selected snippet - `↑/↓` to browse snippets - `Enter` to execute the command - SSH auto-login with saved passwords supported - First-connection host key auto-accept (no interactive `yes/no` prompt) **Command Execution Navigation:** - `↑/↓` or `j/k` - Browse command snippets - `Tab` - Fill input with selected snippet - `Enter` - Execute the command - `n` - Add new custom snippet - `d` - Delete selected custom snippet - `Esc` - Return to host list ### CLI Usage ctty provides both command-line operations and an interactive TUI interface: ```bash # Launch interactive TUI mode for browsing and connecting to hosts ctty # Connect directly to a specific host (with history tracking) ctty my-server # Execute a command on a remote host ctty my-server uptime # Execute command with arguments ctty my-server ls -la /var/log # Force TTY allocation for interactive commands ctty -t my-server sudo systemctl restart nginx # Launch TUI with custom SSH config file ctty -c /path/to/custom/ssh_config # Connect directly with custom SSH config file ctty my-server -c /path/to/custom/ssh_config # Add a new host using interactive form ctty add # Add a new host with pre-filled hostname ctty add hostname # Add a new host with custom SSH config file ctty add hostname -c /path/to/custom/ssh_config # Edit an existing host configuration ctty edit my-server # Edit host with custom SSH config file ctty edit my-server -c /path/to/custom/ssh_config # Move a host to another SSH config file (requires Include directives) ctty move my-server # Move host with custom SSH config file (requires Include directives) ctty move my-server -c /path/to/custom/ssh_config # Search for hosts (interactive filter or keyword/tag query) ctty search ctty search prod ctty search "#web" # Check network connectivity and SSH port reachability ctty ping prod-server ctty ping web1 web2 --json ctty ping --tags prod --all # Inspect real-time host metrics (uptime, CPU load, memory %, disk %) ctty peek prod-server ctty peek web1 web2 --json ctty peek --tags prod --concurrency 4 # Open SFTP file browser directly for a host ctty sftp prod-server # Open FTP site manager, or a site browser directly ctty ftp ctty ftp lab-nas # FTP headless transfers (no TUI, dirs recursive, progress on stderr) ctty ftp ls lab-nas /pub --format json ctty ftp get lab-nas /pub/file.txt ./file.txt ctty ftp put lab-nas ./file.txt /pub/file.txt ctty ftp mkdir lab-nas /pub/newdir ctty ftp rm lab-nas /pub/file.txt ctty ftp rmdir lab-nas /pub/olddir ctty ftp rename lab-nas /pub/old.txt /pub/new.txt # Open WebDAV site manager, or a site browser directly ctty webdav ctty webdav nextcloud # WebDAV headless transfers (no TUI, dirs recursive, progress on stderr) ctty webdav ls nextcloud /Documents --format json ctty webdav get nextcloud /Documents/report.pdf ./report.pdf ctty webdav put nextcloud ./backup/ /RemoteBackup/ ctty webdav mkdir nextcloud /Documents/Archive ctty webdav rm nextcloud /Documents/old.pdf ctty webdav rmdir nextcloud /Documents/TempDir ctty webdav rename nextcloud /Documents/a.pdf /Documents/b.pdf # Open S3 site manager, or a site browser directly ctty s3 ctty s3 minio # S3 headless operations (no TUI, progress on stderr) ctty s3 list --format json ctty s3 ls minio my-bucket/docs --format json ctty s3 get minio my-bucket/docs/report.pdf ./report.pdf ctty s3 put minio ./backup/ my-bucket/backup/ ctty s3 mkdir minio my-bucket/Archive ctty s3 rm minio my-bucket/old.pdf ctty s3 rm minio my-bucket/TempDir -r ctty s3 rename minio my-bucket/old.txt new.txt ctty s3 mv minio my-bucket/olddir my-bucket/newdir # Browse the local filesystem (search, mkdir/delete/rename, file details) ctty browse ctty browse ~/Downloads # Open Serial device manager directly ctty serial # Add/edit a host without opening the form ctty add --name web-server --hostname 10.0.1.10 --user root --tags prod ctty edit --name web-server --port 2222 # Transfer files over SFTP (no TUI needed) ctty put web-server ./app.tar.gz /srv/www/app.tar.gz ctty get web-server /var/log/app.log ./app.log ctty scp web-server:/etc/ctty.conf ./ctty.conf # Run the same command on many hosts at once ctty exec --tags prod --list-hosts ctty exec --tags prod -- uptime ctty exec --hosts web-01,db-01 -- df -h # Query saved devices as JSON (for scripts / agents) ctty serial list --format json ctty telnet search core --format json # Back up configurations and credentials (optionally encrypted with AES-256-GCM) ctty backup -o my-backup.tar.gz ctty backup -p "passphrase" -o backup.ctty # Restore configuration files from a backup archive ctty restore backup.tar.gz --dry-run ctty restore backup.ctty -p "passphrase" --overwrite # Export connection profiles to JSON or OpenSSH format ctty export --format json ctty export --format ssh --tags prod # Import hosts from Tabby, Termius, FinalShell, or generic JSON ctty import tabby --dry-run ctty import termius -f ./termius-export.json ctty import finalshell -f ~/.finalshell/conn ctty import json -f ./hosts.json # Override interface language (auto, zh, en) ctty --lang zh ctty search prod --lang en # Print machine-readable info (JSON) for scripting ctty info prod-server ctty info prod-server --pretty # With a custom SSH config file ctty -c /path/to/custom/ssh_config info prod-server # Pipe to jq ctty info prod-server | jq -r '.result.target.hostname' ctty info prod-server | jq -r '.result.target.user' # Show version information ctty --version # Disable automatic update check (useful on air-gapped machines) ctty --no-update-check # Self-update: check for a newer release (add --yes to download & install) ctty update ctty update --yes # Import SSH hosts from Tabby (writes ~/.ssh/config.d/tabby.conf) ctty import --from tabby ctty import tabby --dry-run ctty import tabby -f /path/to/tabby/config.yaml # Show help and available commands ctty --help ``` ### Host Info (JSON) `ctty info ` prints a single JSON object to stdout so you can script against it with `jq`. ```bash # Extract fields ctty info prod-server | jq -r '.result.target.hostname' ctty info prod-server | jq -r '.result.target.port' # Check not-found (exit code 2) ctty info does-not-exist | jq -r '.error.code' ``` ### Shell Completion ctty supports shell completion for host names, making it easy to connect to hosts without typing full names: ```bash ctty # Lists all available hosts ctty pro # Completes to hosts starting with "pro" (e.g., prod-server) ``` **Setup Instructions:** **Bash:** ```bash # Enable for current session source <(ctty completion bash) # Enable permanently (add to ~/.bashrc) echo 'source <(ctty completion bash)' >> ~/.bashrc ``` **Zsh:** ```bash # Enable for current session source <(ctty completion zsh) # Enable permanently (add to ~/.zshrc) echo 'source <(ctty completion zsh)' >> ~/.zshrc ``` **Fish:** ```bash # Enable for current session ctty completion fish | source # Enable permanently ctty completion fish > ~/.config/fish/completions/ctty.fish ``` **PowerShell:** ```powershell # Enable for current session ctty completion powershell | Out-String | Invoke-Expression # Enable permanently (add to your PowerShell profile) Add-Content $PROFILE 'ctty completion powershell | Out-String | Invoke-Expression' ``` ### Direct Host Connection ctty supports direct connection to hosts via the command line, making it easy to integrate into your existing workflow: ```bash # Connect directly to any configured host ctty production-server ctty db-staging ctty web-01 # All direct connections are tracked in your history # Use the TUI to see your most recently connected hosts ``` **Features of Direct Connection:** - **Instant connection** - No TUI navigation required - **History tracking** - All connections are recorded with timestamps - **Error handling** - Clear messages if host doesn't exist or configuration issues - **Config file support** - Works with custom config files using `-c` flag ### Remote Command Execution Execute commands on remote hosts without opening an interactive shell: ```bash # Execute a single command ctty prod-server uptime # Execute command with arguments ctty prod-server ls -la /var/log # Check disk usage ctty prod-server df -h # View logs (pipe to local commands) ctty prod-server 'cat /var/log/nginx/access.log' | grep 404 # Force TTY allocation for interactive commands (sudo, vim, etc.) ctty -t prod-server sudo systemctl restart nginx ``` **Features:** - **Exit code propagation** - Remote command exit codes are passed through - **TTY support** - Use `-t` flag for commands requiring terminal interaction - **Pipe-friendly** - Output can be piped to local commands for processing - **History tracking** - Command executions are recorded in connection history ### Backup Configuration ctty automatically creates backups of your SSH configuration files before making any changes to ensure your configurations are safe. **Backup Location:** - **Unix/Linux/macOS**: `~/.config/ctty/backups/` (or `$XDG_CONFIG_HOME/ctty/backups/` if set) - **Windows**: `%APPDATA%\ctty\backups\` (fallback: `%USERPROFILE%\.config\ctty\backups\`) **Key Features:** - Automatic backup before any modification - One backup per file (overwrites previous backup) - Stored separately to avoid SSH Include conflicts - Easy manual recovery if needed **Additional Storage:** - **Connection History**: Stored in the same config directory for persistent tracking - **Port Forwarding History**: Saved configurations for quick reuse of common forwarding setups **Quick Recovery:** ```bash # Unix/Linux/macOS cp ~/.config/ctty/backups/config.backup ~/.ssh/config # Windows copy "%APPDATA%\ctty\backups\config.backup" "%USERPROFILE%\.ssh\config" ``` ### Configuration File Options By default, ctty uses the standard SSH configuration file at `~/.ssh/config`. You can specify a different configuration file using the `-c` flag: ```bash # Use custom config file in TUI mode ctty -c /path/to/custom/ssh_config # Use custom config file with commands ctty add hostname -c /path/to/custom/ssh_config ctty edit hostname -c /path/to/custom/ssh_config ctty move hostname -c /path/to/custom/ssh_config ``` ### Advanced Features #### Host Movement Between Config Files ctty provides a powerful `move` command to relocate SSH hosts between different configuration files. **This feature requires SSH Include directives to be present in your SSH configuration.** ```bash # Move a host to another config file (requires Include directives) ctty move my-server # Move with custom config file (requires Include directives) ctty move my-server -c /path/to/custom/ssh_config ``` **⚠️ Important Requirements:** - **SSH Include directives must be present** in your SSH config file (either `~/.ssh/config` or the file specified with `-c`) - The config file must contain `Include` statements referencing other SSH configuration files - Without Include directives, the move command will display an error message **Features:** - **Interactive file selector** - Choose destination config file from Include directives - **Include support** - Works seamlessly with SSH Include directives structure - **Atomic operations** - Safe host movement with automatic backups - **Validation** - Prevents conflicts and ensures configuration integrity - **Error handling** - Clear messages when Include files are needed but not found **Use Cases:** - Reorganize hosts from main config to specialized include files - Move development hosts to separate environment-specific configs - Consolidate configurations for better organization **Example Setup Required:** Your main SSH config file must contain Include directives like: ```ssh # ~/.ssh/config Include ~/.ssh/config.d/* Include work-servers.conf Include projects/*.conf Host personal-server HostName personal.example.com User myuser ``` #### Real-time Connectivity Status ctty features asynchronous SSH connectivity checking that provides visual indicators of host availability: **Status Indicators:** - 🟒 **Online** - SSH connection successful (shows response time) - 🟑 **Connecting** - Currently testing connectivity - πŸ”΄ **Offline** - SSH connection failed or host unreachable - ⚫ **Unknown** - Status not yet determined **Features:** - **Non-blocking checks** - Status updates happen in the background - **Response time tracking** - See connection latency for online hosts - **Automatic refresh** - Status indicators update continuously - **Error details** - Detailed error information for failed connections #### Automatic Update Checking ctty includes built-in version checking that notifies you of available updates: **Features:** - **Background checking** - Version check happens asynchronously, never blocking startup - **Release notifications** - Clear indicators when updates are available - **Pre-release detection** - Identifies beta and development versions - **GitHub integration** - Direct links to release pages - **Non-intrusive** - Updates don't interrupt your workflow - **Configurable** - Can be disabled for air-gapped or offline environments **Update notifications appear:** - In the main TUI interface as a subtle notification - Only when a newer stable version is available **Disabling update checks:** Via the CLI flag (one-time): ```bash ctty --no-update-check ``` Via `~/.config/ctty/config.json` (persistent): ```json { "check_for_updates": false } ``` #### Self-Update When a new release is detected, update directly from inside ctty: - **From the TUI** β€” press `U` when the update banner is shown, confirm with `y`. Progress (download β†’ checksum verification β†’ install) runs in a modal; restart ctty afterwards to run the new version. - **From the CLI** β€” `ctty update` checks for a newer release; `ctty update --yes` downloads and installs it. Updates download the same release assets as the installers (`ctty__.tar.gz`, `.zip` on Windows), verify the sha256 against the published `checksums.txt`, and swap the binary in atomically β€” an interrupted update never leaves you with a broken binary. If the binary was installed to a directory requiring elevated permissions, re-run with sudo or fix ownership of the executable. #### Import from Tabby Migrate SSH profiles from [Tabby](https://tabby.sh) into OpenSSH config that ctty already uses: ```bash ctty import --from tabby ctty import tabby --dry-run ctty import tabby -f /path/to/tabby/config.yaml ``` Profiles (`type: ssh`) are appended to `~/.ssh/config.d/tabby.conf`, and an `Include` line is added to `~/.ssh/config` if needed. Existing `Host` names are skipped. Tabby vault passwords are not imported β€” set them again in ctty or keep using keys. #### Port Forwarding History ctty remembers your port forwarding configurations for easy reuse: **Features:** - **Automatic saving** - Successful forwarding setups are saved automatically - **Quick reuse** - Previously used configurations appear as suggestions - **Per-host history** - Forwarding history is tracked per SSH host - **All forward types** - Supports Local (-L), Remote (-R), and Dynamic (-D) forwarding history - **Persistent storage** - History survives application restarts ### Platform-Specific Notes **Windows:** - ctty works with the built-in OpenSSH client (Windows 10/11) - Configuration file location: `%USERPROFILE%\.ssh\config` - Compatible with WSL SSH configurations - Supports the same SSH options as Unix systems **Unix/Linux/macOS:** - Standard SSH configuration file: `~/.ssh/config` - Full compatibility with OpenSSH features - Preserves file permissions automatically **Termux (Android):** - Detected automatically by the `install/unix.sh` installer - Installs to `$PREFIX/bin` (e.g. `~/termux/files/usr/bin`), not `/usr/local/bin` - No `sudo` β€” runs with the Termux user permissions - Architecture detection (`aarch64 β†’ arm64`, `armv7* β†’ armv7`) picks the cgo `ctty_Android_*` release asset, which uses Android system DNS (the pure-Go resolver breaks on some devices, e.g. `[::1]:53 connection refused`); the saved-password vault is shared with the Linux build ## πŸ—οΈ Configuration ctty works directly with your standard SSH configuration file (`~/.ssh/config`). It adds special comment tags for enhanced functionality while maintaining full compatibility with standard SSH tools. ### SSH Include Support ctty fully supports SSH Include directives, allowing you to organize your SSH configurations across multiple files. This is particularly useful for managing large numbers of hosts or organizing configurations by environment, project, or team. **Include Examples:** ```ssh # Main ~/.ssh/config file Host personal-server HostName personal.example.com User myuser # Include work-related configurations Include work-servers.conf # Include all configurations from a directory Include projects/* # Include with relative paths Include ~/.ssh/configs/production.conf ``` **Organization Examples:** *work-servers.conf:* ```ssh # Tags: work, production Host prod-web-01 HostName 10.0.1.10 User deploy ProxyJump bastion.company.com # Tags: work, staging Host staging-api HostName staging-api.company.com User developer ``` *projects/client-alpha.conf:* ```ssh # Tags: client, development Host client-alpha-dev HostName dev.client-alpha.com User admin Port 2222 ``` **Example configuration:** Include ~/.ssh/conf.d/* ```ssh # Tags: production, web, frontend Host web-prod-01 HostName 192.168.1.10 User deploy Port 22 IdentityFile ~/.ssh/production_key Compression yes ServerAliveInterval 60 # Tags: development, database Host db-dev HostName dev-db.company.com User admin Port 2222 IdentityFile ~/.ssh/dev_key StrictHostKeyChecking no UserKnownHostsFile /dev/null # Tags: production, backend Host backend-prod HostName 10.0.1.50 User app Port 22 ProxyJump bastion.company.com ProxyCommand ssh -W %h:%p Jumphost IdentityFile ~/.ssh/production_key Compression yes ServerAliveInterval 300 BatchMode yes ``` ### Supported SSH Options ctty supports all standard SSH configuration options: **Built-in Fields:** - `HostName` - Server hostname or IP address - `User` - Username for SSH connection - `Port` - SSH port number - `IdentityFile` - Path to private key file - `ProxyJump` - Jump server for connection tunneling (e.g., `user@jumphost:port`) - `ProxyCommand` - Jump command for connection tunneling (e.g, `ssh -W %h:%p Jumphost`) - `Tags` - Custom tags (ctty extension); the special tag `hidden` hides the host from the TUI and `ctty search` while keeping it connectable via `ctty ` **Additional SSH Options:** You can add any valid SSH option using the "SSH Options" field in the interactive forms. Enter them in command-line format (e.g., `-o Compression=yes -o ServerAliveInterval=60`) and ctty will automatically convert them to the proper SSH config format. **Common SSH Options:** - `Compression` - Enable/disable compression (`yes`/`no`) - `ServerAliveInterval` - Interval in seconds for keepalive messages - `ServerAliveCountMax` - Maximum number of keepalive messages - `StrictHostKeyChecking` - Host key verification (`yes`/`no`/`ask`) - `UserKnownHostsFile` - Path to known hosts file - `BatchMode` - Disable interactive prompts (`yes`/`no`) - `ConnectTimeout` - Connection timeout in seconds - `ControlMaster` - Connection multiplexing (`yes`/`no`/`auto`) - `ControlPath` - Path for control socket - `ControlPersist` - Keep connection alive duration - `ForwardAgent` - Forward SSH agent (`yes`/`no`) - `LocalForward` - Local port forwarding (e.g., `8080:localhost:80`) - `RemoteForward` - Remote port forwarding - `DynamicForward` - SOCKS proxy port forwarding **Example usage in forms:** ``` SSH Options: -o Compression=yes -o ServerAliveInterval=60 -o StrictHostKeyChecking=no ``` This will be automatically converted to: ```ssh Compression yes ServerAliveInterval 60 StrictHostKeyChecking no ``` ### Application Configuration ctty supports a configuration file to customize its behavior, including language, key bindings, update checking, and custom tag colors. You can also configure these interactively in the TUI by pressing `S`. **Configuration File Location:** - **Linux/macOS**: `~/.config/ctty/config.json` (respects `$XDG_CONFIG_HOME`) - **Windows**: `%APPDATA%\ctty\config.json` **Example Configuration:** ```json { "language": "zh_CN", "check_for_updates": true, "key_bindings": { "quit_keys": ["q", "ctrl+c"], "disable_esc_quit": false }, "tag_colors": { "prod": "#FF0055", "staging": "#FFAA00", "k8s": "#326CE5", "mine": "#00DDFF" } } ``` **Available Options:** - **language**: Interface language: `"auto"` (follow OS locale), `"zh_CN"` (Simplified Chinese), or `"en"` (English). Default: `"auto"`. - **check_for_updates**: Boolean to enable or disable the automatic update check at startup. Default: `true`. Set to `false` on air-gapped or offline machines to avoid connection delays. - **key_bindings.quit_keys**: Array of keys that will quit the application. Default: `["q", "ctrl+c"]` - **key_bindings.disable_esc_quit**: Boolean flag to disable ESC key from quitting the application. Default: `false`. Useful for Vim users. - **tag_colors**: Map of custom hex color codes for specific tags (e.g. `{"prod": "#FF0055"}`). Overrides built-in semantic colors and hash palette. **For Vim Users:** If you frequently press ESC accidentally causing the application to quit, set `disable_esc_quit` to `true`. This will disable ESC as a quit key while preserving all other functionality. **For Air-gapped Machines:** If ctty is slow to start due to DNS timeouts when reaching GitHub, set `check_for_updates` to `false`. You can also use the `--no-update-check` CLI flag for a one-time override without editing the config file. **Default Configuration:** If no configuration file exists, ctty will automatically create one with default settings that maintain backward compatibility. ## πŸ› οΈ Development ### Prerequisites - Go 1.23+ - Git ### Build from Source ```bash # Clone the repository git clone https://github.com/zsuroy/ctty.git cd ctty # Build the binary go build -o ctty . # Run ./ctty ``` ### Project Structure ``` ctty/ β”œβ”€β”€ main.go # Application entry point β”œβ”€β”€ cmd/ # CLI commands (Cobra) β”‚ β”œβ”€β”€ root.go # Root command, CLI flags, and interactive mode β”‚ β”œβ”€β”€ add.go # Add host command β”‚ β”œβ”€β”€ edit.go # Edit host command β”‚ β”œβ”€β”€ move.go # Move host command β”‚ β”œβ”€β”€ search.go # Search command β”‚ β”œβ”€β”€ serial.go # Serial device manager command β”‚ β”œβ”€β”€ telnet.go # Telnet manager / direct-connect command β”‚ β”œβ”€β”€ sftp.go # SFTP file browser command β”‚ β”œβ”€β”€ ftp.go # FTP site manager / browser command β”‚ β”œβ”€β”€ webdav.go # WebDAV site manager / browser command β”‚ β”œβ”€β”€ info.go # Machine-readable JSON host info β”‚ └── completion.go # Shell tab completion script generator β”œβ”€β”€ internal/ β”‚ β”œβ”€β”€ config/ # SSH & App configuration management β”‚ β”‚ β”œβ”€β”€ ssh.go # SSH config parsing, manipulation, and include support β”‚ β”‚ └── appconfig.go# App settings (~/.config/ctty/config.json) β”‚ β”œβ”€β”€ connectivity/ # SSH connectivity checking β”‚ β”‚ └── ping.go # Asynchronous SSH ping functionality β”‚ β”œβ”€β”€ history/ # Connection history tracking β”‚ β”‚ └── history.go # History management and last login tracking β”‚ β”œβ”€β”€ i18n/ # Internationalization & locale auto-detection β”‚ β”‚ β”œβ”€β”€ i18n.go # Core translation lookup & state β”‚ β”‚ β”œβ”€β”€ locales.go # Translation dictionaries (English & Chinese) β”‚ β”‚ β”œβ”€β”€ detect_darwin.go # macOS AppleLocale/AppleLanguages detector β”‚ β”‚ β”œβ”€β”€ detect_windows.go # Windows Win32 API GetUserDefaultLocaleName β”‚ β”‚ └── detect_other.go # Linux POSIX locale & Android getprop β”‚ β”œβ”€β”€ serialconfig/ # Serial device configuration and connection β”‚ β”‚ β”œβ”€β”€ serial.go # Device config storage (~/.config/ctty/serial.json) β”‚ β”‚ β”œβ”€β”€ ports.go # Port enumeration and helpers β”‚ β”‚ β”œβ”€β”€ connect.go # Serial connection bridge (ExecCommand) β”‚ β”‚ β”œβ”€β”€ raw_unix.go # POSIX raw terminal mode (x/term) β”‚ β”‚ └── raw_windows.go # Windows raw terminal mode (x/term) β”‚ β”œβ”€β”€ rawterm/ # Shared raw-mode helpers for serial & telnet β”‚ β”‚ └── rawterm.go # MakeRaw / Restore wrappers over x/term β”‚ β”œβ”€β”€ telnetconfig/ # Telnet device configuration β”‚ β”‚ └── telnet.go # Device config storage (~/.config/ctty/telnet.json, atomic writes) β”‚ β”œβ”€β”€ telnetclient/ # Native RFC 854 telnet client β”‚ β”‚ β”œβ”€β”€ telnet.go # IAC state machine, negotiation, interactive bridge β”‚ β”œβ”€β”€ sftpconfig/ # SFTP client engine & file transfer β”‚ β”‚ └── client.go # SFTP session, upload, download, and listing β”‚ β”œβ”€β”€ ftpconfig/ # FTP site inventory (~/.config/ctty/ftp.json) β”‚ β”œβ”€β”€ ftpclient/ # Plain-FTP transport (list, download, upload, mkdir, delete, rename) β”‚ β”œβ”€β”€ ftpcred/ # FTP passwords in the encrypted vault (ftp: names) β”‚ β”œβ”€β”€ webdavconfig/ # WebDAV site inventory (~/.config/ctty/webdav.json) β”‚ β”œβ”€β”€ webdavclient/ # WebDAV transport (list, download, upload, mkdir, delete, rename) β”‚ β”œβ”€β”€ webdavcred/ # WebDAV passwords in the encrypted vault (webdav: names) β”‚ β”œβ”€β”€ version/ # Version checking and updates β”‚ β”‚ β”œβ”€β”€ version.go # GitHub release checking and version comparison β”‚ β”‚ └── version_test.go # Version parsing and comparison tests β”‚ β”œβ”€β”€ ui/ # Terminal UI components (Bubble Tea) β”‚ β”‚ β”œβ”€β”€ tui.go # Main TUI interface and program setup β”‚ β”‚ β”œβ”€β”€ model.go # Core TUI model and state β”‚ β”‚ β”œβ”€β”€ update.go # Message handling and state updates β”‚ β”‚ β”œβ”€β”€ view.go # UI rendering and layout β”‚ β”‚ β”œβ”€β”€ table.go # Host list table component with status indicators & tag colors β”‚ β”‚ β”œβ”€β”€ tag_color.go# Semantic & hash-based tag color mapping β”‚ β”‚ β”œβ”€β”€ add_form.go # Add host form interface β”‚ β”‚ β”œβ”€β”€ edit_form.go# Edit host form interface β”‚ β”‚ β”œβ”€β”€ move_form.go# Move host form interface β”‚ β”‚ β”œβ”€β”€ info_form.go# Host details modal β”‚ β”‚ β”œβ”€β”€ help_form.go# Keyboard shortcut help modal β”‚ β”‚ β”œβ”€β”€ port_forward_form.go # Port forwarding setup with history β”‚ β”‚ β”œβ”€β”€ styles.go # Lip Gloss styling definitions β”‚ β”‚ β”œβ”€β”€ sort.go # Sorting and filtering logic β”‚ β”‚ β”œβ”€β”€ serial_form.go # Serial device list UI β”‚ β”‚ β”œβ”€β”€ serial_add_form.go # Add serial device form β”‚ β”‚ β”œβ”€β”€ serial_connect_form.go # Edit serial parameters form β”‚ β”‚ β”œβ”€β”€ telnet_form.go # Telnet device list UI with reachability probe β”‚ β”‚ β”œβ”€β”€ ftp_sites.go # FTP site manager UI β”‚ β”‚ β”œβ”€β”€ ftp_view.go # FTP dual-pane local|remote browser UI β”‚ β”‚ β”œβ”€β”€ webdav_sites.go # WebDAV site manager UI β”‚ β”‚ β”œβ”€β”€ webdav_view.go # WebDAV dual-pane browser UI β”‚ β”‚ └── sftp_view.go # SFTP remote & local browser UI β”‚ └── validation/ # Input validation β”‚ └── ssh.go # SSH config validation β”œβ”€β”€ images/ # Documentation assets β”‚ β”œβ”€β”€ logo.png # Project logo β”‚ └── ctty.gif # Demo animation β”œβ”€β”€ install/ # Installation scripts β”‚ β”œβ”€β”€ unix.sh # Unix/Linux/macOS installer β”‚ └── README.md # Installation guide β”œβ”€β”€ .github/ # GitHub configuration β”‚ β”œβ”€β”€ copilot-instructions.md # Development guidelines β”‚ └── workflows/ # CI/CD pipelines β”‚ └── build.yml # Multi-platform builds β”œβ”€β”€ go.mod # Go module definition β”œβ”€β”€ go.sum # Go module checksums β”œβ”€β”€ LICENSE # MIT license └── README.md # Project documentation ``` ### Dependencies - [Cobra](https://github.com/spf13/cobra) - CLI framework - [Bubble Tea](https://github.com/charmbracelet/bubbletea) - TUI framework - [Bubbles](https://github.com/charmbracelet/bubbles) - TUI components - [Lipgloss](https://github.com/charmbracelet/lipgloss) - Styling - [Serial](https://github.com/bugst/go-serial) - Cross-platform serial port communication ## πŸ“¦ Releases Automated releases are built for multiple platforms: | Platform | Architecture | Download | |----------|-------------|----------| | Linux | AMD64 | [ctty_Linux_x86_64.tar.gz](https://github.com/zsuroy/ctty/releases/latest/download/ctty_Linux_x86_64.tar.gz) | | Linux | ARM64 | [ctty_Linux_arm64.tar.gz](https://github.com/zsuroy/ctty/releases/latest/download/ctty_Linux_arm64.tar.gz) | | macOS | Intel | [ctty_Darwin_x86_64.tar.gz](https://github.com/zsuroy/ctty/releases/latest/download/ctty_Darwin_x86_64.tar.gz) | | macOS | Apple Silicon | [ctty_Darwin_arm64.tar.gz](https://github.com/zsuroy/ctty/releases/latest/download/ctty_Darwin_arm64.tar.gz) | | Windows | AMD64 | [ctty_Windows_x86_64.zip](https://github.com/zsuroy/ctty/releases/latest/download/ctty_Windows_x86_64.zip) | ## 🀝 Contributing Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change. ### Development Workflow 1. **Fork** the repository 2. **Create** a feature branch (`git checkout -b feature/amazing-feature`) 3. **Commit** your changes (`git commit -m 'Add amazing feature'`) 4. **Push** to the branch (`git push origin feature/amazing-feature`) 5. **Open** a Pull Request ## πŸ“ License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. ## πŸ™ Acknowledgments This project is a fork of [sshm](https://github.com/Gu1llaum-3/sshm) by [@Gu1llaum-3](https://github.com/Gu1llaum-3). We are grateful for the original work that made ctty possible. - [Charm](https://charm.sh/) for the amazing TUI libraries - [Cobra](https://cobra.dev/) for the excellent CLI framework - [@Gu1llaum-3](https://github.com/Gu1llaum-3/sshm) for creating sshm, the ssh foundation of ctty - [@yimeng](https://github.com/yimeng) for contributing SSH Include directive support - [@ldreux](https://github.com/ldreux) for contributing multi-word search functionality - [@qingfengzxr](https://github.com/qingfengzxr) for contributing custom key bindings support - [Linux.do](https://linux.do) Β· [V2ex](https://v2ex.com)for opensource support - The Go community for building such fantastic tools ## Star History Star History Chart ---
**Made with ❀️ by [zsuroy](https://github.com/zsuroy)** ⭐ **Star this repo if you found it useful!** ⭐