Metadata-Version: 2.4
Name: flyfile
Version: 0.1.0
Summary: Agent-native data transfer: push/pull/send anything between agents and machines
Requires-Python: >=3.10
Requires-Dist: fastapi>=0.110
Requires-Dist: flaxkv2>=0.2.14
Requires-Dist: httpx>=0.27
Requires-Dist: pyyaml>=6.0
Requires-Dist: typer>=0.12
Requires-Dist: uvicorn[standard]>=0.29
Requires-Dist: zstandard>=0.22
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Description-Content-Type: text/markdown

# flyfile

Agent-native data transfer. Push/pull anything (text, files, directories) through a central
server, or stream it directly client-to-client. Built for AI agents: JSON output everywhere,
stable exit codes, content-addressed dedup, burn-after-read.

```bash
pip install flyfile

# server (single worker; data lives in LMDB via flaxkv2)
flyfile serve --port 8632 --token SECRET

# client
export FLYFILE_SERVER=http://host:8632 FLYFILE_TOKEN=SECRET
echo "build log" | flyfile push - --name buildlog --tag ci --ttl 2h
flyfile push ./model.bin --reads 1            # burn after one read
flyfile push ./dataset/                       # dirs stream as tar, no temp files
flyfile ls --tag ci --json
flyfile preview k3x9m2pq                      # peek without consuming reads
flyfile pull k3x9m2pq -o ./model.bin

# client → client (server relays the stream, nothing is stored)
flyfile send ./results/          # prints: code: amber-falcon
flyfile recv amber-falcon        # on the other machine
```

## Agent contract

- **JSON everywhere**: `--json`, or automatic when stdout is not a TTY. Progress goes to
  stderr, data to stdout. Never prompts.
- **Exit codes (stable)**: 0 ok · 2 usage · 3 not found · 4 auth · 5 conflict ·
  6 expired/burned · 7 network (retryable) · 1 other.
- **Errors** are JSON on stderr: `{"error", "message", "retryable", "suggestion"}`.
- **Idempotent push**: content-addressed (sha256). Re-pushing the same bytes is instant
  (`"deduped": true`).
- **`flyfile preview <id>`** reads the head of an object (or a dir's file manifest)
  without downloading and without consuming burn-after-read counts.
- **`flyfile schema [cmd]`** dumps the command tree as JSON for introspection.
- **`flyfile send --json`** emits NDJSON events; the `code` event arrives before the
  transfer starts, so an agent can hand it to the receiver immediately.

## Design notes

- Storage is [flaxkv2](https://github.com/KenyonY/flaxkv) (LMDB): metadata and 8 MiB
  content chunks in one env. The LMDB file does not shrink after deletes (free pages are
  reused; file size ≈ historical peak).
- Compression (zstd-3) happens on the *client*; the server stores/relays compressed bytes.
  Each 8 MiB chunk of a large upload is an independent zstd frame, so parallel upload,
  resume, and parallel download all work per-chunk.
- Burn-after-read: the read is claimed atomically when chunk 0 (or `/content`) is fetched.
  Later chunks of an in-flight parallel download are served during a grace period
  (default 15 min) even after the object burns.
- Run exactly **one** uvicorn worker: relay pairing and the burn-claim lock are in-process.

## Development

```bash
uv venv && uv pip install -e ".[dev]"
.venv/bin/pytest
scripts/bench.sh   # 1 GiB loopback throughput smoke test
```
