A modern, lightweight SSH terminal with integrated file manager. Built with Go (Wails) and React.
- SSH Connection Management: Automatically reads and parses
~/.ssh/configfile - Integrated File Manager: Three-pane layout with SFTP file browser
- Remote Files: Browse and manage files on SSH servers via SFTP
- Local Files: Browse and manage local filesystem
- Drag & drop file transfer between remote and local
- File Operations:
- Double-click to edit: Open files in floating independent editor window
- F2 to rename: Quick rename for files and directories
- Right-click context menu: Edit, Download, Upload, Delete, Rename
- Modern Terminal: Based on xterm.js with full terminal emulation
- Drag & Drop: Drag files from Finder/Explorer to insert absolute path into terminal
- Clipboard Support: Cmd+C/V copy-paste, select-to-copy, right-click-paste
- File Editor: Multi-tab file editor with Notepad++-like features
- Drag & Drop: Drag files from Finder/Explorer to open
- Multi-tab Interface: Edit multiple files simultaneously
- Smart Tab Labels: Long filename truncation with full path tooltip on hover
- Auto-save Location: Files saved to ~/Documents/XTermFileManager by default
- Smart Naming: Auto-increment (Untitled.txt, Untitled-1.txt, Untitled-2.txt...)
- Syntax Highlighting: Support for 30+ programming languages via Monaco Editor
- Unsaved Changes Warning: Visual indicator and confirmation dialog
- Developer Tools: Professional tools for developers
- JSON Formatter: Tree view with expand/collapse, syntax highlighting (like json.cn)
- C Formatter: Auto-format with configurable indent size
- Escape Tool: Auto-convert escape sequences with toggle mode
- Keyboard Shortcuts:
- Ctrl+C: Copy (with selection) or interrupt (without selection)
- Ctrl+D: Send EOF signal
- F2: Rename selected file/directory
- Preferences Menu: Application menu with terminal settings (Preferences > Terminal)
- Lightweight: Built with Go + Wails, much lighter than Electron
Bug Fixes:
- Same-tab terminal reconnects no longer start from a blank screen: When an SSH terminal disconnects and reconnects in the same tab, the previous scrollback is replayed before the new session starts, so users can still see the earlier command/output context.
- Local terminal restarts keep prior output visible in the same tab: Reopening a local shell in an existing tab now preserves the tab's earlier terminal history instead of discarding it as soon as the PTY is recreated.
Quality Improvements:
- Terminal history is now tracked per tab instead of per backend session id: Tabs keep a stable frontend history key even when the underlying SSH/local session id changes during reconnect.
- Added terminal history retention regression tests: New frontend coverage verifies history append, isolation, and cleanup behavior for tab-scoped terminal history.
Bug Fixes:
- Switching from symbol input to Chinese no longer leaks a Latin preedit letter: On macOS, after typing a plain symbol or ASCII key and then entering Chinese like
子, the terminal now waits for the IME composition to resolve instead of forwarding the transient letter first, soz子no longer appears. - Chinese input stays correct when moving between ASCII symbols and pinyin composition: The terminal now handles plain letters and punctuation through the same native-input tracking path, preventing both missing symbols and stray leading letters during IME transitions.
Quality Improvements:
- Deferred native text handling now distinguishes composition from committed text: The terminal listens to
compositionstart/compositionendtogether withbeforeinput/inputso ASCII fallback is only flushed when no committed IME text arrives. - Expanded IME regression tests beyond punctuation-only cases: Frontend coverage now checks macOS single-character candidate tracking for both letters and symbols plus committed/composition stage detection.
Bug Fixes:
- Terminal symbol input works again after the v2.53 release: macOS punctuation keys such as
-,,,.,/, and;are no longer swallowed by the deferred IME workaround, while Chinese full-width punctuation still commits correctly through the native input path. - Chinese punctuation and ASCII punctuation now coexist safely: The terminal now delays forwarding raw ASCII punctuation briefly and replaces it with the committed native IME character when available, preventing both missing symbols and duplicate punctuation.
Quality Improvements:
- Deferred punctuation handling now distinguishes ASCII fallback from committed IME text: The terminal tracks punctuation long enough to swap native committed text in place, but only flushes the ASCII fallback when no IME replacement arrives.
Bug Fixes:
- macOS Chinese punctuation no longer doubles after the v2.52 fix: The terminal now treats the native xterm/browser input path as the only source of committed punctuation and stops using any manual punctuation resend fallback, so entering a single Chinese comma or period no longer inserts two symbols.
Quality Improvements:
- Deferred punctuation handling now only suppresses duplicate key events: The macOS punctuation guard now keeps temporary state just long enough to ignore duplicate keyboard events and clears that state as soon as native terminal input arrives.
Bug Fixes:
- macOS Chinese punctuation no longer duplicates in terminal apps: The terminal now lets the native committed IME input path deliver full-width punctuation on its own and only uses the manual
keyupfallback when that native path fails, preventing a single Chinese punctuation keystroke from being written twice.
Quality Improvements:
- Deferred punctuation flow narrowed to fallback-only writes: The macOS punctuation workaround now clears its pending state when native committed input arrives, reducing interference with xterm's built-in input pipeline while preserving the existing safety fallback.
Bug Fixes:
- macOS Chinese punctuation now reaches terminal apps correctly: The terminal now defers plain punctuation keys to the committed
beforeinputtext path on macOS, so Chinese IME full-width punctuation like,。!?;:is no longer downgraded to ASCII inside terminal apps such ascodex. - Cross-page terminal copy works again: Long drag selections across multiple screens of scrollback now keep their cached selection snapshot in sync even when select-to-copy is disabled, restoring reliable
Cmd+C/ menu copy behavior for large terminal selections. - Bottom SSH status bar stays on one line without horizontal scrolling: The server info footer now compresses each metric into a fixed single-row layout with ellipsis and hover details instead of wrapping to two lines or forcing horizontal scroll.
Quality Improvements:
- Added targeted terminal IME regression tests: New frontend tests cover the macOS punctuation deferral rules and accepted committed-text event types for the terminal input path.
- Refined terminal copy fallback scope: Native copy handling now distinguishes terminal-internal DOM selections from selections outside the terminal, so fallback copy logic stays reliable without stealing clipboard actions from editors or other controls.
Bug Fixes:
- macOS terminal garbled glyph fragments fixed: Terminal sessions on macOS now use the safer DOM renderer inside Wails
WKWebView, avoiding intermittent WebGL text corruption where random colored character shards could appear during normal terminal output.
Quality Improvements:
- Renderer platform detection expanded: Added explicit Apple platform detection so renderer selection stays predictable across macOS and future Apple WebView environments.
- Added renderer regression coverage: New frontend tests verify Apple terminals use the DOM renderer while Windows and Linux keep their intended renderer behavior.
New Features:
- SSH command snippets side panel: SSH sessions now include a dedicated Commands pane between the terminal and file managers, so frequently used ops snippets can be inserted without leaving the app.
- Editable snippet library with sensible defaults: The app now seeds
command-snippets.jsonin the user config directory with common tmux, Docker, log, archive, and troubleshooting commands.
Bug Fixes:
- Snippet changes reload live after save: Saving the command snippets config through the built-in editor now emits a backend event so the Commands pane refreshes immediately without restarting the app.
- SSH pane resizing now supports four-way layouts: Terminal split dragging was updated from a fixed 3-pane model to named pane widths, keeping terminal, commands, remote files, and local files resizable together.
Quality Improvements:
- Added snippet search and persistence tests: New frontend and backend tests cover fuzzy search, drag reorder behavior, config seeding, and snippet sanitization.
New Features:
- SSH config save auto-formatting: Saving
~/.ssh/configthrough the app now inserts a blank line between adjacentHostblocks by default, making large server lists much easier to scan and maintain.
Bug Fixes:
- SSH config spacing stays tidy on save: The backend now normalizes host-block spacing for both local and remote SSH config saves while preserving comments inside each server block.
- Finder metadata no longer belongs in releases: Removed tracked
.DS_Storefiles from the repository so macOS Finder metadata stops polluting release diffs.
Quality Improvements:
- Added SSH config formatting tests: Covered host-block spacing and inline comment preservation with dedicated Go tests.
New Features:
- SSH server sidebar sorting: The left server list now supports one-click A-Z / Z-A sorting and can write the reordered
Hostblocks back into~/.ssh/config. - Manual server drag reordering: Servers can now be dragged directly in the sidebar, and the visible order is persisted back to the SSH config file instead of being treated as temporary UI state.
Bug Fixes:
- Multi-page terminal copy works through native copy actions: When selecting terminal text across long scrollback and using the app's copy action, the terminal now reuses a short-lived cached selection snapshot so copied text no longer disappears on long drag selections.
- SSH server list respects config order: The backend no longer force-sorts SSH aliases alphabetically, so custom ordering inside
~/.ssh/configis preserved in the UI.
Quality Improvements:
- Added ordering and clipboard regression tests: Covered SSH config ordering helpers and terminal copy fallback behavior with new frontend and backend tests to reduce release regressions.
New Features:
- VS Code-like local file explorer mode: The local file pane now supports a tree navigation view with expandable folders, sticky root path, and quick switching between list view and explorer view while keeping the current directory context visible.
Bug Fixes:
- Windows local terminal no longer disconnects immediately: Fixed the ConPTY session monitor so it waits for the actual shell process instead of marking the terminal disconnected right after startup.
- Windows file drag-to-terminal path insertion is shell-safe: Local Windows paths with spaces are now inserted with double quotes so they work correctly in both
cmd.exeand PowerShell. - Windows local file pane "go up" path corruption fixed: Navigating to the parent directory no longer turns
D:\...into\D:\...on Windows. - Windows local terminal flicker reduced: Local terminals on Windows now use the DOM renderer instead of GPU-backed renderers to avoid flashing the adjacent file pane in WebView2.
New Features:
- SSH server info bar in terminal view: Connected SSH sessions now show a live status strip with system name, CPU, memory, disk, load, uptime, and network throughput, refreshed periodically from the remote host.
- Remote host telemetry backend: Added a lightweight
GetSSHServerInfo()backend API that samples common Linux host metrics and computes network RX/TX rates between polls for the active SSH session.
Bug Fixes:
- macOS Ctrl+letter terminal shortcuts work reliably again: On WKWebView, hidden textarea key handling could swallow
Ctrl+A,Ctrl+E,Ctrl+K,Ctrl+U, and similar readline/tmux shortcuts. The terminal now sends the correct ASCII control bytes directly when needed. - Server info polling respects connection state: SSH-only polling now stops cleanly when a session disconnects, preventing noisy "session not found/not connected" failures in the terminal UI.
New Features:
- Full OpenSSH config support on macOS: SSH connections now resolve effective config through user + system OpenSSH config, including recursive
Include,IdentityFile,IdentityAgent,ProxyJump,ProxyCommand,UserKnownHostsFile,ForwardAgent,UseKeychain,AddKeysToAgent,IdentitiesOnly,PasswordAuthentication, and timeout-related options. - macOS Keychain-backed SSH auth cache: Server passwords and encrypted private-key passphrases are cached in Keychain on macOS, with a single "Clear Auth Cache" action to remove stored SSH credentials.
- ssh-agent + private key passphrase flow: Added
ssh-agentsigner support, encrypted private-key passphrase prompts, automatic retry after invalid cached passphrases, and agent forwarding for interactive terminal sessions whenForwardAgent yesis configured.
Bug Fixes:
- Password-only SSH hosts now connect correctly: Hosts without
IdentityFilenow prompt for password and can reconnect with cached credentials, matching common OpenSSH/MobaXterm workflows. - Terminal link opening and text copy on macOS: Ctrl+left-click now opens hovered URLs in terminal output, and selected text can be copied reliably through native copy handling.
- Server sidebar scroll: The left server list now scrolls correctly, so long SSH config lists remain fully reachable and clickable.
Bug Fixes:
- Interactive terminal apps could not copy to system clipboard: Added OSC 52 clipboard handling so TUI apps like
opencodecan copy text through the host terminal, instead of only showing "Copied to clipboard" inside the app while leaving the real system clipboard unchanged.
Bug Fixes:
- Terminal paste garbled from external apps: Fixed Chinese/UTF-8 clipboard text becoming mojibake when pasted into terminal from other apps. Standard paste now prefers the browser/native clipboard paste path, with API fallback for right-click paste and
Ctrl+Shift+V.
Improvements:
- Collapsible file panes in terminal view: Remote terminal layout now lets users collapse the remote and local file panels to reclaim more horizontal space for the command line. Local terminal view also supports collapsing the local file panel.
Bug Fixes:
- Editor pane invisible/uneditable: Fixed critical CSS bug where opened files in the Editor tab appeared empty and could not be edited. Root cause:
.editor-panesetvisibility: hiddenandpointer-events: none, but.editor-pane-activeonly overrodedisplaywithout restoringvisibility: visibleandpointer-events: auto. All file types (including drag-and-drop opened files) were affected.
Bug Fixes:
- Terminal Chinese input garbled (IME fix): Fixed Chinese/Japanese/Korean IME input producing garbled text in all terminals (local + SSH). Root cause: the custom key event handler in xterm.js was interfering with IME composition events. Added
isComposing/keyCode===229guard to skip custom handler during IME composition, letting xterm.js internalCompositionHelperhandle CJK input correctly. - Windows terminal UTF-8 output truncation: Fixed potential garbled output on Windows local terminals when multi-byte UTF-8 characters (Chinese, emoji) are split across
Read()buffer boundaries. AddedUTF8SafeBufferto Windows ConPTY output reader, matching the existing fix in Unix/macOS terminals. - SSH terminal UTF-8 locale: Added
Setenv("LANG", "en_US.UTF-8")andSetenv("LC_ALL", "en_US.UTF-8")to SSH sessions for better Chinese character support on remote servers (silently ignored if server rejectsSetenv).
New Features:
- Copy to System Clipboard: Right-click any file/folder in all three file managers (Remote, Local, FileBrowser) → "Copy to System Clipboard" — paste into Finder, Feishu, WeChat, Slack, etc. with Cmd+V
- macOS: Native
NSPasteboard writeObjects:via CGo/Objective-C for zero-dependency OS integration - Windows: PowerShell
Set-Clipboard -Pathfor CF_HDROP clipboard format - Remote files: Auto-download via SFTP to temp directory, then copy to clipboard; supports both files and directories (recursive download)
- Temp directory cleanup on app shutdown via
OnShutdownhook
- macOS: Native
- Multi-File Selection: All three file managers now support multi-select
- Cmd+Click (Mac) / Ctrl+Click (Windows): Toggle individual file selection
- Shift+Click: Range select from last clicked file to current
- Shift+Cmd+Click: Append range to existing selection
- Right-click context menu operates on all selected files (batch clipboard copy, batch in-app copy/cut)
- Selection count shown in context menu labels and status bar
Bug Fixes:
- Remote folder clipboard: Fixed
CopyRemoteFilesToSystemClipboardfailing on directories — now detects file vs directory viasftpClient.Stat()and routes toDownloadFileorDownloadDirectoryaccordingly
New Features:
- Tab Right-Click Context Menu: All tab-based views (Terminal, Editor, Files) now support right-click context menu with:
- Close — close the clicked tab
- Close All to the Left — close all tabs to the left of clicked tab
- Close All to the Right — close all tabs to the right of clicked tab
- Close All Others — close all tabs except the clicked one
- Rename — rename the clicked tab
- Disabled state for menu items when action not applicable (e.g. no tabs to the left)
- Terminal Search:
Cmd+F/Ctrl+Fopens in-terminal search bar with next/prev navigation and real-time highlighting
Terminal Enhancements:
- xterm.js Package Upgrade: Migrated from deprecated
xtermto new@xterm/xterm@5.5.0package family - WebGL Renderer: GPU-accelerated rendering with automatic fallback chain: WebGL → Canvas → DOM
- Unicode 11 Support: Correct rendering of emoji (😊) and CJK wide characters (占2列宽)
- Clickable URLs: URLs in terminal output are automatically detected and clickable
- Inline Images: Support for Sixel and iTerm2 inline image protocols
Bug Fixes:
- Batch Tab Close: Fixed batch close operations (Close Left/Right/Others) only closing one tab instead of all — caused by React state closure snapshot issue; now uses single-state-update pattern
Bug Fixes:
- In-App Drag & Drop to Terminal: Fixed file drag from file managers to terminal inserting path
- Root cause: Wails
DisableWebViewDrop: truecauses WKWebView to intercept ALL drop events at native Objective-C level — JavaScriptdropevents never fire - Solution: Use
dragendevent + shared memory module (dragState.ts) instead ofdrop+dataTransfer - Use
document.elementFromPoint()duringdragoverto track cursor position over terminal/file-manager zones
- Root cause: Wails
- Cross-Pane File Transfer: Fixed drag-and-drop file transfer between remote and local file managers
- Same root cause as above —
dropnever fires, so transfer logic moved to unifieddragendhandler - Remote-to-local (download) and local-to-remote (upload) both work via
dragend+setDragTarget()
- Same root cause as above —
- Drag-Over Visual State Stuck: Fixed file manager
drag-overCSS highlight not clearing after drop- Root cause:
setDragOver(false)was only called indrophandler which never fires - Solution: File managers now listen for
dragendonwindowto clear visual state
- Root cause:
- SSH Connection Failure: Fixed
ConnectSSHpassing host string instead of fullSSHConfigEntryobject- Error:
json: cannot unmarshal string into Go value of type app.SSHConfigEntry - Fixed in both
handleCreateSessionandconnectSessionIfNeeded(lazy connect)
- Error:
New Features:
- Debug Log Tab: Built-in Log tab for frontend debugging without browser DevTools
dlog()utility logs to in-memory buffer (max 500 entries) +console.log- Log tab with Copy All button for easy bug reporting
- All drag-and-drop code instrumented with
dlog()for traceability
Files Changed:
- New:
frontend/src/utils/dragState.ts(shared drag payload + target zone tracking) - New:
frontend/src/utils/debugLog.ts(in-memory log collector) - New:
frontend/src/components/log/LogTab.tsx(debug log viewer UI) - Modified:
frontend/src/App.tsx(added Log tab) - Modified:
frontend/src/components/terminal/TerminalTab.tsx(dragend strategy, ConnectSSH fix) - Modified:
frontend/src/components/file-manager/LocalFileManager.tsx(dragState + dragend cleanup) - Modified:
frontend/src/components/file-manager/FileManager.tsx(dragState + dragend cleanup) - Modified:
AGENTS.md(WKWebView drop limitation, ConnectSSH parameter, Debug Log Tab docs)
Bug Fixes:
- Local Terminal Chinese Input: Fixed broken Chinese character input in local terminals
- Added
LANG=en_US.UTF-8andLC_ALL=en_US.UTF-8environment variables - Local terminal now matches SSH terminal behavior for multi-byte character support
- Added
- Local Terminal Delete Key: Fixed Delete/Backspace key showing garbled characters (
^?or^H)- Added
TERM=xterm-256colorenvironment variable (matches SSH terminal configuration) - Terminal control sequences now work correctly
- Added
Configuration Improvements:
- Vite Auto-Open Browser: Disabled automatic browser tab opening during
wails dev- Added
open: falsetofrontend/vite.config.ts - Eliminates unnecessary browser tab at
http://localhost:5173/
- Added
Documentation:
- Updated
AGENTS.mdwith critical configuration settings section- Added "Vite Auto-Open Browser" must-disable configuration
- Added "Local Terminal Environment Variables" must-set configuration
- Prevents AI agents from repeating these common mistakes
Files Changed:
- Backend:
internal/app/pty_unix.go(added TERM and UTF-8 locale environment variables) - Frontend:
frontend/vite.config.ts(disabled auto-open browser) - Documentation:
AGENTS.md(added Critical Configuration Settings section)
Critical Fixes:
- Windows Local Terminal Support: Implemented Windows ConPTY support for local terminals
- Created platform-specific PTY implementations (
pty_unix.go/pty_windows.go) - Windows now supports cmd.exe, PowerShell Core, and PowerShell 5
- Fixed terminal not working on Windows at all
- Created platform-specific PTY implementations (
- Linux Shell Fallback: Fixed shell default (macOS →
/bin/zsh, Linux →/bin/bash) - Session Cleanup Leak: Fixed local terminal process leak when closing tabs
- Double-Close Panic: Added
sync.Onceguard to preventstopChandouble-close panic
Improvements:
- Session ID Collision Fix: Changed from
Unix()toUnixNano()for unique IDs - Dead Code Cleanup: Removed unused WebSocket field/import, deleted
SessionView.tsx - File Rename:
websocket_handler.go→terminal_handler.go(more accurate) - Path Injection Fix: Accept
initialDirparameter inStartLocalTerminalSession()(safer than sendingcdcommands) - Disconnection Notification: Backend emits
terminal:disconnectedevent, terminal shows red disconnect message - Windows Keyboard Fixes: Platform detection,
macOptionIsMetaconditional, added Ctrl+Shift+C/V support (Linux/Windows terminal convention)
New Dependencies:
- Added:
github.com/UserExistsError/conptyv0.1.4 (Windows ConPTY) - Removed:
github.com/gorilla/websocket(unused)
Files Changed:
- Backend:
internal/app/terminal_handler.go,internal/app/pty_unix.go(new),internal/app/pty_windows.go(new),internal/app/app.go - Frontend:
frontend/src/components/terminal/Terminal.tsx,frontend/src/components/terminal/TerminalTab.tsx - Documentation: Added
BUILD.md,docs/BUILD-RELEASE.md,docs/VERSION-RELEASE.md,build-release.shscript
New Features:
- Full internationalization support with react-i18next
- Language switcher in Settings tab (English / 简体中文)
- 158+ UI strings translated across 7 modules (common, terminal, editor, files, sync, tools, settings)
- Ant Design components auto-sync with selected language
- User language preference persists across app restarts (saved to
~/Library/Application Support/xterm-file-manager/settings.json) - Settings tab: centralized location for language selection and terminal preferences
Technical Implementation:
- Backend: Added
Localefield toTerminalSettingsstruct in Go - Frontend: Integrated react-i18next with 7 namespace modules
- Language packs: 14 JSON files (7 modules × 2 languages)
- Real-time language switching without app restart
- Parameterized translations with variable interpolation (e.g.,
t('connectedToHost', { host }))
Files Changed:
- Backend:
internal/app/app.go(added Locale field) - Frontend: 10 components refactored (App, ToolsTab, EditorTab, TerminalTab, SessionView, FileManager, LocalFileManager, FilesTab, SyncPanel, SettingsTab)
- New:
frontend/src/i18n/directory with initialization config and 14 language pack JSON files - New:
frontend/src/components/settings/SettingsTab.tsxcomponent
New Features:
- File Association: register as default app for 38+ file types (txt, json, md, yaml, go, py, js, ts, etc.)
- macOS "Open With" support: right-click any supported file in Finder/Feishu -> Open With -> XTerm File Manager
- macOS
OnFileOpencallback with queue mechanism (handles files opened before app startup) - Windows file association via command-line args (
os.Args), opens files in main window EditorTab - Cross-platform
editor:open-fileWails event for backend-to-frontend file open requests
Platform Behavior:
- macOS: opens files in native NSWindow + WKWebView (Monaco Editor)
- Windows/Linux: opens files in main window EditorTab (Monaco Editor)
New Features:
- Local File Browser tab (Files) with multi-tab support, Windows-style navigation (back/forward/up), breadcrumb path bar, and status bar
- Finder drag-and-drop: drag files/folders from macOS Finder to open in Files tab
- File operations: copy/cut/paste, rename (Enter or F2), delete, new file/folder
- Right-click context menu for all file operations
- Terminal integration: one-click open terminal at current directory
- Pop-out window: drag tab out to open in native macOS NSWindow
- Independent editor window for double-click file editing
Bug Fixes:
- Fixed TDZ error ("Cannot access 'u' before initialization") caused by referencing
constbefore declaration in minified build - Fixed + button only working once (was deduplicating same-path tabs)
- Fixed Finder drag-drop not working (missing
--wails-drop-target: dropCSS property) - Added Enter key as rename shortcut (F2 doesn't work on macOS)
Build Process:
- Documented correct production build steps to avoid stale cache issues
- Added one-liner build command for quick rebuild
build/bin/*can be safely deleted;frontend/dist/directory itself must be preserved (gitkeep)- Must always clean Vite cache + use
-cleanflag + kill old process before opening
Bug Fixes:
- Reverted Terminal.tsx paste handling to v2.25 stable version (bracketed paste mode for multiline)
- Fixed paste in vim: removed broken "paste as-is" change that caused issues
- Restored correct Ctrl+V exclusion from macOS Ctrl passthrough rule
Security Enhancements:
- SSH Host Key Verification: Implemented TOFU (Trust On First Use) strategy
- Verifies host keys against
~/.ssh/known_hosts - Auto-trusts new hosts and records fingerprint
- Detects and blocks key mismatch attacks
- Verifies host keys against
- Fixed JSON marshal error handling (prevents silent failures)
- Fixed EOF error comparison (proper type checking instead of string comparison)
Performance Optimizations:
- SFTP Connection Pool: Reuses SFTP connections instead of creating/destroying per operation
- Removed excessive terminal output logging (eliminates per-byte logging overhead)
- Extracted magic numbers to named constants (IOBufferSize=32KB, SSHConnectTimeout=10s)
Bug Fixes:
- Debug log path: Changed from shared
/tmpto user-specific directory- macOS:
~/Library/Logs/xterm-file-manager/debug.log - Linux:
~/.cache/xterm-file-manager/debug.log
- macOS:
- Added missing RenameLocalFile and RenameRemoteFile backend methods
- Deprecated CreatePTY method (goroutine leak risk, use StartTerminalSession instead)
- Terminal Drag & Drop: Drag files from Finder/Explorer into Terminal to insert absolute path
- Automatic path escaping for paths with spaces (wraps in quotes)
- Multiple files separated by spaces (shell argument list format)
- Visual feedback overlay when dragging files over terminal
- Works with both local terminal and SSH sessions
- Useful for quickly inserting file paths into commands without typing
- Custom Tab Bar: Replaced Ant Design Tabs with native scrollable tab bar
- First tab pinned (position: sticky) — close button stays at fixed screen position
- Click x repeatedly without moving mouse to close multiple files
- Native
overflow-x: autofor reliable sticky behavior
- New Files Leftmost: Latest opened files prepend to tab list (left-side insertion)
- "..." File List Button: Dropdown shows all open files with quick switch
- Compact Tabs: Tab width reduced to 90px (2x more visible tabs on screen)
- Custom Dock Menu: Right-click app icon in Dock shows all open editor windows
- Dynamic window list updated in real-time as editors open/close
- Click any window title to bring it to front
- Current active window marked with checkmark (✓)
- "Show All Editor Windows" command to bring all editors forward at once
- Implemented via Objective-C Runtime (
class_addMethod) injecting into Wails delegate
- Window Menu Integration: All editor windows appear in macOS menu bar Window menu
- Auto-added via
addWindowsItem:when editor opens - Auto-removed via delegate when editor closes
- Auto-added via
- Fixed CGo Memory Management: Eliminated use-after-free crash in async dispatch blocks
- Synchronous NSString conversion before async operations
- Proper strong references for all NSWindow instances
- Clean delegate-based lifecycle management
- Native macOS Independent Editor Window: Double-click file opens in a real OS-level native window
- CGo + NSWindow + WKWebView: True native macOS window, not a browser tab
- Completely independent from Wails main window — interact with terminal and editor simultaneously
- Copy from terminal → paste into editor freely between windows
- Go backend HTTP server (127.0.0.1 only) serves Monaco Editor page
- Dark theme matching VS Code, syntax highlighting for 30+ languages
- Cmd+S to save, unsaved changes warning on close
- Fallback textarea if Monaco CDN unavailable
- Supports both remote (SFTP) and local file editing
- Tab Label UX Improvements:
- Smart filename truncation for long filenames (max 120px)
- Full path tooltip on hover for easy identification
- Fixed drag-and-drop overlay not clearing after file drop
- Drag & Drop Refinements:
- Switched to Wails native
OnFileDropAPI for reliable file path handling - Added safety timeout (3s) to auto-clear drag overlay
- Fixed WebView drag-and-drop integration with
DragAndDrop: trueflag
- Switched to Wails native
- New Editor Tab: Multi-tab file editor with Notepad++-like capabilities
- Drag & drop files from system to open
- Create new files with auto-naming (Untitled.txt, Untitled-1.txt, etc.)
- Default save location: ~/Documents/XTermFileManager
- Open File button with file type filters
- Monaco Editor with syntax highlighting for 30+ languages
- Cmd+S keyboard shortcut for saving
- Unsaved changes indicator and warning dialog
- Backend APIs: CreateLocalFile, GetDefaultEditorDirectory, GetNextUntitledFileName, OpenFileDialog
- Wails Integration: OnFileDrop API for reliable drag-and-drop support
- JSON Formatter: Complete rewrite with tree view
- Tree view with expand/collapse (+/- buttons) like json.cn
- Syntax highlighting for keys, strings, numbers, booleans, null
- Preview mode showing item counts when collapsed
- Auto-format on input
- Toggle between tree view and text view
- C Formatter: Enhanced with auto-format
- Auto-format on input (no button needed)
- Configurable indent size (2-8 spaces)
- Better operator spacing and brace handling
- Escape Tool: Improved UX
- Auto-convert on input
- Toggle mode button for quick switching
- Enhanced swap functionality (bidirectional)
- More escape sequences (\b, \f, \v)
- Improved help documentation layout
- Go code reorganization: Moved all business logic to
internal/app/package - Cleaner root directory: Only
main.goremains in project root - Standard Go layout: Follows Go community best practices with
internal/directory - Modular package structure: Business code in
apppackage, main only handles initialization - Updated Wails bindings: Auto-generated bindings now in
frontend/wailsjs/go/app/ - Documentation organized: All docs in
docs/, scripts inscripts/
- Double-click to edit files: Double-click any file (local or remote) to open in code editor
- F2 rename shortcut: Press F2 to rename selected files/directories
- Context menu rename: Added "Rename" option to right-click menu
- Backend APIs: Added
RenameRemoteFile()andRenameLocalFile()functions - Keyboard shortcuts: Verified Ctrl+C and Ctrl+D work correctly in terminal
- User experience: Seamless file editing and renaming workflow
- Fixed wails.json: Converted to flat colon-separated key format (
"frontend:install","frontend:build","frontend:dev:serverUrl") — the old nested format was silently ignored by Wails CLI, causing "No Install command" and the Vite dev server not starting - Fixed main.go assets: Simplified asset server config — removed placeholder fallback, rely on Wails to handle dev/prod modes correctly via
wails.json - Fixed clipboard: Added standard macOS Edit menu (Copy/Paste/SelectAll) — required for Cmd+C/V to work in WebView
- Fixed terminal borders: Added
ResizeObserverso the terminal reflows correctly when the container resizes (sidebar toggle, tab switch, layout changes) - Fixed server colors: Overrode Ant Design's default dark text to light colors in the server list for dark theme visibility
- Fixed menu structure: Added standard macOS menus (App, Edit, Window) alongside the Preferences menu
- Improved resize: Debounced terminal resize to prevent rapid-fire calls; only process
keydownevents in keyboard handler to prevent double-fire
- Download
xterm-file-manager-darwin-arm64.zipfrom Releases - Extract the ZIP file
- You'll get
xterm-file-manager-darwin-arm64.app
Important - Fix "App is damaged" error (one-time setup):
If you see "xterm-file-manager-darwin-arm64 is damaged and can't be opened", this is macOS Gatekeeper blocking unsigned apps. Fix it by running in Terminal:
# Remove quarantine attribute (only needed once)
xattr -cr xterm-file-manager-darwin-arm64.appAfter removing the quarantine attribute, you can:
- Double-click the app to open it (no need to use
opencommand anymore) - Or install it to your system (see below)
Install to Applications folder (recommended):
- Drag
xterm-file-manager-darwin-arm64.appto your/Applicationsfolder - The app will appear in Launchpad and Applications folder
- You can launch it from there like any other app
- No need to use Terminal commands after installation
- Download
xterm-file-manager-darwin-amd64.zipfrom Releases - Extract the ZIP file to get
xterm-file-manager-darwin-amd64.app - If you see "App is damaged" error, run in Terminal (one-time only):
xattr -cr xterm-file-manager-darwin-amd64.app
- Drag the app to
/Applicationsfolder to install (optional but recommended)
- Download
xterm-file-manager-windows-amd64.exefrom Releases - Run the
.exefile directly
- Launch the application
- The app will automatically read your SSH config from
~/.ssh/config - Select a server from the list to connect
- Use the integrated terminal and file manager
Note: Make sure you have SSH keys configured in ~/.ssh/config for the servers you want to connect to.
- Go 1.21+
- Node.js 18+
- Wails CLI:
go install github.com/wailsapp/wails/v2/cmd/wails@latest
- 📦 发版编译指南 - 如何编译发版到
build/releases/ - 🚀 开发模式 - 下面是开发相关的命令
# Install Go dependencies
go mod download
# Install frontend dependencies
cd frontend && npm install && cd ..
# Run in development mode (starts Vite + Go app automatically)
wails devwails dev handles everything automatically:
- Installs frontend dependencies (
npm install) - Starts the Vite dev server with hot-reload
- Compiles and runs the Go backend
- Opens the app window loading from Vite
You just need to run wails dev — no manual frontend build needed.
If the UI is not updating after changes:
# Clean Vite cache and restart
cd frontend && rm -rf node_modules/.vite .vite && cd ..
wails devIf that doesn't help, do a full clean:
# Full clean rebuild
rm -rf frontend/dist/assets frontend/dist/*.html frontend/dist/*.js
cd frontend && rm -rf node_modules/.vite .vite && npm install && cd ..
wails devNote: Do NOT delete the entire
frontend/dist/directory — it contains agitkeepfile needed by Go's//go:embeddirective. Only delete the build outputs inside it.
使用自动化脚本编译发版到 build/releases/ 目录:
# macOS Apple Silicon (M1/M2/M3) - 默认
./build-release.sh
# 或者指定平台
./build-release.sh darwin-arm64 # macOS Apple Silicon
./build-release.sh darwin-amd64 # macOS Intel
./build-release.sh windows # Windows 64-bit
./build-release.sh linux # Linux 64-bit
./build-release.sh all # 编译所有平台脚本自动完成:
- ✅ 清理所有缓存(Vite、build 产物)
- ✅ 检查并安装依赖
- ✅ 编译指定平台
- ✅ 打包到
build/releases/ - ✅ 显示文件大小和路径
输出文件格式:
- macOS:
xterm-file-manager-v{version}-darwin-arm64.zip(包含 .app) - Windows:
xterm-file-manager-v{version}-windows-amd64.exe - Linux:
xterm-file-manager-v{version}-linux-amd64.tar.gz
Every build must follow these steps, otherwise you may get stale cached code:
# Step 1: Clean all caches (REQUIRED every time)
rm -rf build/bin/* # 可以随便删,只有编译产物
rm -rf frontend/dist/assets # 只删 assets,不要删 dist/ 目录本身
cd frontend && rm -rf node_modules/.vite .vite && cd .. # 清 Vite 缓存
# Step 2: Build
wails build -platform darwin/arm64 -clean
# Step 3: Kill old process before opening (macOS may reuse old instance)
pkill -f xterm-file-manager 2>/dev/null; sleep 1
# Step 4: Open the new build
open build/bin/xterm-file-manager.appBuild for other platforms (still need Step 1 first):
wails build -platform darwin/amd64 -clean # macOS Intel
wails build -platform windows/amd64 -clean # Windows
wails build -platform linux/amd64 -clean # LinuxOne-liner for quick rebuild (macOS Apple Silicon):
rm -rf build/bin/* frontend/dist/assets && cd frontend && rm -rf node_modules/.vite .vite && cd .. && wails build -platform darwin/arm64 -clean && pkill -f xterm-file-manager 2>/dev/null; sleep 1; open build/bin/xterm-file-manager.appImportant notes:
- Always use
-cleanflag to avoid stale binaries- Always clean Vite cache before building — Vite may serve old bundled JS otherwise
- Do NOT delete the entire
frontend/dist/directory — it contains agitkeepfile needed by Go's//go:embed- Always kill the old process before opening — macOS may reuse the already-running old instance instead of launching the new build
xterm-file-manager/
├── main.go # Application entry point
├── internal/
│ └── app/ # Business logic (package app)
│ ├── app.go # App struct, settings, lifecycle
│ ├── ssh.go # SSH config parser (~/.ssh/config)
│ ├── ssh_manager.go # SSH connection pool management
│ ├── websocket_handler.go # Terminal PTY I/O (SSH + local)
│ ├── local_files.go # File operations (local + SFTP)
│ ├── editor_server.go # HTTP server for standalone editor
│ └── editor_window_darwin.go # Native macOS window (CGo)
├── frontend/ # React frontend
│ ├── src/
│ │ ├── components/
│ │ │ ├── terminal/ # Terminal components
│ │ │ ├── file-manager/ # File manager components
│ │ │ ├── editor/ # Code editor
│ │ │ ├── session/ # Session management
│ │ │ └── tools/ # Utility tools
│ │ └── main.tsx
│ ├── wailsjs/ # Auto-generated Wails bindings
│ │ └── go/app/ # Go -> JS bindings
│ └── package.json
├── docs/ # Documentation
│ ├── QUICKSTART.md
│ ├── RELEASE.md
│ ├── RUN.md
│ ├── 工程总结.md
│ └── ...
├── scripts/ # Scripts and configs
│ ├── karabiner-config.json
│ └── test-keyboard.sh
├── build/ # Build resources
│ ├── appicon.png
│ └── bin/ # Build output
├── go.mod
└── wails.json # Wails configuration
MIT