Drivel is a Go FUSE filesystem that mounts a local directory as an
interceptor: every operation is proxied to a backing directory (the source of
truth) and asynchronously, bidirectionally synced with a storage provider. Two
backends ship: Google Drive, driven by the Drive API's changes.list cursor
feed — not webhooks, not the Workspace Events API — and SFTP, which has no change
feed of any kind and is therefore polled by the enumeration sweep. Each backend
runs in its own process.
New here? Architecture for what talks to what, then Workflows for how a write and a remote change actually travel. Fifteen minutes gets you oriented.
About to change sync? Conventions first. Echo suppression is the load-bearing correctness concern in this codebase and it is easy to regress without any test going red.
Writing a provider? Writing a provider. You should not need to touch anything outside your own package.
Just want it to build? Building and Testing.
Changing the website? The website. It renders docs/user/ by
mounting it, so editing the manual changes the site without anyone touching
site/.
| Architecture | Runtime components, package dependency graph, and what the seams enforce. |
| Workflows | Sequence and decision diagrams: outbound push, inbound pull, the sweep, hydration, shutdown. |
| Storage schema | The two bbolt databases, bucket by bucket, and the authority ladder. |
| Dependencies | Every direct dependency, why it is there, what was rejected, and what a change would cost. |
| Conventions | The rules that carry correctness — read before touching sync, hydration or uploads. |
| Building | Make targets, toolchain, lint, hooks, CI, running and debugging. |
| Testing | The suite, the kernel facilities it needs, platform runs, and the property tests. |
| Writing a provider | provider.Store and its optional interfaces, with a checklist. |
| Glossary | Echo, baseline, sweep, placeholder, seam, generation. |
| Multi-client test plan | The fleet-convergence campaign and its rig. |
| The website | How syshlted.github.io/drivel is built, why it mounts docs/user/ instead of copying it, and what generates its images. |
DESIGN.md and CLAUDE.md, both at the repo root, are internal working
documents rather than published documentation. DESIGN.md is the long-form
architectural record — every decision, its alternatives, and why they lost — and
the pages here cite it by section (DESIGN.md §4) when you need the argument
behind a rule rather than the rule. CLAUDE.md is the conventions file the
repo's agents and contributors work from.
Neither is maintained to the standard of the two published collections. Read them for reasoning, not for interface documentation.
| Package | Role |
|---|---|
cmd/drivel |
Entry point: flags, the flag→spec mapping, signal context. |
internal/app |
The composition root below main: one mount's lifecycle, N of them per process, and the cross-mount guards. |
internal/config |
The TOML config file. Knows nothing about any provider. |
internal/mount |
The mount-backend seam: Backend, Options, ResolveBacking. |
internal/vfs |
The go-fuse mount backend — loopback proxy that emits one event per mutation. |
internal/fsevent |
Backend-neutral change Event / Op types. |
provider |
Public. The backend seam: Store, the optional capabilities, the registry, and capability negotiation. |
ranges |
Public. Leaf value package: the block bitmap. No I/O. Public because RangePutter names it. |
plugin |
Public. Loading a backend that runs in its own process: discovery, the re-exec of a bundled one, the host-side proxy, and Serve. |
cmd/drivel-provider-* |
The backends as installable executables, each a three-line main around plugin.Serve. Not commands a user runs, and not in the default build — cmd/drivel bundles them. |
internal/provider/gdrive |
Google Drive. The only package that knows what a file ID is. |
internal/provider/gdrive/gdconf |
Drive's settings table and its two enumerated types — the vocabulary, without the SDK. |
internal/provider/sftp |
SFTP. Host key verification fails closed. |
internal/gauth |
Google OAuth: credential I/O and the interactive login flow. |
internal/transport |
HTTP/3 (QUIC) client with HTTP/2 fallback. |
internal/syncengine |
Outbound push (Engine), inbound pull (Downloader), and the enumeration sweep (reconcile.go). |
internal/state |
Engine-level bbolt state: cursor, echo records, sweep marks. |
internal/pathindex |
Provider-private bbolt path↔ID cache. |
internal/hydrate |
Lazy hydration: placeholders, the xattr marker, fault-in on first I/O. |
internal/completion |
Leaf, pure: renders the bash and zsh completion stubs and answers drivel __complete. |
internal/testenv |
Test-only: turns a silently-skipped kernel facility into a failure in CI. |
contrib/ |
Not a package — two //go:build ignore generators that derive the artwork and the website's images. See the website. |