A single Grove node โ one device running grove.py and web.py. Every cell has its own identity (keypair), storage, and dashboard. Your laptop, a Raspberry Pi, a VPS โ each is a cell.
All the cells you're connected to. Your personal distributed network.
Another cell in your fleet. Peers sync files, relay messages, and back each other up.
A peer you've promoted to friend status. Friends can share files with you (via grants). Non-friend peers can still store your encrypted chunks but can't share files with you.
A person with portal browser access but no cell of their own. Observers are provisioned automatically when a friend visits a portal page โ no password required on first entry. They can view files and folders that the cell owner has explicitly shared ("Show in Portal"), and use GroveAI at the friends tier. Observers cannot push chunks, modify grants, or access files not shared with them.
| Tier | Runs a cell? | Shares files? | Portal access? |
|---|---|---|---|
| Cell owner | Yes | Yes | Yes (full admin) |
| Friend | Yes | Yes (mutual grant) | Yes (friends tier) |
| Observer | No | No | Yes (read-only, scoped) |
A peer marked as a preferred sync target. Your chunks will always be synced to favorite peers first, regardless of speed ranking.
A 4MB piece of a file, encrypted with ChaCha20-Poly1305. Files are split into chunks for storage and transfer. Chunk filenames are their BLAKE2b hash (content-addressed).
A JSON file describing a complete file: its chunk hashes, encryption metadata, and (in v1) encrypted-at-rest sensitive fields (filename, source path). On-disk filenames are opaque: , where the content hash is derived from signable manifest fields. Manifests live in ~/.grove/manifests/. The v1 format (ยง7) ensures that even the filename of a shared file is not visible to chunk-holding peers.
A cryptographic permission to access a shared file. When you share a file with a peer, you create a signed grant containing the manifest hash, the encrypted file key, and your signature. Grants are verified using Ed25519 signatures.
The system's record of which chunks live on which peers. Used to decide where to replicate, what's under-replicated, and what's at risk. Stored in ~/.grove/placement.db (SQLite).
How many copies of each chunk exist across the fleet. Default desired factor: 2 (your cell + one peer). Configurable per-cell.
A WebSocket server that lets cells communicate when they can't reach each other directly (e.g., behind NAT). Cells connect to a relay and exchange messages through it. Relay operators can't read message contents (end-to-end encrypted).
How two cells communicate. Types:
100.x.x.x)200: / 201: / 202: addresses)192.168.x.x)A credit system for resource sharing. 1 bounty = 1 GB-month of chunk storage. Cells earn bounty daily by holding chunks for other peers; they spend bounty when peers hold their chunks. Tracked bilaterally in grove.db. "Blind bytes" (chunks held for unknown peers who haven't exchanged bilateral data) are also tracked and represent fleet contribution, not waste.
How extra storage drives attached to a cell contribute to Grove:
~/.grove/chunks)Your files in ~/GroveHome are the primary copy โ they stay on disk in plaintext. Encrypted chunks are generated from plaintext and replicated to peers; if a chunk is missing but the plaintext source exists locally, Grove regenerates the chunk on demand. This means GroveHome = 1 full replica even without any remote peers.
A 24-hour soft-delete window. When you delete a file from Grove, the manifest is marked pending_delete_at and the item appears in the Recycle Bin. After 24 hours (or manual confirmation), the manifest and chunks are permanently removed. The dashboard shows a banner when items are in the bin, and warns loudly when the countdown is under an hour.
The dashboard's ๐ Files tab โ your personal drive. Shows files you've uploaded to GroveHome, lets you browse folders, upload, download, share, and delete. Only your own files appear here; files shared by others appear in Feed.
The dashboard's ๐ก Feed tab โ incoming shares from friends. Shows files that friends have explicitly shared with you via grants. Feed is signal (what peers want you to see); Files is content (your drive).
A folder can carry a role that changes how Grove displays it instead of a plain file list. Roles: photos (gallery), notes (markdown reader), site (published web page), audio (music library), video (video library), and mixed (the default file list). Roles are inferred automatically โ a folder becomes audio or video when at least 3 of its files are that media type and they're at least half the folder โ and can be overridden manually ("show as music/video/files"). Overrides persist in folder_roles.json. The view that draws a role is its renderer; renderers run identically on the owner dashboard and the portal.
The shared renderer behind the audio and video roles. It presents a folder as a library + a single unified player (audio and video share one player), modeled on a music app's library tab. It is folder-derived: track titles come from the filename (a leading track-number prefix is stripped) and sub-folders become a nested tree โ there is no ID3/metadata tag reading. The player handles play/pause, seek, next/previous, shuffle, auto-advance, a lossless badge for FLAC/WAV/ALAC/AIFF, and fullscreen for video.
The byte-range delivery path that lets large media start and seek instantly. When a player requests a byte range (HTTP Range), Grove decrypts only the 4MB chunks that cover that range rather than the whole file, so seeking into a large FLAC or movie costs one or two chunk decrypts. The same spine serves both the audio and video renderers.
Two related things:
1. Browser-only access for people who don't run a cell. A friend can visit a cell's portal URL, log in as an Observer, and access files the owner has shared ("Show in Portal").
2. Owner WAN remote access โ the cell owner can provision their own portal account on a gateway cell (Settings โ Remote Access) to access their drive from outside Tailscale. Files in ~/GroveHome/Remote are auto-shared to the portal (the "Remote folder").
A cell with a public domain name (e.g. grove.nook.li) that serves invite links, the portal, and the WebSocket relay. Typically a VPS or a home server with nginx and a TLS cert. Grove cells use gateway_url in config to point at their gateway.
Built-in AI chat powered by local LLM inference via llama.cpp. Selects the cheapest-capable local model first (Low/Mid/High/Auto tiers), then escalates to a friend's cell if needed. Image generation is available on capable nodes (where the stable-diffusion binary and a Flux model are installed). AI-trust model: local-first by default; peer queries require a mutual-friend relationship and are E2E-encrypted.
Background process that runs every ~5 minutes. Probes all peers, checks for missing chunks, pulls/pushes data to maintain replication targets, records speed measurements, and runs health checks.
1. Upload โ File saved to GROVE_HOME (your file tree)
2. Chunk โ Split into 4MB chunks, encrypted with ChaCha20
3. Manifest โ JSON manifest created describing the file
4. Local storage โ Chunks stored in ~/.grove/chunks/{hash[:2]}/{hash}
5. Sync โ Opp sync pushes chunks to peers (speed-ranked)
6. Placement โ Placement DB tracks which peers hold which chunks
7. Healing โ If a peer goes offline, chunks re-replicate elsewhere
1. Select file โ Choose file(s) in Files tab (your drive)
2. Pick peers โ Select which friends to share with
3. Create grant โ Signed grant with encrypted file key
4. Push grant โ Grant sent to friend's cell
5. Friend sees it โ Appears in their ๐ก Feed tab (not their Files tab)
6. Friend downloadsโ Chunks pulled from your cell (or other holders)
~/.grove/ # Runtime directory (GROVE_DIR)
โโโ config.json # Cell configuration
โโโ node.key # Ed25519 private signing key
โโโ node.pub # Ed25519 public key
โโโ node_x25519.key # X25519 private key (for chat encryption)
โโโ node_x25519.pub # X25519 public key
โโโ .key # Master encryption key (256-bit)
โโโ peer_secret # Global shared secret for peer API auth (fallback)
โโโ dashboard_auth # Dashboard password hash
โโโ placement.db # SQLite: chunk placement tracking
โโโ grove.db # SQLite: bounty, grants, milestones, stats
โโโ peer_speeds.json # Recorded route speeds
โโโ peer_health.json # Peer uptime tracking
โโโ chunks/ # Encrypted chunk storage
โ โโโ ab/ # First 2 hex chars of BLAKE2b hash
โ โ โโโ ab3f7c... # Full hash filename
โ โโโ ...
โโโ manifests/ # File manifests (opaque <content_hash>.json names)
โ โโโ a1b2c3d4e5f6....json
โโโ invites/ # Created invite tokens
โโโ models/ # AI model files (.gguf)
โโโ assets/ # Frontend HTML/CSS/JS assets
โโโ grove.py # Core library
โโโ web.py # Web dashboard + API server
~/GroveHome/ # User file tree (GROVE_HOME); plaintext primary replica
โโโ Documents/
โโโ Photos/
โโโ Remote/ # Auto-shared to portal (Remote folder feature)
โโโ ... # Your actual files
โโโโโโโโโโโโ
โ Relay โ (WebSocket hub, optional)
โโโโโโฌโโโโโโ
โ
โโโโโโโโโโโผโโโโโโโโโโ
โ โ โ
โโโโโดโโโ โโโโโดโโโ โโโโโดโโโ
โ Cell โ โ Cell โ โ Cell โ
โ (Mac)โ โ (Pi) โ โ (VPS)โ
โโโโโโโโ โโโโโโโโ โโโโโโโโ
โ โ โ
Tailscale / Yggdrasil / LAN / WAN
Cells find the best route to each peer automatically. Routes are benchmarked every 6 hours and scored by throughput + latency.