transfer_family_cli 0.4.0

TUI to browse and transfer files via AWS Transfer Family connector
Documentation
# 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**.

| Option           | Env var                 | Description                                                                               |
| ---------------- | ----------------------- | ----------------------------------------------------------------------------------------- |
| `--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)

| Command                         | Description                                                                                                                          |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| **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

| Key           | Action                                                                           |
| ------------- | -------------------------------------------------------------------------------- |
| **↑ / ↓**     | 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.