- Default active pane changed from Remote to Local on SFTP init
- renderPane now takes maxH parameter for fixed border height
- paneStyle.Height(maxH) prevents border from shrinking/growing on scroll
- Stacked mode: maxH = t.height - 6; Side-by-side: t.height - 5
Stacked mode (<50 cols) now shows only the active pane (Local/Remote)
with a visual indicator bar. Tab switches between panes. Side-by-side
mode (>=50 cols) unchanged.
Root cause: lipgloss Width(maxW) = content area inside border, border adds 2 chars extra.
- halfW was t.width/2, should be t.width/2-2 (reserve border per pane)
- innerW was maxW-4, should be maxW-2 (padding only, not border)
- Each pane total = maxW + 2 (content + border)
- NEW responsive.go: wrapFooter, adaptiveSidePad, clampWidth, truncateStr
- Footer auto-wraps to multi-line on narrow terminals (full labels preserved)
- Box width clamped to terminal width across all tabs
- Host/key/snippet rows truncated with ellipsis; compact format <35 cols
- SFTP panes stack vertically when terminal < 50 cols
- Tab bar truncates names on overflow
- Form contentW minimum lowered 50->30 for mobile
- Fixed: key_list_tab & snippet_list_tab dropped last data row (off-by-one bug)
- tea.Batch(tea.ClearScreen, sshConnectCmd) before SSH starts so TUI
output doesn't bleed into SSH terminal
- tea.ClearScreen after SSH exits so SSH output doesn't ghost in TUI
- Host list now paginates: only (term_height - 8) / 5 cards shown,
viewport follows selectedIndex with centered scrolling
- Shows 'N of M hosts' indicator when content is clipped
- Added 'e' key alias for editing host (Ctrl+E or E)
- Status bar footer centered within terminal width using lipgloss.Width
- Auth Type field replaced with toggle pills (password/key)
Space/Enter/←/→ cycle between options on the focused field
Selected type shown with SelectedStyle/TagStyle (green),
inactive type shown in muted SubtitleStyle
Help hint 'Space/←/→ to toggle' shown when focused
- Added toggleAuthType() and cycleAuthType() helpers
Bug: t.inputs[t.focus].Update(msg) discarded the returned textinput.Model,
so typed characters were never stored in the input state.
Fix: capture both updated model and cmd from textinput.Update():
t.inputs[t.focus], cmd = t.inputs[t.focus].Update(msg)
return t, cmd
Same fix applied to all 3 forms (host, key, snippet).
Also moved ctrl+s out of default to its own case for clarity.
CRITICAL BUG: sshConnectCmd wrapped tea.ExecProcess inside an extra
closure, so Bubble Tea never executed the SSH process — Enter appeared
to do nothing.
Fix:
- sshConnectCmd now returns tea.ExecProcess directly (no extra closure)
- tea.ExecProcess handles all process lifecycle (start, PTY, exit)
- sshExitMsg errors are shown in host list view (ErrorStyle)
- Error routed via Model.Error → HostListTab.err → View()
- 2 lines top padding instead of aggressive vertical centering
- centerText() uses lipgloss.Width for accurate ANSI-aware centering
- Each card line centered individually within terminal width
- Card width capped at 74 chars
Phase B — Tamagosh-inspired dual-pane file browser:
- Left pane: local filesystem (starts at /Users/swanadiva)
- Right pane: remote filesystem via SFTP
- Tab key switches active pane (green border = active)
- Local CWD indicator per pane
- File listing with dir/ file size display
- Filter mode with / key
- Copy files: C key copies from active pane to opposite pane
- Delete (D), mkdir (N on remote), Refresh (R)
- Esc to close
- File size formatting (B/KiB/MiB/GiB)
- Progress message during transfers
- StylePaneActive (green border) / StylePaneInactive (muted border)
Phase A — Tamagosh-inspired redesign:
- Replace goroutine-based SSH (crypto/ssh) with tea.ExecProcess + native ssh binary
- Zero-lag SSH: native binary pegang TTY langsung, ga ada Go buffering
- Password auth via sshpass -e (SSHPASS env)
- Key auth via ssh -i <tmpfile> + SSH_ASKPASS for passphrase
- ControlMaster sockets for fast reconnect
- Add askpass subcommand for SSH_ASKPASS support
- Gruvbox Material Dark Hard palette for comfortable viewing
- Clean up old session messages (openSessionMsg, sessionOutputMsg, sessionDoneMsg)
- Remove 354-line session.go, replace with 150-line ssh.go
- KeyListTab: view/add/edit/delete SSH keys (Ctrl+K from host list)
- KeyFormTab: add/edit key form with name, type, private key, passphrase
- SnippetListTab: view/add/edit/delete snippets (Ctrl+P from host list)
- SnippetFormTab: add/edit snippet form with name, command, description, tags
- Updated status bar with new hints
- Save/delete commands for both key pairs and snippets
- SFTPBrowserTab with remote directory browsing
- Open via Ctrl+F from host list
- Navigate dirs, filter with /, refresh with r
- Dir/icon display with file sizes
- Sort dirs first, then by name
- HostFormTab with textinput fields for all host fields
- Add (Ctrl+N) and Edit (Ctrl+E) from host list
- Save to JSON storage, auto-reload on save
- Esc to cancel, navigable form with keyboard
- Update Makefile with test-coverage and verify targets
- Add build.sh script for cross-platform builds with SHA256 checksums
- Implement integration tests for full workflow (add/list/get/update/export/delete)
- Add config integration test
- Update project state documentation
- Add export command with JSON file output and size summary
- Add import command with replace/merge strategies and dry-run preview
- Add integration test for export/import round-trip via storage layer
- Update project state documentation
- Add edit command with flag-based and interactive update modes
- Add delete command with confirmation prompt and --force flag
- Include delete alias 'rm' for convenience
- Add comprehensive tests for both commands
- Update project state documentation
- Add connect command with native SSH (default) and direct Go SSH (--direct) modes
- Support host lookup by name or ID
- Build SSH arguments for system SSH client
- Include timeout configuration flag
- Add comprehensive tests for command and SSH arg building
- Update project state documentation
- Add root command with Cobra framework
- Implement shell completion support for bash/zsh/fish/powershell
- Add version command
- Add configuration initialization on startup via PersistentPreRunE
- Include verbose (-v/-vv) and debug flags
- Set up proper error handling and exit codes
Co-Authored-By: Claude <noreply@anthropic.com>