Skip to content

Add Connectivity feature: remote file browsing, sessions, CI extraction, themes#10

Merged
bluestreak01 merged 9 commits intomasterfrom
feature/connectivity-and-enhancements
Apr 15, 2026
Merged

Add Connectivity feature: remote file browsing, sessions, CI extraction, themes#10
bluestreak01 merged 9 commits intomasterfrom
feature/connectivity-and-enhancements

Conversation

@nwoolmer
Copy link
Copy Markdown
Contributor

@nwoolmer nwoolmer commented Apr 3, 2026

Summary

Adds a comprehensive Connectivity feature (experimental) to middle-manager, enabling remote file browsing across 8 protocols, persistent tmux sessions, CI test failure extraction, and a theme system.

Remote File Browsing (Ctrl+T)

  • 8 protocols: SSH, SFTP, SMB, WebDAV, S3/S3-compatible, GCS, Azure Blob Storage, NFS
  • All implement a common RemoteFs trait — adding new protocols requires zero dispatch code changes
  • Shell-out architecture: uses system CLI tools (ssh, sftp, smbclient, curl, aws, gcloud, az, mount) for maximum compatibility
  • Unified connection dialog with protocol tabs (Alt+Left/Right to cycle)
  • Saved connections (F2 to save, stored in ~/.config/middle-manager/connections.json)
  • Cross-panel copy/move between local and any remote
  • Remote file editing (F3/F4 downloads, edits, uploads on save)
  • Background connection with progress display and 30-second timeout

Session Persistence (--session / Ctrl+Y)

  • middle-manager --session <name> creates/attaches to persistent tmux sessions
  • Survive terminal disconnects; reattach from any device via SSH
  • Session manager dialog (Ctrl+Y) for create/attach/kill
  • Nested session detection prevents tmux-in-tmux issues

CI Failure Extraction (Ctrl+E)

  • Extracts failed test names from Azure DevOps and GitHub Actions
  • Azure test results API (instant, structured) with PAT auth support
  • Falls back to log tail download (last 512KB, gzip compressed)
  • Parses Rust, Java/Maven/Gradle, Go, Python, Jest patterns
  • GitHub API rate limit monitoring
  • Real-time progress in status bar

Theme System (Shift+F1)

  • QuestDB Dark theme: deep purple-black backgrounds with rose-pink accents (#d14671, #892c6c)
  • Settings dialog with live theme switching
  • Thread-local cached theme access (no RwLock per frame)

Other

  • Create file (Shift+F7) on local and remote panels
  • Error/info popup overlays
  • Status bar with auto-clearing progress messages
  • Debug logging (MM_DEBUG=1)
  • Linux clipboard: native xclip/xsel/wl-copy support
  • Empty file editor fix (no more panic on 0-byte files)

New Hotkeys

Key Context Action
Ctrl+T File panel Open/close remote connection dialog
Ctrl+Y File panel Open/close session manager
Ctrl+E CI panel Extract all test failures to file
Shift+F1 Any Open settings dialog
Shift+F7 File panel Create (touch) new file
F2 Remote dialog Save connection
Alt+←/→ Remote dialog Cycle protocol

Architecture

  • RemoteFs trait (src/remote_fs.rs) — 10 methods, implemented by all 7 remote connection types
  • PanelSource::Remote { Rc<dyn RemoteFs> } — single enum variant replaces per-protocol variants
  • Background connections via spawn_remote_connect() + mpsc channel polling
  • No new native library deps (only added quick-xml for WebDAV XML parsing)

Test plan

  • 408 tests pass (331 binary + 67 lib + 10 integration)
  • Integration tests against S3Mock, Azurite, localhost SFTP
  • Multiple security/performance audit passes
  • Tested with QuestDB Azure DevOps CI (private + public projects)
  • Manual: Ctrl+T → each protocol tab → connect → browse → copy files
  • Manual: --session foo → detach → reattach
  • Manual: Ctrl+E on a PR with CI failures
  • Manual: Shift+F1 → switch theme → verify persistence

🤖 Generated with Claude Code

…, NFS

Adds a comprehensive remote file browsing system to middle-manager,
branded as "Connectivity [experimental]". Users can browse, edit, copy,
and manage files across 8 remote protocols directly from the dual-panel
file manager.

## Remote Protocols (Ctrl+T)

All protocols implement a common `RemoteFs` trait, so adding new
protocols requires zero changes to dispatch code.

- **SSH**: Terminal sessions via system `ssh`, with auto-reconnect on disconnect
- **SFTP**: File browsing via `sftp` CLI in batch mode
- **SMB**: File browsing via `smbclient` CLI
- **WebDAV**: File browsing via `curl` + `quick-xml` PROPFIND parsing
- **S3**: Object storage via `aws s3api` (JSON output, supports S3-compatible
  like MinIO, Backblaze B2, Cloudflare R2 via --endpoint-url)
- **GCS**: Google Cloud Storage via `gcloud storage` (JSON format)
- **Azure Blob**: Via `az storage blob` with connection string support,
  container browsing, and automatic API version backoff for Azurite
- **NFS**: Mount-based with automatic unmount on disconnect

## Session Persistence (--session / Ctrl+Y)

- `middle-manager --session <name>` creates/attaches to tmux sessions
- Sessions survive terminal disconnects; reattach from any device via SSH
- Tmux prefix set to backtick to avoid hotkey conflicts
- Nested session detection prevents accidental tmux-in-tmux
- Session manager dialog (Ctrl+Y) for create/attach/kill

## CI Failure Extraction (Ctrl+E)

- Extracts failed test names from Azure DevOps and GitHub Actions CI logs
- Azure test results API (fast path) with PAT auth support
- Falls back to log tail download (last 512KB) with gzip compression
- Parses Rust, Java/Maven/Gradle, Go, Python, Jest failure patterns
- Writes consolidated Markdown report grouped by check
- GitHub API rate limit monitoring
- Real-time progress in status bar

## Theme System (Shift+F1)

- Settings dialog with theme cycling (Left/Right arrows)
- QuestDB Dark theme: deep purple-black backgrounds, rose-pink accents
  using QuestDB brand colors (#d14671, #892c6c)
- Theme persisted in state.json, loaded on startup
- Thread-local cache with generation counter avoids RwLock on every frame

## Saved Connections

- F2 in remote dialog saves current connection to connections.json
- Saved connections shown on dialog open for quick reconnect
- Delete saved connections with Del key

## Other Enhancements

- **Touch/create file** (Shift+F7) for local and remote panels
- **Remote file editing**: F3/F4 downloads to temp, edits, uploads on save
- **Error popups**: Red-bordered for errors, green for success, dismissible
- **Status bar**: Shows progress messages with 5-second auto-clear
- **Debug logging**: MM_DEBUG=1 logs all shell commands to debug.log
- **Linux clipboard**: Native xclip/xsel/wl-copy support (falls back to OSC 52)
- **Empty file editor fix**: No more panic on 0-byte files

## New Hotkeys

| Key | Context | Action |
|-----|---------|--------|
| Ctrl+T | File panel | Open remote connection dialog |
| Ctrl+T | Remote panel | Disconnect and return to local |
| Ctrl+Y | File panel | Open session manager |
| Ctrl+E | CI panel | Extract all test failures |
| Shift+F1 | File panel | Open settings |
| Shift+F7 | File panel | Create (touch) new file |
| F2 | Remote dialog | Save connection |
| Alt+Left/Right | Remote dialog | Cycle protocol |
| Tab | Remote dialog | Cycle fields / switch mode |
| Del | Saved connections | Remove saved connection |

## Architecture

- `RemoteFs` trait in `src/remote_fs.rs` — common interface for all protocols
- `PanelSource::Remote { Rc<dyn RemoteFs> }` — single enum variant for all remotes
- Background thread connections via `spawn_remote_connect()` + mpsc polling
- 30-second connection timeout with progress display
- All protocols shell out to CLI tools (no native library dependencies except quick-xml)

## Testing

- 408 unit tests (331 binary + 67 lib + 10 integration)
- Integration tests for S3 (S3Mock), Azure (Azurite), SFTP (localhost)
- Multiple security/performance audit passes
- Bounds-checked array access, no panics on user input

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@nwoolmer nwoolmer force-pushed the feature/connectivity-and-enhancements branch from 13a5faa to 2bf4d97 Compare April 3, 2026 14:44
- Fix tmux intercepting mouse scroll: unbind WheelUpPane/WheelDownPane
  from copy-mode, rebind with send-keys -M to pass through to app
- Add Shift+PageUp/PageDown for keyboard scrolling in Claude panel
  (20 lines at a time, since regular PageUp/Down are forwarded to Claude)
- Mouse scroll in Claude panel scrolls 3 lines at a time

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bluestreak01 added a commit that referenced this pull request Apr 4, 2026
Adds two major features for PR code review:

**PR Diff Panel (Ctrl+D)**
- Tree view of files changed in the current PR
- Grouped by directory with expand/collapse
- File status indicators (Added/Modified/Deleted/Renamed)
- Quick search: type to filter, Up/Down to cycle matches
- Persisted across sessions

**Side-by-Side Diff Viewer**
- Full-file diff with base branch (via git merge-base)
- Syntax highlighting on both panels
- Text selection (Shift+arrows) and clipboard copy (Ctrl+C)
- Search with match highlighting (Ctrl+F, n/N)
- Hunk navigation (Alt+Up/Down) skips to next/prev diff hunk
- Terminal caret on either panel, Tab to switch sides
- F4 toggles to editor at current line (Esc returns)
- Viewport position preserved across editor/viewer transitions

**Architecture improvements**
- Replaced 5 separate focus fields with single PanelFocus enum
- Extracted focused_side() helper for bottom panel resize logic
- Bottom panel key/action intercepts guarded by mode check
- 346 tests (33 new covering tree building, diff parsing,
  navigation, selection, search, and rendering helpers)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bluestreak01 and others added 3 commits April 4, 2026 15:50
…y-and-enhancements

# Conflicts:
#	src/action.rs
#	src/app.rs
#	src/main.rs
#	src/ui/footer.rs
#	src/ui/mod.rs
Critical (crashes/security):
- Fix RwLock deadlock in theme() when THEME is None
- Fix SFTP command injection via newlines in shell_quote()
- Fix SMB command injection via semicolons in to_smb_path()
- Fix WebDAV credentials visible in process table (use curl stdin config)
- Remove default TLS verification bypass in WebDAV (opt-in insecure flag)
- Pass Azure SAS tokens/connection strings via env vars, not CLI args
- Set 0600 permissions on saved connections file
- Fix byte-boundary string slicing panics with char-aware truncation
- Fix NFS path traversal via .. components

High (data loss/logic bugs):
- Snapshot active_panel at copy dialog open to prevent panel swap bug
- Azure rename: only delete source after confirmed successful copy
- Azure rename: use dst_container for cross-container moves
- move_entry: only fallback to copy+delete on EXDEV, not all errors
- copy_dir_recursive: handle symlinks to prevent infinite recursion
- Remove redundant double-poll of dir_watcher.has_changes()
- Settings dialog: Left key now cycles theme backward
- Tmux bind-key: target specific session instead of global
- CI Azure test results: continue on bad run IDs instead of aborting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Security-critical escaping:
- sftp shell_quote: control chars, newlines, quotes, backslashes (10 tests)
- smb to_smb_path: semicolons, quotes, backslashes, combined (7 tests)

UTF-8 safety:
- truncate_to_width: ASCII, CJK, emoji, multi-byte, edge cases (8 tests)
- ceil_char_boundary: mid-char, boundaries, past-end (6 tests)

Path traversal / filesystem:
- NFS normalize_path + local_path traversal guard (10 tests)
- fs_ops move_entry EXDEV handling, error propagation (3 tests)
- fs_ops copy_dir_recursive with symlinks and loops (3 tests)

Azure / CI:
- azure_blob resolve_path, to_prefix, connection string parsing (15 tests)
- ci.rs parse_failures across 6 CI frameworks + edge cases (17 tests)

Saved connections:
- Serde round-trip, file permissions 0600/0700, load/save (14 tests)

WebDAV:
- insecure flag, URL construction, display labels (7 tests)

Theme:
- next()/prev() cycling and round-trip (5 tests)

Integration tests:
- Fix no-op WebDAV/SMB parser tests to call actual parsers
- Panic on connect failure after skip-guard passes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bluestreak01
Copy link
Copy Markdown
Member

bluestreak01 commented Apr 4, 2026

@nwoolmer

  • the Ctrl+T dialog is not usable on mac
  • there is no visual progress indicator for test extraction
  • test extraction is UI are disconnected, i can navigate away while extraction is in progress orphaning it
  • theme switch is nice, but for "list" item we already use us "space" to cycle. Also dialog spacing could be better across all dialogs - they look sloppy
  • extracting test names only without error details assumes too much. For me personally this would be useless.

@bluestreak01
Copy link
Copy Markdown
Member

i would suggest the following:

  • make external connectivity dialog usable (so it doesn't get stuck on tab order) and polish the layout, so it is consistent with the existing dialogs
  • lets review the fixes, those are very useful
  • lets polish theme dialog

and lets not bother with test name extraction

nwoolmer and others added 4 commits April 6, 2026 15:10
…ialog, settings

- Add Shift+F2 as alternative to Ctrl+T for connectivity (Mac compat)
- Show blocking popup with summary after CI failure extraction
- Replace log downloads with API-only extraction (GitHub annotations, Azure test results)
- Require and validate PAT/auth before starting extraction
- Add spacebar to cycle theme in settings dialog for consistency
- Fix connectivity dialog tab ordering: Tab/BackTab cycle fields uniformly
- Extract failure info (error messages) alongside test names

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…y-and-enhancements

Resolve conflicts between remote connectivity features (SSH/SFTP/S3/etc)
and master's new features (copy options, dir size calc, clipboard module,
hex editor, sparse copy, overwrite dialog).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bugs fixed:
- Settings dialog now uses shared dialog_helpers (render_dialog_frame,
  dialog_styles) instead of ad-hoc rendering
- Popup colors use theme (popup_error_border, popup_success_border)
  instead of hardcoded Color::Red/Green
- SSH dialog BackTab now cycles fields backward (new ToggleReverse action)
- NFS copy_dir_recursive skips symlinks to prevent infinite recursion
- Remove dead code: sftp remove_file(), debug_log log_cmd()
- ThemeName::all() changed from #[allow(dead_code)] to #[cfg(test)]

Duplication eliminated:
- Default download_dir/upload_dir implementations on RemoteFs trait
  (removed identical copies from sftp, smb, webdav)
- Shared path_to_prefix() in remote_fs.rs (was duplicated in s3, gcs, azure)
- Shared format_size() in remote_fs.rs (was duplicated in ci, hex_view, parquet)
- Shared config_dir() in remote_fs.rs (was duplicated in 4 files)
- Deleted render_smb/render_webdav (use generic render_fields)
- Extracted render_input_bar/render_dropdown_list in panel_view.rs
- Extracted footer_styles() and build_colon_spans() in footer.rs

Allocation improvements:
- SSH host list: single buffer + display_label() called once per host
- Footer: split ": label" into two Spans (zero format! per key)
- Popup: replaced title.to_lowercase() with direct contains checks
- SSH filter: pre-computed lowercase search strings (hosts_lower)

Clippy fixes:
- All clippy warnings resolved (range contains, redundant closure,
  collapsible if, complex type alias, thread_local const, etc.)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bluestreak01 bluestreak01 merged commit 5aa0a44 into master Apr 15, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants