Rclone — Structure#
Layout pattern#
Custom Plugin-Registry Layout (not standard Go layout)
Rclone uses a custom layout centered on a central registry (fs/registry.go) and two symmetrical “aggregator” packages (backend/all, cmd/all) that activate plugins via blank imports. The repo does not use a top-level internal/ or pkg/ directory; instead it uses lib/ for shared utilities and fs/ as the core abstraction layer. This is a deliberate architectural choice to support 70+ independently compiled backends without requiring every build to include every backend.
Directory map#
rclone/
├── rclone.go — Single main.go: imports all backends + commands via blank imports
├── go.mod / go.sum — Module definition
├── Makefile — Primary build system
├── Dockerfile — Multi-stage Docker build
├── VERSION — Version string (used in Makefile + LDFLAGS)
│
├── backend/ — 70+ cloud/protocol storage backends (each in its own package)
│ ├── all/ — Aggregator: blank-imports every backend to register them
│ ├── alias/ — Virtual: remaps a path in another remote
│ ├── archive/ — Virtual: transparent archive handling
│ ├── azureblob/ — Azure Blob Storage
│ ├── b2/ — Backblaze B2
│ ├── cache/ — Virtual: caching decorator
│ ├── chunker/ — Virtual: splits large files into chunks
│ ├── compress/ — Virtual: transparent compression
│ ├── crypt/ — Virtual: transparent encryption/decryption
│ ├── combine/ — Virtual: merges multiple remotes into one namespace
│ ├── drive/ — Google Drive
│ ├── dropbox/ — Dropbox
│ ├── ftp/ — FTP
│ ├── local/ — Local filesystem
│ ├── memory/ — In-memory (testing/transient)
│ ├── onedrive/ — Microsoft OneDrive
│ ├── s3/ — Amazon S3 (and S3-compatible APIs)
│ ├── sftp/ — SFTP
│ ├── union/ — Virtual: policy-based union of remotes
│ └── ... — ~55 more backends
│
├── cmd/ — CLI commands (one package per subcommand)
│ ├── all/ — Aggregator: blank-imports every command to register them
│ ├── cmd.go — Core CLI setup: cobra root command, global flags, Main()
│ ├── completion.go — Shell completion helpers
│ ├── copy/ — `rclone copy`
│ ├── sync/ — `rclone sync`
│ ├── move/ — `rclone move`
│ ├── ls* / — `rclone ls`, lsd, lsl, lsf, lsjson
│ ├── check/ — `rclone check`
│ ├── mount/ — `rclone mount` (FUSE, build-tag guarded)
│ ├── cmount/ — `rclone mount` via cgofuse
│ ├── mount2/ — Alternative FUSE mount implementation
│ ├── nfsmount/ — NFS mount
│ ├── serve/ — `rclone serve` subcommands:
│ │ ├── dlna/ — serve via DLNA/UPnP
│ │ ├── docker/ — Docker volume plugin
│ │ ├── ftp/ — serve as FTP server
│ │ ├── http/ — serve as HTTP server
│ │ ├── nfs/ — serve as NFS server
│ │ ├── restic/ — serve Restic REST API
│ │ ├── s3/ — serve as S3-compatible server
│ │ ├── sftp/ — serve as SFTP server
│ │ └── webdav/ — serve as WebDAV server
│ ├── rc/ — `rclone rc` (remote control client)
│ ├── rcd/ — `rclone rcd` (remote control daemon)
│ ├── bisync/ — `rclone bisync` (bidirectional sync)
│ ├── config/ — `rclone config` (interactive configuration)
│ ├── test/ — Development/debug subcommands
│ └── ... — ~30 more commands
│
├── fs/ — Core filesystem abstraction layer (the heart of rclone)
│ ├── fs.go — Core interfaces: Fs, Object, Directory
│ ├── registry.go — Backend registration (RegInfo, Register())
│ ├── features.go — Optional feature detection (Features struct)
│ ├── config/ — Configuration loading, flags, configmap, configstruct
│ ├── filter/ — Include/exclude filter rules
│ ├── operations/ — File operations: copy, check, dedupe, lsjson
│ ├── sync/ — Sync engine: sync.go, pipe.go
│ ├── march/ — Directory tree walking + pairing (two-tree sync)
│ ├── walk/ — Recursive directory listing
│ ├── accounting/ — Transfer stats, bandwidth throttling
│ ├── cache/ — Fs object cache (avoid re-creating remotes)
│ ├── hash/ — Hash type registry (MD5, SHA1, SHA256, etc.)
│ ├── fserrors/ — Error types (retriable, fatal, no retry)
│ ├── fspath/ — Remote path parsing ("remote:path")
│ ├── fshttp/ — Shared HTTP transport with retries/rate-limiting
│ ├── rc/ — Remote control API (JSON-RPC over HTTP)
│ ├── log/ — Structured logging
│ ├── logger/ — Per-file transfer logging
│ ├── asyncreader/ — Asynchronous read-ahead buffering
│ ├── chunkedreader/ — Chunked reads for large objects
│ ├── list/ — List helpers
│ ├── object/ — Object wrapper utilities
│ └── dirtree/ — Directory tree data structure
│
├── vfs/ — Virtual filesystem layer (FUSE, VFS-serve, mount)
│ ├── vfs.go — VFS struct: POSIX semantics over fs.Fs
│ ├── dir.go — VFS directory node
│ ├── file.go — VFS file node
│ ├── read.go — Read path
│ ├── write.go — Write path
│ ├── read_write.go — Read-write combined mode
│ ├── vfscache/ — Local disk cache for VFS writes
│ ├── vfscommon/ — Shared VFS options (VFSCommonOpt)
│ ├── vfsflags/ — CLI flags for VFS options
│ └── vfstest/ — Generic VFS test suite
│
├── lib/ — Shared utilities (no imports from cmd/ or backend/)
│ ├── rest/ — Generic REST client
│ ├── oauthutil/ — OAuth2 token management + web flow
│ ├── http/ — HTTP server framework (used by serve/*)
│ ├── pacer/ — Retry + rate-limit pacer (used by all backends)
│ ├── dircache/ — Directory ID cache (used by drive-like backends)
│ ├── encoder/ — Filename encoding/decoding for special characters
│ ├── errors/ — Error wrapping helpers
│ ├── multipart/ — Multipart upload helpers
│ ├── cache/ — Generic LRU cache
│ ├── kv/ — Key-value store (used by cache backend)
│ ├── batcher/ — Batch operations helper
│ ├── pool/ — Buffer pool
│ ├── readers/ — io.Reader utilities
│ ├── ranges/ — Byte range tracking
│ ├── atexit/ — Clean shutdown hooks
│ ├── systemd/ — Systemd notify integration
│ ├── daemonize/ — Process daemonization
│ ├── buildinfo/ — Version + build metadata
│ └── plugin/ — External plugin loader
│
├── librclone/ — C shared library + Gomobile bindings
│ ├── librclone/ — Core CGo export: RPC() and Initialize()
│ ├── gomobile/ — Gomobile-compatible wrapper
│ ├── ctest/ — C test program
│ ├── python/ — Python bindings example
│ └── php/ — PHP bindings example
│
├── fstest/ — Integration test infrastructure
│ ├── fstests/ — Generic backend test suite (runs against all backends)
│ ├── mockfs/ — Mock Fs for unit tests
│ ├── mockobject/ — Mock Object for unit tests
│ ├── mockdir/ — Mock Directory for unit tests
│ ├── test_all/ — Test runner for all backends
│ └── testserver/ — Test server helpers
│
├── cmdtest/ — CLI integration tests
├── contrib/ — External contributions (Docker plugin, Docker image)
├── bin/ — Build helper scripts
├── docs/ — Hugo-based documentation site
└── graphics/ — Logo assetsEntry points#
Rclone produces a single binary from the root rclone.go:
| File | Binary | Description |
|---|---|---|
rclone.go | rclone | The sole production binary — all commands and backends included via blank imports |
fstest/test_all/main.go | test_all | Test runner that executes the generic backend test suite against all real remotes |
cmd/test/info/internal/build_csv/main.go | (dev tool) | Development tool for building CSV data about backends |
All rclone subcommands (copy, sync, mount, serve webdav, etc.) are part of the same binary, selected via cobra subcommand dispatch. There is no multi-binary architecture.
The librclone/ packages do not have their own main.go; they produce a .so/.a C shared library via go build -buildmode=c-shared.
Package organization#
Internal packages: None — rclone does not use a top-level
internal/directory. All packages are importable in principle (though organized by convention).Public packages (lib/): The
lib/directory acts as the shared utilities layer. Key packages:lib/rest— Generic REST HTTP client with retrieslib/oauthutil— OAuth2 flows (used by drive, dropbox, onedrive, etc.)lib/pacer— Retry/backoff pacer used by every backendlib/dircache— Directory ID caching for hierarchical APIslib/encoder— Filename character encoding/escapinglib/http— HTTP server used by allrclone servecommandslib/rest— REST client used by most API-based backends
Layering: The architecture enforces a strict dependency direction:
cmd/* → fs/* → lib/* backend/* → fs/* → lib/* vfs/* → fs/* → lib/* cmd/* → vfs/* (for mount/serve) librclone/* → fs/rc (via JSON-RPC)Commands do not import backends directly. Backends register themselves into
fs.Registryviainit()in theirbackend/<name>/<name>.gofile, and thebackend/all/all.goaggregator triggers all registrations with a single blank import fromrclone.go.
Build system#
- Build tool: GNU Make +
go build - Key targets:
make/make rclone— Builds therclonebinary with version LDFLAGSmake test_all— Builds the multi-backend test runner- Various release targets for uploading betas to
beta.rclone.org - Build tags (
GOTAGS) control feature inclusion (e.g., FUSE support:cmount)
- Docker: Yes, multi-stage. Builder stage uses
golang:alpine+make. Final stage usesalpine:latestwithfuse3andca-certificates. CGO is disabled by default (ARG CGO_ENABLED=0), though FUSE backends require CGo.
Notable structural decisions#
Blank-import plugin registration: Backends and commands self-register via
init()functions. Thebackend/allandcmd/allaggregators are the only place that couples all plugins together. This allows building custom rclone binaries with a subset of backends by substituting or omitting the aggregator, with zero changes to backend code.cmd/as one-package-per-subcommand: Each rclone subcommand lives in its own directory (e.g.,cmd/copy/copy.go). Commands register themselves into cobra’s root command via their owninit(), keeping the command tree decentralized and the corecmd.gofile small.fs/as the abstraction kernel: Thefs/package is rclone’s core — it holds theFsandObjectinterfaces, the backend registry, configuration handling, operations engine, and the sync algorithm. It is the heaviest directory and functions as the project’s “kernel” that everything else depends on.vfs/as a POSIX adapter: Rather than baking POSIX semantics into individual backends, rclone provides a dedicated VFS layer that translates POSIX filesystem calls (read, write, seek, truncate) into object-storage operations. This VFS is shared between FUSE mounting, WebDAV serving, SFTP serving, and Docker volume plugin.librclone/as a lateral exit point: The C shared library exposes the entire rclone feature set via thefs/rcJSON-RPC API, not via direct function calls. This means the library interface is the same protocol asrclone rcd+rclone rc, keeping the embedded API and the daemon API identical without additional maintenance burden.No
vendor/directory: Rclone does not vendor its dependencies, relying on Go module proxy caching. Given the ~100 direct dependencies, vendoring would add significant repository weight.