# fs0

<p align="center">
  <img src="docs/fs0.png" alt="fs0" width="160">
</p>

<p align="center">
  Distributed storage written in Rust.
</p>

<p align="center">
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></a>
  <img src="https://img.shields.io/badge/version-0.2.0-brightgreen.svg" alt="Version 0.2.0">
  <img src="https://img.shields.io/badge/rust-2024-orange.svg" alt="Rust 2024">
</p>

**fs0** is a distributed filesystem prototype with a central metadata service, storage nodes, local volumes, compressed chunks, content hashing, and a single CLI for operating files and local nodes.

## Features

- Central metadata service
- Storage node process backed by local volumes
- Chunked file upload and download
- Zstandard compression
- BLAKE3 content hashing
- Iroh-based transport layer
- JSON output for scripting where supported
- Rust 2024 workspace split into reusable crates

## Installation

Build the CLI:

```bash
cargo build --release -p fs0-cli
```

Run from the workspace:

```bash
cargo run -p fs0-cli -- --help
```

Install from the checkout:

```bash
cargo install --path crates/fs0-cli
```

The installed binary is named `fs0`.

## Configuration

`fs0` reads `~/.fs0/config.toml` by default. Use `--config <PATH>` to load a different file.

A local test config has been generated in this checkout at:

```text
.local/fs0-test/config.toml
```

Copy it to `~/.fs0/config.toml` if you want the CLI to use it without passing `--config`.

That file is ready for local testing after replacing these placeholders with values printed/generated by `fs0 central run`:

- `REPLACE_WITH_CENTRAL_ENDPOINT_ID_FROM_CENTRAL_RUN`
- `REPLACE_WITH_RELAY_CA_CERT_FROM_CENTRAL_RUN`

The generated local config uses:

- central DB: `.local/fs0-test/central.sqlite`
- relay cert/key: `.local/fs0-test/relay-cert.pem`, `.local/fs0-test/relay-key.pem`
- storage volume: `.local/fs0-test/volume-1`
- token: `local-test-token`
- central address: `127.0.0.1:7800`
- relay HTTPS: `127.0.0.1:7801`
- relay QUIC: `127.0.0.1:7802`
- storage bind port: `3341`

## Local Test Commands

These commands are for manual local testing. They are listed here only; they are not executed by the setup.

Build:

```bash
cargo build -p fs0-cli
```

Install the generated config as your default local config:

```bash
mkdir -p ~/.fs0
cp .local/fs0-test/config.toml ~/.fs0/config.toml
```

Start central in one terminal:

```bash
target/debug/fs0 central run
```

Copy the central endpoint id and relay CA certificate printed/generated by central into `~/.fs0/config.toml`, replacing the placeholder values.

Create and register a local volume:

```bash
target/debug/fs0 storage create-volume .local/fs0-test/volume-1 \
  --name local-volume-1 \
  --max-bytes 4G
```

Inspect the volume:

```bash
target/debug/fs0 storage inspect-volume .local/fs0-test/volume-1
```

Start storage in a second terminal:

```bash
target/debug/fs0 storage run
```

Prepare a local file:

```bash
printf 'hello fs0\n' > .local/fs0-test/hello.txt
```

Upload and inspect:

```bash
target/debug/fs0 put /hello.txt .local/fs0-test/hello.txt
target/debug/fs0 ls /
target/debug/fs0 stat /hello.txt
target/debug/fs0 peers
```

Download:

```bash
target/debug/fs0 get /hello.txt .local/fs0-test/hello.downloaded.txt
diff .local/fs0-test/hello.txt .local/fs0-test/hello.downloaded.txt
```

Copy, move, delete, and inspect change logs:

```bash
target/debug/fs0 cp /hello.txt /copy.txt
target/debug/fs0 mv /copy.txt /renamed.txt
target/debug/fs0 rm /renamed.txt
target/debug/fs0 changes
```

## CLI Reference

Global options:

| Option | Description |
|---|---|
| `--config <PATH>` | Config file path. Defaults to `~/.fs0/config.toml`. |
| `--json` | Print JSON output where supported. |

Top-level commands:

| Command | Description |
|---|---|
| `fs0 ls [DIR]` | List a remote directory. |
| `fs0 stat <REMOTE_PATH>` | Show remote file metadata and read plan. |
| `fs0 get <REMOTE_PATH> <LOCAL_PATH>` | Download a remote file. |
| `fs0 put <REMOTE_PATH> <LOCAL_PATH>` | Upload a remote file. Use `-` as local path to read from stdin. |
| `fs0 rm <REMOTE_PATH>` | Delete a remote file. |
| `fs0 cp <SOURCE_PATH> <TARGET_PATH>` | Copy a remote file. |
| `fs0 mv <SOURCE_PATH> <TARGET_PATH>` | Move or rename a remote file. |
| `fs0 changes` | List central file change events. |
| `fs0 peers` | Show known storage peers. |
| `fs0 central run` | Run a central metadata server. |
| `fs0 storage run` | Run a storage node. |
| `fs0 storage create-volume <PATH>` | Create and register a local volume. |
| `fs0 storage inspect-volume <PATH>` | Inspect local volume metadata. |

Command arguments and options:

| Command | Arguments | Options | Defaults |
|---|---|---|---|
| `fs0 ls` | `[DIR]` | `--limit <N>`, `--cursor <CURSOR>` | `DIR=/`, `limit=100` |
| `fs0 stat` | `<REMOTE_PATH>` | none | none |
| `fs0 get` | `<REMOTE_PATH> <LOCAL_PATH>` | none | none |
| `fs0 put` | `<REMOTE_PATH> <LOCAL_PATH>` | `--prefer-volume <NAME>` | none |
| `fs0 rm` | `<REMOTE_PATH>` | none | none |
| `fs0 cp` | `<SOURCE_PATH> <TARGET_PATH>` | none | none |
| `fs0 mv` | `<SOURCE_PATH> <TARGET_PATH>` | none | none |
| `fs0 changes` | none | `--cursor <CURSOR>`, `--limit <N>` | `cursor=0`, `limit=100` |
| `fs0 peers` | none | none | none |
| `fs0 central run` | none | `--config <PATH>` | `~/.fs0/config.toml` |
| `fs0 storage run` | none | `--config <PATH>` | `~/.fs0/config.toml` |
| `fs0 storage create-volume` | `<PATH>` | `--config <PATH>`, `--name <NAME>`, `--max-bytes <SIZE>` | none |
| `fs0 storage inspect-volume` | `<PATH>` | none | none |

Supported size suffixes for `--max-bytes`: `K`, `M`, `G`, `T`. Volumes must be at least `4G`.

## License

MIT
