# Transfer Family CLI
A terminal UI (TUI) that lets you browse and transfer files on a remote SFTP server through **AWS Transfer Family** connector APIs. Use it when the remote host is only reachable from AWS (e.g. IP allowlist), so a normal SFTP client cannot connect directly.
## Overview
The CLI talks to AWS Transfer Family to list directories and move files. Listings and file data are staged in an S3 bucket you provide. You use familiar actions: list, change directory, download (get), and upload (put).
- **List** – Start a directory listing for the current remote path; results appear in the TUI.
- **Change directory** – Move into a subdirectory or up one level.
- **Get** – Download the selected remote file to your local download directory.
- **Put** – Upload a local file to the current remote directory.
## Prerequisites
- **AWS credentials** – Configured via environment, `~/.aws/credentials`, or `--profile`.
- **Transfer Family connector** – A connector ID (e.g. `c-01234567890abcdef`) that can reach your SFTP server.
- **S3 staging location** – A bucket and prefix (e.g. `my-bucket/transfer-cli/`) where the CLI can write listing results and stage file transfers. The connector must have read/write access to this location.
## Installation
From [crates.io](https://crates.io) (after the first publish):
```bash
cargo install transfer_family_cli
```
From this repo:
- From repo root: `cargo install --path domains/transfer_family_cli`
- From this directory: `cargo install --path .`
Run the CLI (requires `TRANSFER_CONNECTOR_ID` and `TRANSFER_S3_ROOT`, or `--connector-id` and `--s3-root`):
```bash
transfer-family-cli --help
```
To run the in-memory demo (no AWS credentials needed):
```bash
cargo run -p transfer_family_cli --example demo
```
## Building
From the repo root:
```bash
bazel build //domains/transfer_family_cli:transfer-family-cli
```
Run the binary:
```bash
bazel-bin/domains/transfer_family_cli/transfer-family-cli --help
```
Or from this directory with Cargo:
```bash
cargo build --release
./target/release/transfer-family-cli --help
```
## Configuration
Options can be set via **command-line flags** or **environment variables**.
| `--connector-id` | `TRANSFER_CONNECTOR_ID` | **(required)** AWS Transfer Family connector ID. |
| `--s3-root` | `TRANSFER_S3_ROOT` | **(required)** S3 location for staging: `bucket/prefix` (e.g. `my-bucket/transfer-cli/`). |
| `--region` | `AWS_REGION` | AWS region (default: `us-east-1` if unset). |
| `--profile` | `AWS_PROFILE` | AWS credentials profile name. |
| `--download-dir` | `TRANSFER_DOWNLOAD_DIR` | Local directory for downloaded files (default: `.`). |
Example:
```bash
transfer-family-cli \
--connector-id c-01234567890abcdef \
--s3-root my-transfer-staging/transfer-cli-staging/ \
--region us-east-1 \
--download-dir ~/Downloads
```
With environment variables:
```bash
export TRANSFER_CONNECTOR_ID=c-01234567890abcdef
export TRANSFER_S3_ROOT=my-transfer-staging/transfer-cli-staging/
transfer-family-cli
```
## Using the TUI
After startup you see the current remote path and connector in the header, the file/directory list, a status line, and a **command line** at the bottom (`> _`). Type commands there and press **Enter** to run them. Use **↑ / ↓** to move the selection in the list (e.g. to `get` the selected file or `cd` into the selected directory).
### Commands (familiar syntax)
| **ls** | List current remote directory (StartDirectoryListing → show results from S3). |
| **cd** | Change into the **selected** directory (use ↑/↓ first). |
| **cd <name>** | Change into a subdirectory by name (e.g. `cd foo`). |
| **cd ..** | Go up one directory. |
| **get** | Download the **selected** file to the local download directory. |
| **get <remote_path>** | Download a file by remote path (e.g. `get /path/to/file.txt`). |
| **put <local_path>** | Upload a local file to the current remote directory (e.g. `put ./myfile.txt`). **Put always requires a path.** |
| **rm** | Delete the **selected** file (use ↑/↓ first). A confirmation popup appears; press **y** to confirm or **n** / **Esc** to cancel. |
| **rm <remote_path>** | Delete a file by remote path (e.g. `rm /path/to/file.txt`). Same confirmation: **y** to confirm, **n** / **Esc** to cancel. |
| **rm <glob>** | Delete files in the current directory matching the glob (e.g. `rm *.txt`). Prompts for each matching file (**y** / **n** / **Esc**). |
| **mv <dest>** | Move the **selected** file to `dest` (use ↑/↓ first). |
| **mv <src> <dest>** | Move remote path `src` to `dest` (e.g. `mv /path/old.txt /path/new.txt`). |
| **quit** or **q** | Exit the CLI. |
### Keys
| **↑ / ↓** | Move selection in the file list. |
| **Enter** | Run the command typed in the command line. |
| **Esc** | Clear the command line; when a delete confirmation is shown, cancels the delete. |
| **Backspace** | Delete last character in the command line. |
### Status line
The line above the command line shows the last result (e.g. “Listing…”, “Download complete.”, “Put failed: …”) or the hint: `ls cd [dir|..] get [file] put <local> rm [file|glob] mv [src] dest quit`. While an operation is in progress, a spinner and message are shown.
## Staging layout in S3
Under the `s3_root` (bucket/prefix) you configure, the CLI uses:
- **Listings** – `{s3_root}listings/` – Directory listing JSON from StartDirectoryListing.
- **Retrieve (get)** – `{s3_root}retrieve/` – Files pulled from the remote server before you download them locally.
- **Send (put)** – `{s3_root}send/` – Local files uploaded here before being sent to the remote server.
Ensure the connector’s IAM role can read and write these paths in the bucket.
## Tests
From the repo root:
```bash
bazel test //domains/transfer_family_cli:rustfmt
```
From this directory:
```bash
cargo test
```
Unit tests cover listing JSON parsing and S3 path splitting; they do not call AWS.