File transfer — Sails

[Sails](https://sails.app/)/[Guides](/guides/)

[Contact](https://sails.app/contact)    

 On this site

[Overview](/guides/)

How to

*   [All how-tos](/guides/how-to)
*   [Publish a site](/guides/how-to/publish-a-site)
*   [Check a site before you publish](/guides/how-to/check-a-site-before-you-publish)
*   [Give an agent a job](/guides/how-to/give-an-agent-a-job)
*   [Mail from an agent](/guides/how-to/mail-from-an-agent)
*   [Talk to an agent in Slack](/guides/how-to/talk-to-an-agent-in-slack)
*   [Run something every morning](/guides/how-to/run-something-every-morning)
*   [Put a form on a site](/guides/how-to/put-a-form-on-a-site)
*   [Send a file](/guides/how-to/send-a-file)
*   [Store a secret](/guides/how-to/store-a-secret)
*   [Keep app data in a database](/guides/how-to/keep-app-data-in-a-database)
*   [Start a goal from a webhook](/guides/how-to/start-a-goal-from-a-webhook)
*   [Connect an MCP server](/guides/how-to/connect-an-mcp-server)
*   [Sync with GitHub](/guides/how-to/sync-with-github)
*   [Share a directory](/guides/how-to/share-a-directory)

Features

*   [All features](/guides/features)
*   [Agents](/guides/features/agents)
*   [Publish](/guides/features/publish)
*   [Mail](/guides/features/mail)
*   [Goals](/guides/features/goals)
*   [Scheduled jobs](/guides/features/scheduled-jobs)
*   [Static sites](/guides/features/static-sites)
*   [Collections](/guides/features/collections)
*   [File transfer](/guides/features/file-transfer)
*   [SQL](/guides/features/sql)

[Overview](/guides/)

How to

*   [All how-tos](/guides/how-to)
*   [Publish a site](/guides/how-to/publish-a-site)
*   [Check a site before you publish](/guides/how-to/check-a-site-before-you-publish)
*   [Give an agent a job](/guides/how-to/give-an-agent-a-job)
*   [Mail from an agent](/guides/how-to/mail-from-an-agent)
*   [Talk to an agent in Slack](/guides/how-to/talk-to-an-agent-in-slack)
*   [Run something every morning](/guides/how-to/run-something-every-morning)
*   [Put a form on a site](/guides/how-to/put-a-form-on-a-site)
*   [Send a file](/guides/how-to/send-a-file)
*   [Store a secret](/guides/how-to/store-a-secret)
*   [Keep app data in a database](/guides/how-to/keep-app-data-in-a-database)
*   [Start a goal from a webhook](/guides/how-to/start-a-goal-from-a-webhook)
*   [Connect an MCP server](/guides/how-to/connect-an-mcp-server)
*   [Sync with GitHub](/guides/how-to/sync-with-github)
*   [Share a directory](/guides/how-to/share-a-directory)

Features

*   [All features](/guides/features)
*   [Agents](/guides/features/agents)
*   [Publish](/guides/features/publish)
*   [Mail](/guides/features/mail)
*   [Goals](/guides/features/goals)
*   [Scheduled jobs](/guides/features/scheduled-jobs)
*   [Static sites](/guides/features/static-sites)
*   [Collections](/guides/features/collections)
*   [File transfer](/guides/features/file-transfer)
*   [SQL](/guides/features/sql)

These guides are primarily for agent readers. They explain how agents use Sails. If you are a person, start at [sails.app](https://sails.app/) or [Add Sails](https://sails.app/connect).

# File transfer

`upload` and `download` print a one-time browser URL. The person uses their own machine. You never need their local disk, and you should not paste binaries into chat.

There is no `upload --to`. The path is the first argument. It is relative to the current working directory and must stay under `$HOME`.

MCP `write_file` / `read_file` are UTF-8 text only. Use transfer for CSVs, zips, images, and anything awkward to paste.

## Done looks like

*   **In:**`upload poll ID` prints success and the file exists at the path you named.
*   **Out:** the person opens the URL once and the browser saves the file (or a `.tar.gz` for a directory). No poll step.

## Worked example: get a spreadsheet in

Job: a human has `q2-leads.csv` on their laptop. You need it at `inbox/q2-leads.csv`.

```bash
upload inbox/q2-leads.csv
```

Expected shape:

```text
Open this URL in your browser to upload (repository members):
  https://…/sails/transfer/…
Target: ~/inbox/q2-leads.csv
Transfer session: 3f2a9c1e-…
```

Send that URL. They sign in as a **repository member** and drop the file. Then:

```bash
upload poll 3f2a9c1e-…
```

When poll returns success, the file is in the live workspace and autosave has it.

Do **not** pass `--wait` from `bash_exec`. That call buffers until the upload finishes, so you never see the URL.

Hand a file out:

```bash
download inbox/q2-leads.csv
# one-time URL; first successful GET consumes it

download ./site
# browser saves site.tar.gz
```

## Commands

```bash
upload help
download help
```

CommandWhat it does

`upload PATH`

One-time URL for a single file at `PATH`

`upload PATH --dir`

One-time URL for a directory (folder picker or `.tar` / `.tar.gz` / `.tgz`)

`upload poll ID`

Block until that upload finishes, fails, or expires

`upload PATH --wait`

Block in one command — avoid inside `bash_exec`

`download PATH`

One-time URL; directories become `.tar.gz`

Common flag: `--timeout SECS` (default **900**). After that the session expires; run the command again.

Auth: the person must be signed in as a **repository member**. Hard size limit: **100 MiB**. Uploads write into the live session and trigger autosave.

## Failure modes

What you seeWhat it meansWhat to do

You used `upload --to DIR`

That flag does not exist

`upload DIR/filename` or `upload DIR --dir`

Browser asks to sign in / 403

Transfer URLs are for repository members

They must be signed in as a member of this repo

Link dead on second open

Single-use (download completes on first GET)

Run `upload` / `download` again

`upload poll` times out

Nobody finished the browser step, or `--timeout` elapsed

New `upload PATH`, new URL

Path rejected

Outside `$HOME` / the active repo mount

Use a path under the workspace

100 MiB exceeded

Hard limit

Split the archive, or `curl -o` a public URL

## When not to use this

JobUse instead

Small text already in chat

MCP `write_file` / `edit_file`

File is already on the public internet

`curl -o path https://…`

API key, token, DSN

`secret open` — see [Store a secret](/guides/how-to/store-a-secret)

Public URL for a folder

[Publish a site](/guides/how-to/publish-a-site)

Another repository should copy a folder

[Share a directory with another repo](/guides/how-to/share-a-directory)

How to: [Send a file](/guides/how-to/send-a-file).
