sshcp
v0.2.2
Published
Easy SSH file copy CLI tool with persistent server selection, bookmarks, rsync sync, and 2-way watch mode
Maintainers
Readme
sshcp
Easy SSH file copy CLI tool with persistent server selection, bookmarks, rsync sync, and 2-way watch mode.
No more typing long scp user@host:/path/to/file commands. Just select your server once and copy files with ease.
Features
- Interactive server selection - Arrow-key navigation from
~/.ssh/config - Persistent server selection - No need to re-select every time
- Bookmarks - Save frequently used remote paths
- Rsync sync - Efficient incremental directory syncing
- Watch mode - 2-way sync with conflict resolution
- Beautiful terminal UI - Rich formatting and progress display
Installation
Using npx (easiest)
npx sshcp --help
npx sshcp setRequires Python and uv or pipx installed.
Using uv (recommended for Python users)
# Run without installing
uvx sshcp --help
# Or install globally
uv tool install sshcpUsing pip
pip install sshcpFrom source
git clone https://github.com/shubham8550/sshcp.git
cd sshcp
uv sync
uv run sshcp --helpQuick Start
# 1. Select your server (arrow keys to navigate)
sshcp set
# 2. Copy files
sshcp push ./local_file.txt /remote/path/
sshcp pull /remote/file.txt ./local/
# 3. Use bookmarks for frequent paths
sshcp bookmark add logs /var/log/myapp
sshcp pull @logs/error.log ./
# 4. Sync directories efficiently
sshcp sync ./src /var/www/app
# 5. Watch and auto-sync changes
sshcp watch ./project /deploy/appCommands
Server Selection
sshcp set
Interactive server selector with arrow-key navigation:
╭─ Select SSH Server ─────────────────────────────────╮
│ Name Host User Port │
│ prod 192.168.1.100 deploy 22 │
│ ▸ staging staging.example admin 22 │
│ dev 10.0.0.50 dev 2222 │
╰─────────────────────────────────────────────────────╯
↑/↓ navigate • Enter select • q quitsshcp status
Show currently selected server with details.
File Transfer
sshcp push <local> <remote>
Upload a file or directory to the selected server.
sshcp push ./myfile.txt /home/user/myfile.txt
sshcp push ./folder /remote/destination/sshcp pull <remote> <local>
Download a file or directory from the selected server.
sshcp pull /var/log/app.log ./app.log
sshcp pull /etc/nginx ./nginx_config/Bookmarks
Save frequently used remote paths for quick access.
sshcp bookmark add <name> <path>
Create a new bookmark:
sshcp bookmark add logs /var/log/myapp
sshcp bookmark add config /etc/nginx
sshcp bookmark add deploy /var/www/productionsshcp bookmark list
Show all saved bookmarks:
╭─────────────── Saved Bookmarks ───────────────╮
│ Name Path Usage │
│ @logs /var/log/myapp @logs/... │
│ @config /etc/nginx @config/... │
│ @deploy /var/www/production @deploy/... │
╰───────────────────────────────────────────────╯sshcp bookmark rm <name>
Remove a bookmark.
Using Bookmarks
Use @bookmark syntax in any path:
sshcp pull @logs/error.log ./ # → /var/log/myapp/error.log
sshcp push nginx.conf @config/ # → /etc/nginx/
sshcp sync ./src @deploy # → /var/www/productionSync (Rsync)
Efficient incremental directory syncing using rsync.
sshcp sync <local> <remote> [options]
# Push local to remote (default)
sshcp sync ./local_folder /remote/folder
# Pull remote to local
sshcp sync ./local_folder /remote/folder --pull
# Delete files not in source
sshcp sync ./src @deploy --delete
# Preview changes without executing
sshcp sync ./src /remote --dry-run
# Exclude patterns
sshcp sync ./project /deploy --exclude "*.log" --exclude "node_modules"Options:
| Option | Short | Description |
|--------|-------|-------------|
| --pull | -p | Pull from remote to local (default is push) |
| --delete | -d | Delete files not present in source |
| --dry-run | -n | Preview changes without executing |
| --exclude | -e | Exclude patterns (can be used multiple times) |
Watch Mode (2-Way Sync)
Monitor directories and sync changes bidirectionally in real-time.
sshcp watch <local> <remote> [options]
# Start watching (prompts on conflict - default)
sshcp watch ./src /var/www/app
# With bookmark
sshcp watch ./project @deploy
# Custom poll interval
sshcp watch ./src /app --interval 10
# Auto-resolve conflicts
sshcp watch ./src /app --on-conflict local # Always use local
sshcp watch ./src /app --on-conflict remote # Always use remote
sshcp watch ./src /app --on-conflict newer # Keep newer version
sshcp watch ./src /app -c skip # Skip conflictsOutput:
╭─────────── Watch Mode Active ───────────────────────╮
│ Local: /Users/me/project/src │
│ Remote: myserver:/var/www/app │
│ Mode: 2-way sync │
╰─────────────────────────────────────────────────────╯
Press Ctrl+C to stop
[12:34:56] → Updated: src/app.py
[12:35:10] ← Downloaded: config/settings.json
[12:35:20] ⚠ CONFLICT: data/cache.dbConflict Resolution:
When both local and remote versions of a file change, you'll see:
╭─────────────── ⚠ Conflict Detected ─────────────────╮
│ File: data/cache.db │
│ │
│ Local Remote │
│ Modified 2024-01-13 12:35 2024-01-13 12:34 │
│ Size 1.2 KB 1.3 KB │
│ │
│ Local is newer │
│ │
│ [L] Keep local [R] Keep remote [S] Skip [Q] Quit │
╰─────────────────────────────────────────────────────╯Options:
| Option | Short | Description |
|--------|-------|-------------|
| --interval | -i | Seconds between remote polling (default: 5) |
| --on-conflict | -c | Conflict resolution mode (default: ask) |
Conflict Resolution Modes:
| Mode | Description |
|------|-------------|
| ask | Prompt user for each conflict (default) |
| local | Always keep local version |
| remote | Always keep remote version |
| newer | Keep the newer version by timestamp |
| skip | Skip conflicting files |
Configuration
SSH Config
sshcp reads hosts from ~/.ssh/config:
Host prod
HostName 192.168.1.100
User deploy
IdentityFile ~/.ssh/id_rsa
Host staging
HostName staging.example.com
User admin
Port 22sshcp Config
Configuration is stored in ~/.config/sshcp/:
config.json- Selected serverbookmarks.json- Saved bookmarks
Requirements
- Python 3.10+
- OpenSSH (for
scpandsshcommands) - rsync (for sync command)
- SSH config file with configured hosts
License
MIT
