Opake#
/oʊˈpɑːk/ — like "opaque," but Dutch-flavored.
An encrypted personal cloud built on the AT Protocol.
Opake uses your existing PDS as a storage and identity layer. Files are encrypted client-side with AES-256-GCM before upload — the PDS only ever sees ciphertext. Custom lexicons under app.opake.* give structure to documents, encryption metadata, and sharing grants.
Your data is opaque to everyone without the key. That's the point.
Issue Tracker · Architecture · Lexicons
Install#
Requires Rust 1.75+.
cargo install --path crates/opake-cli
This puts opake in your ~/.cargo/bin/.
How It Works#
plaintext file
→ encrypt with random AES-256-GCM key
→ upload ciphertext blob to PDS
→ wrap content key to owner's DID public key
→ store metadata as app.opake.document record
No modifications to the PDS. All crypto happens on your machine.
Build From Source#
Requires Rust 1.75+.
git clone <repo-url>
cd opake.dev
cargo build --release
Produces two binaries: target/release/opake (CLI) and target/release/opake-appview (indexer/API server).
Usage#
# authenticate (resolves PDS automatically, uses OAuth by default)
opake login alice.example.com
# explicit PDS override
opake login alice.example.com --pds https://pds.example.com
# force legacy password-based auth
opake login alice.example.com --legacy
# log in to a second account
opake login bob.other.com
# list accounts and switch default
opake accounts
opake set-default bob.other.com
# upload a file (encrypts + uploads)
opake upload photo.jpg --tags vacation,beach
# upload into a directory
opake upload photo.jpg --dir Photos
# organize files into directories
opake mkdir Photos
opake tree
# list your documents
opake ls
opake ls --long
opake ls --tag vacation
# use a specific account for any command
opake ls --as alice.example.com
opake upload doc.pdf --as did:plc:alice123
# download and decrypt (your own files)
opake download photo.jpg
opake download photo.jpg -o ~/Downloads/copy.jpg
# print a file to stdout (decrypt without saving)
opake cat notes.txt
opake cat Photos/notes.txt
# download a shared file from another user (via grant URI)
opake download --grant at://did:plc:abc/app.opake.grant/tid123
# delete (supports paths and recursive directory deletion)
opake rm photo.jpg
opake rm Photos/photo.jpg
opake rm -r Photos
# move a file to another directory
opake move photo.jpg Photos/
# view or edit document metadata
opake metadata show photo.jpg
opake metadata rename photo.jpg vacation-photo.jpg
opake metadata tag add photo.jpg travel
opake metadata tag remove photo.jpg travel
opake metadata describe photo.jpg "Beach sunset from last summer"
opake metadata describe photo.jpg --clear
# resolve a handle or DID to see their public key
opake resolve alice.example.com
# share a file with another user
opake share photo.jpg alice.example.com
# list grants you've shared
opake shared
opake shared --long
# revoke a share grant
opake revoke at://did:plc:abc/app.opake.grant/tid123
# check incoming grants (via AppView)
opake inbox --appview https://appview.example.com
opake inbox --long
# keyring-based group sharing
opake keyring create family-photos
opake keyring ls
opake keyring add-member family-photos alice.example.com
opake upload photo.jpg --keyring family-photos
opake download --keyring-member at://did:plc:abc/app.opake.document/tid456
opake keyring remove-member family-photos alice.example.com
# transfer encryption identity to a new device
opake pair request # on the NEW device (polls for approval)
opake pair approve # on the EXISTING device (select + approve)
# delete all Opake data from PDS (see what would go)
opake purge --dry-run
# delete everything (prompts for confirmation phrase)
opake purge
# skip confirmation and also remove local identity
opake purge --force
# remove an account (defaults to only account if just one)
opake logout
opake logout bob.other.com
Commands accept a filename, a path (Photos/beach.jpg), or an at:// URI. If a filename matches multiple documents, you'll be prompted to use the full URI.
The --as flag works with document commands (upload, download, ls, rm, move, cat, tree, metadata, share, shared, revoke) and accepts a handle or DID.
AppView#
The AppView is a separate binary (opake-appview) that indexes grants and keyrings from the AT Protocol firehose and serves them via a REST API. It enables grant discovery — "what's been shared with me?" — without scanning every PDS in the network.
See docs/appview.md for configuration, authentication, API endpoints, and deployment.
Architecture#
Four crates + a web frontend:
opake-core— platform-agnostic library (compiles to WASM). Encryption, records, XRPC client, document operations,Storagetrait.opake-cli— CLI binary.FileStorage(filesystem-backed), command dispatch.opake-appview— Axum-based indexer and REST API. Jetstream firehose consumer, SQLite storage, DID-scoped Ed25519 auth.opake-derive— Proc-macro crate.RedactedDebugderive macro for secret-safe Debug output.web/— React SPA (Vite + TanStack Router + Tailwind/daisyUI). Usesopake-corevia WASM.IndexedDbStorage(IndexedDB-backed) implements the sameStoragetrait as the CLI.
See docs/ARCHITECTURE.md for the encryption model, crate structure, and design decisions. See docs/FLOWS.md for sequence diagrams of every operation.
Roadmap#
- CLI foundation (auth, upload, download, ls, rm)
- Client-side AES-256-GCM encryption
- Asymmetric key wrapping (x25519-hkdf-a256kw)
- Automatic token refresh
- Multi-account support (--as flag, logout, set-default, accounts)
- Public key auto-publish on login (app.opake.publicKey record)
- DID resolution and public key extraction
- Direct file sharing between DIDs
- Cross-PDS shared file download (via --grant flag)
- Grant listing (shared command)
- AppView indexer (grants + keyrings from firehose)
- AppView REST API with DID-scoped Ed25519 auth
- Folder hierarchy (mkdir, tree, path-aware rm/mv/cat/upload)
- Grant discovery (inbox command — queries AppView)
- Keyring-based group sharing
- Web UI — cabinet file browser (in progress, auth stubbed)
- AT Protocol OAuth (DPoP) for CLI and browser authentication
- Device-to-device identity pairing via PDS relay
- Seed phrase key derivation for multi-device
Development#
cargo test # run all Rust tests
cargo clippy # lint
cargo fmt # format
# web frontend
cd web
bun install # install deps
bun run wasm:build # build opake-core WASM module
bun run dev # start Vite dev server
bun run test # run Vitest suite
CI runs on Tangled via .tangled/workflows/test.yml.
See CONTRIBUTING.md for contribution guidelines.
Lexicons#
Custom AT Protocol schemas live in lexicons/. See lexicons/README.md for the full schema documentation and lexicons/EXAMPLES.md for annotated example records.