The scout toolkit

Four small Rust tools for using Swarm — the decentralized storage network — without running a node. They share one foundation, the scout library, and cover the everyday things people actually do with storage: read, sync, publish, and keep secrets.

ToolCrateWhat it does
scoutswarm-scouta light client: read / write / feeds / encrypted sharing (CLI and library)
stashswarm-stashsync a folder ↔ Swarm — a feed-backed drive
perchswarm-perchpublish a folder as a website with a stable URL
keepswarm-keepan encrypted secrets/notes vault
cargo install swarm-scout swarm-stash swarm-perch swarm-keep

The "no-node" idea

Running a full Swarm (Bee) node means staking, syncing a reserve, and operating infrastructure. Most people who use Swarm don't want that — they want to fetch a file, publish a site, or back up a folder.

These tools split the two halves of that:

  • Reads (/bzz, /bytes, feeds) are served by any gateway — no node, stake, or stamp. By default they use the public Swarm gateway, so reading works out of the box.
  • Writes (uploads, feed updates, sharing) need a Bee node that holds a postage batch (a prepaid storage stamp). You point the tools at your own or a hosted node — "bring your own stamp."

See Getting started for both.

Who it's for / where you'd use them

  • App & script developersswarm-scout is a small library to read or write Swarm from a backend, CLI, bot, serverless function, or CI job, without the full node/client surface. stash/perch/keep are each ~150 lines on top of it — proof the library is the building block.
  • Site authorsperch hosts a static site, docs, or dapp frontend on Swarm with a link that survives redeploys (decentralized hosting).
  • Anyone who wants durable storagestash for folder backup/sync, keep for portable, client-side-encrypted secrets.

Status & caveats

All four are early (v0.1–v0.6), single-author, and verified end-to-end against a live Bee node (Sepolia testnet, Bee 2.7.2). They're not yet mainnet-hardened at scale, and keep's encryption (ChaCha20-Poly1305), while standard, is unaudited. Writes cost BZZ (postage). Treat them as solid, working building blocks rather than turnkey products.

Getting started

Install

cargo install swarm-scout swarm-stash swarm-perch swarm-keep
# binaries: scout, stash, perch, keep

Reading needs nothing

Reads default to the public Swarm gateway, so this works immediately:

scout cat <reference>          # print content
scout get <reference> out.bin  # download to a file

Override the read endpoint with --gateway / $BEE_GATEWAY to use your own node or a private gateway.

Writing needs a node + a postage batch

Uploading (and feeds, sharing, stash push, perch deploy, keep set) requires a Bee node that holds a postage batch. Two pieces:

  1. A node. Run Bee locally (defaults to http://localhost:1633) or use a hosted one. Point the tools at it with --node / $BEE_NODE.
  2. A postage batch. Buy one on the node — it prepays storage:
    curl -s -XPOST "$BEE_NODE/stamps/<amount>/<depth>"   # returns a batchID
    
    On a fresh testnet node a usable batch needs amount above the chain's current total and takes a couple of minutes to become usable. Pass the batch id with --stamp / $BEE_STAMP.
export BEE_NODE=http://localhost:1633
export BEE_STAMP=<batchID>
scout up notes.md          # -> a reference
perch deploy ./site        # -> a website URL

Environment variables

VarUsed byMeaning
BEE_GATEWAYall (reads)read endpoint (default: public gateway)
BEE_NODEall (writes)your Bee node for uploads (default: localhost:1633)
BEE_STAMPall (writes)postage batch id

Concepts in 30 seconds

  • Reference — a content address (hex). Immutable: same bytes → same ref.
  • Feed — a mutable pointer you own; the handle stays put while the content it serves changes. Powers stash/perch/keep's "latest version."
  • Postage batch — prepaid storage; required to upload.
  • ACT — Access Control Trie: encrypt content and grant/revoke specific recipients (used by scout share).

scout — the light client

scout is the foundation: a light client for Swarm as both a CLI and a library (swarm-scout). It does the four things the other tools build on — read, write, feeds, and encrypted sharing.

CLI

# read (no node)
scout cat   <ref> [path]        # print content (manifest-aware, /bzz)
scout get   <ref> <out> [path]  # download to a file
scout bytes <ref>               # raw bytes (/bytes)

# write (node + stamp)
scout up       <file> [--name n] --stamp <batch>
scout up-bytes <file>            --stamp <batch>
scout up-dir   <folder> [--index index.html] --stamp <batch>   # browsable collection

# feeds (a stable handle that serves the latest content)
scout keygen
scout publish <ref> --key <hex> -t <topic> --stamp <batch>     # -> feed handle
scout cat <feed-handle>                                         # read latest

# sharing (encrypted + revocable, via ACT)
scout share <file> --to <pubkey> --stamp <batch>   # -> a share id + refs
scout shares
scout grantees <id>
scout revoke <id> --grantee <pubkey> --stamp <batch>
scout fetch <file_ref> --publisher <pk> --history <h>   # recipient decrypts

Library

use scout::LiteClient;

#[tokio::main] async fn main() -> anyhow::Result<()> {
// read-only, via a gateway
let c = LiteClient::read("https://download.gateway.ethswarm.org")?;
let bytes = c.cat("<reference>").await?;

// add a write endpoint for uploads / feeds / sharing
let c = LiteClient::read("http://localhost:1633")?
    .with_write("http://localhost:1633", "<postage-batch>")?;
let r = c.up_bytes(b"hello".to_vec()).await?;
let handle = c.publish("<feed-key-hex>", "my-topic", &r).await?;
Ok(()) }

See examples/ and the API docs on docs.rs.

Where it fits

Reach for swarm-scout when a Rust project needs light Swarm I/O without operating a node — backends, CLIs, bots, serverless, CI, data tooling. stash, perch, and keep are all thin layers over it.

stash — folder sync

stash syncs a folder to Swarm and pulls it back anywhere. push uploads every file, records a path → reference index, and points a feed at it — so the printed handle is a stable address that always resolves to your latest push. A tiny content-addressed drive.

stash keygen                                          # a drive identity (save the key)
stash push <folder> --key <hex> -t <topic> --stamp <batch>   # -> a handle
stash ls   <handle>                                   # list files
stash pull <handle> <out-dir>                         # restore the folder

Re-pushing under the same key+topic updates what the same handle serves. ls/pull read from a gateway (no node); push needs a node + stamp.

Use cases

  • Backup / restore a working directory or config.
  • Versioned datasets or build artifacts — each push is content-addressed.
  • Dotfiles / small sync across machines (carry the key).

How it works

Each file is uploaded with scout, a JSON index maps paths to references, and a feed makes that index mutable behind one handle. Nothing stash-specific lives on Swarm — you could read the index and files with scout directly.

perch — publish a website

perch publishes a folder as a website on Swarm. deploy uploads it as a browsable Swarm collection (a mantaray manifest with an index document, so bzz/<ref>/ renders your site) and prints the reference; with a feed it gives a stable URL that survives re-deploys — "Netlify for Swarm."

# one-shot (the URL changes each deploy)
perch deploy ./site --stamp <batch>

# stable URL across re-deploys
perch keygen
perch deploy ./site --key <hex> -t <topic> --stamp <batch>
#   -> open  <gateway>/bzz/<handle>/  and re-deploy to update it

--index sets the default document (default index.html); nested assets resolve normally.

Use cases

  • Static sites & docs hosted decentrally (censorship-resistant).
  • Dapp frontends — pin your UI to Swarm with a durable address.
  • One-command publishing of a build output (./dist, ./public).

How it works

deploy is two scout calls: upload the directory as a native Swarm collection, then optionally point a feed at that manifest so one address always serves the latest deploy.

keep — encrypted vault

keep is an encrypted secrets/notes vault synced over Swarm. Your key/value pairs are encrypted client-side (ChaCha20-Poly1305) — only ciphertext ever reaches Swarm — and made mutable behind a feed, so the vault follows you across machines.

keep init --stamp <batch>                 # create a vault (~/.keep/keep.json)
keep set api-token s3cr3t --stamp <batch>
keep get api-token                        # -> s3cr3t  (read; no stamp)
keep list
keep rm  api-token --stamp <batch>

Use cases

  • CLI secret management — API tokens, keys, config secrets.
  • Portable notes/secrets across machines (copy the config).
  • A personal vault whose ciphertext is backed up on Swarm.

How it works & security

The vault is a JSON map encrypted under a key derived from a locally-stored secret (~/.keep/keep.json); the ciphertext is uploaded to Swarm and a feed points at the latest version. The config file is the only thing that can decrypt your vault — copy it to use the vault elsewhere; lose it and the data is unrecoverable, by design. Nothing readable is ever stored on Swarm.

The encryption (ChaCha20-Poly1305) is standard but unaudited; treat keep as a convenient personal vault, not a hardened secrets manager.