* feat(gcs): add Google Cloud Storage support Closes #436 * fix: honor configured protocol and finalization errors * ci: remove TruffleHog checks
6.7 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, GCS, 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.98.0)
- UI Framework: tuirealm v3 (built on crossterm)
- File Transfer: remotefs ecosystem
Build & Development Commands
Task runner is just (modular recipes under just/*.just, imported by root justfile). Run just --list for the full set.
# Build
just build_crates # cargo build --workspace
just build_crates "--release"
cargo build --no-default-features # minimal build without SMB/keyring (no just recipe)
# Test (CI-equivalent)
just test "--no-default-features --features github-actions --no-fail-fast"
# Run a single test / a module (use cargo directly, just recipes don't take test names)
cargo test <test_name> -- --nocapture
cargo test --lib filetransfer::
cargo test --lib config::params::tests
# Lint
just clippy "-- -D warnings"
# Format (dprint: Markdown, TOML, YAML, and Rust via nightly rustfmt)
just fmt_check # check only
just fmt # fix
# All code checks at once (fmt_check, clippy -D warnings, doc, deny, install script lint)
just check_code
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 supportkeyring(default): System keyring integration for password storagesmb-vendored: Vendored SMB library (for static builds)github-actions: CI flag — disables real keyring in tests, uses file-based storageisolated-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 lifecycleHostBridge(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 shortcutssmb,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, GoogleCloudStorageParams, 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]fromserial_test - Encryption: Bookmark passwords encrypted with
magic-crypt; keys stored in system keyring or encrypted file
Other conventions
- Always run
just fmtandjust clippy "-- -D warnings"after modifying Rust code - Always put plans to
./.claude/plans/ - When changing behavior that is documented under
docs/(paths, config keys, commands, flags, etc.), update BOTHdocs/en-US/anddocs/zh-CN/to keep the translations in sync - All code must be cross-platform compatible (Windows, macOS, Linux) — avoid POSIX-only APIs, hardcoded path separators, or shell-specific behavior unless gated behind the
posix/wincfg aliases