Files
termscp/CLAUDE.md
Christian Visintin a252caa66b refactor: FileTransferActivity pane-agnostic dispatch (#386)
Comprehensive design for incremental refactoring of the 13k-line
FileTransferActivity god-struct using a unified Pane abstraction.
Detailed step-by-step plan covering 6 phases: split monoliths,
error handling, Pane struct, action dedup, session split, view reorg.
Extract 26 popup components from the monolithic 1,868-line popups.rs
into 20 individual files under popups/. Each file contains one or two
related components with their own imports. The popups.rs module file
now contains only module declarations and re-exports.
Replace 8 panic!() calls with error!() logging and early returns/fallthrough.
These panics documented invariants (e.g. "this tab can't do X") but would crash
the app if somehow triggered. Error logging is safer and more resilient.
Replace raw FileExplorer fields in Browser with Pane structs that bundle
the explorer and connected state. Move host_bridge_connected and
remote_connected from FileTransferActivity into the panes. Add navigation
API (fs_pane, opposite_pane, is_find_tab) for future unification tasks.
Rename private get_selected_file to get_selected_file_by_id and add three
new unified methods (get_selected_entries, get_selected_file, is_selected_one)
that dispatch based on self.browser.tab(). Old per-tab methods are kept for
now until their callers are migrated in subsequent tasks.
Collapse _local_/_remote_ action method pairs (mkdir, delete, symlink,
chmod, rename, copy) into unified methods that branch internally on
is_local_tab(). This halves the number of action methods and simplifies
the update.rs dispatch logic. Also unifies ShowFileInfoPopup and
ShowChmodPopup dispatching to use get_selected_entries().
Move `host_bridge` and `client` filesystem fields from FileTransferActivity
into the Pane struct, enabling tab-agnostic dispatch via `fs_pane()`/
`fs_pane_mut()`. This eliminates most `is_local_tab()` branching across
15+ action files.
Key changes:
- Add `fs: Box<dyn HostBridge>` to Pane, remove from FileTransferActivity
- Replace per-side method pairs with unified pane-dispatched methods
- Unify navigation (changedir, reload, scan, file_exists, has_file_changed)
- Replace 147-line popup if/else chain with data-driven priority table
- Replace assert!/panic!/unreachable! with proper error handling
- Fix typo "filetransfer_activiy" across ~29 files
- Add unit tests for Pane

Net result: -473 lines, single code path for most file operations.
2026-02-27 21:58:31 +01:00

5.1 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

termscp is a terminal file transfer client with a TUI (Terminal User Interface), supporting SFTP, SCP, FTP/FTPS, Kube, S3, SMB, and WebDAV protocols. It features a dual-pane file explorer (local + remote), bookmarks, system keyring integration, file watching/sync, an embedded terminal, and customizable themes.

  • Language: Rust (edition 2024, MSRV 1.89.0)
  • UI Framework: tuirealm v3 (built on crossterm)
  • File Transfer: remotefs ecosystem

Build & Development Commands

# Build
cargo build
cargo build --release
cargo build --no-default-features              # minimal build without SMB/keyring

# Test (CI-equivalent)
cargo test --no-default-features --features github-actions --no-fail-fast

# Run a single test
cargo test <test_name> -- --nocapture

# Run tests for a module
cargo test --lib filetransfer::
cargo test --lib config::params::tests

# Lint
cargo clippy -- -Dwarnings

# Format
cargo fmt --all -- --check      # check only
cargo fmt --all                 # fix

System Dependencies (for building)

  • Linux: libdbus-1-dev, libsmbclient-dev
  • macOS: pkg-config, samba (brew, with force link)

Feature Flags

  • smb (default): SMB/Samba protocol support
  • keyring (default): System keyring integration for password storage
  • smb-vendored: Vendored SMB library (for static builds)
  • github-actions: CI flag — disables real keyring in tests, uses file-based storage
  • isolated-tests: For parallel test isolation

Architecture

Application Lifecycle

main.rs → parse CLI args → ActivityManager::new() → ActivityManager::run()
                                                        ↓
                                              Activity loop (draw → poll → update)
                                              ├── AuthActivity (login/bookmarks)
                                              ├── FileTransferActivity (dual-pane explorer)
                                              └── SetupActivity (configuration)

ActivityManager owns a Context that is passed between activities. Each activity takes ownership of the Context on on_create() and returns it on on_destroy().

Key Modules

Module Path Purpose
activity_manager src/activity_manager.rs Orchestrates activity lifecycle and transitions
ui/activities src/ui/activities/{auth,filetransfer,setup}/ Three main screens, each implementing the Activity trait
ui/context src/ui/context.rs Shared Context struct (terminal, config, bookmarks, theme)
filetransfer src/filetransfer/ Protocol enum, RemoteFsBuilder, connection parameters
host src/host/ HostBridge trait — abstracts local (Localhost) and remote (RemoteBridged) file operations
explorer src/explorer/ FileExplorer — directory navigation, sorting, filtering, transfer queue
system src/system/ BookmarksClient, ConfigClient, ThemeProvider, SshKeyStorage, KeyStorage trait
config src/config/ TOML-based serialization for themes, bookmarks, user params

Core Traits

  • Activity (src/ui/activities/mod.rs): on_create, on_draw, will_umount, on_destroy — UI screen lifecycle
  • HostBridge (src/host/bridge.rs): Unified file operations interface (connect, list_dir, open_file, mkdir, remove, rename, copy, etc.)
  • KeyStorage (src/system/keys/mod.rs): get_key/set_key — password storage abstraction (keyring or encrypted file fallback)

Conditional Compilation

The build.rs defines cfg aliases via cfg_aliases:

  • posix, macos, linux, win — platform shortcuts
  • smb, smb_unix, smb_windows — feature + platform combinations

Platform-specific dependencies: SSH and FTP crates use different TLS backends on Unix vs Windows. SMB support is completely gated behind the smb feature flag.

File Transfer Protocols

FileTransferProtocol enum maps to protocol-specific parameter types (ProtocolParams enum) and RemoteFsBuilder constructs the appropriate RemoteFs client. Each protocol has its own params struct (e.g., GenericProtocolParams for SSH-based, AwsS3Params, KubeProtocolParams, SmbParams, WebDAVProtocolParams).

Code Conventions

  • rustfmt: group_imports = "StdExternalCrate", imports_granularity = "Module"
  • Error handling: Custom error types with thiserror, module-level Result aliases (e.g., HostResult<T>)
  • Builder pattern: Used for RemoteFsBuilder, HostBridgeBuilder
  • Client pattern: System services wrapped as clients (BookmarksClient, ConfigClient)
  • Tests: Unit tests in #[cfg(test)] blocks within source files. Tests requiring serial execution use #[serial] from serial_test
  • Encryption: Bookmark passwords encrypted with magic-crypt; keys stored in system keyring or encrypted file

Other conventions

  • Always put plans to ./.claude/plans/