restic — API Surface#
API types#
CLI only. restic is a single-binary command-line tool. It exposes no HTTP server, no gRPC service, and no public Go library API. All packages live under internal/ — intentionally unexported. The only external-facing surface is:
- The CLI (cobra commands + pflag flags)
- The REST server protocol (restic is a REST client; it talks to a separate
rest-serverbinary) - Exit codes (documented and meaningful)
- JSON output mode (machine-readable structured stdout for most commands)
CLI#
Framework#
- Framework:
github.com/spf13/cobra+github.com/spf13/pflag - Registration pattern: Each command lives in its own file (
cmd_backup.go, etc.) and exposes a constructornewBackupCommand(globalOptions *global.Options) *cobra.Command. All constructors are called inmain.go:newRootCommand()via a singlecmd.AddCommand(...)block. - Flag pattern: Every command’s options live in a dedicated
<Command>Optionsstruct with anAddFlags(f *pflag.FlagSet)method. Global flags are registered viaglobalOptions.AddFlags(cmd.PersistentFlags())and are persistent (inherited by all subcommands). - Three optional commands are conditionally registered:
mount(FUSE, Linux/macOS only),debug(debug build tag),self-update(separate build tag). Each has a disabled stub (cmd_*_disabled.go) that registers a helpful error message on unsupported platforms.
Command structure#
Top-level commands (28 total)#
Core backup/restore:
| Command | Usage | Description |
|---|---|---|
backup | backup [flags] [FILE/DIR]... | Create a new backup snapshot |
restore | restore [flags] snapshotID | Restore a snapshot to target directory |
snapshots | snapshots [flags] [snapshotID...] | List all snapshots |
ls | ls [flags] snapshotID [dir...] | List files in a snapshot |
diff | diff [flags] snapshotID snapshotID | Show differences between two snapshots |
dump | dump [flags] snapshotID file | Dump file contents from a snapshot to stdout |
find | find [flags] PATTERN... | Find files in snapshots matching patterns |
mount | mount [flags] mountpoint | Mount snapshots as a FUSE filesystem (Linux/macOS) |
Repository management:
| Command | Usage | Description |
|---|---|---|
init | init | Initialize a new repository |
check | check [flags] | Verify repository integrity |
prune | prune [flags] | Remove unreferenced data from repository |
forget | forget [flags] [snapshot ID]... | Remove snapshots per retention policy |
copy | copy [flags] [snapshotID...] | Copy snapshots to another repository |
rewrite | rewrite [flags] [snapshotID...] | Modify snapshots (exclude paths) |
tag | tag [flags] [snapshotID...] | Modify tags of snapshots |
unlock | unlock | Remove stale repository locks |
recover | recover [flags] | Find and save unattached snapshot trees |
migrate | migrate [flags] [name]... | Run repository format migrations |
Key management:
| Command | Subcommand | Description |
|---|---|---|
key | list | List encryption keys |
key | add | Add a new encryption key |
key | remove [ID] | Remove an encryption key |
key | passwd | Change the password for a key |
Repair commands:
| Command | Subcommand | Description |
|---|---|---|
repair | index [flags] | Repair repository index |
repair | packs [packIDs...] | Repair pack files |
repair | snapshots [flags] [snapshot ID]... | Repair snapshot metadata |
Utility/informational:
| Command | Usage | Description |
|---|---|---|
cat | cat [flags] [type] [ID] | Dump raw object (masterkey, config, pack, blob, snapshot, index, key, lock, tree) |
list | list [flags] [type] | List repository objects by type |
stats | stats [flags] [snapshot ID]... | Scan repository for statistics |
cache | cache | Operate on local cache |
generate | generate [flags] | Generate man pages / shell completion |
options | options | List all available extended options |
features | features | List feature flags and their states |
version | version | Print version information |
self-update | self-update [flags] | Update restic binary in place |
debug | debug dump / debug examine | Internal debug commands (debug builds only) |
Deprecated command (kept for compat):
rebuild-index— alias forrepair index
Global flags (persistent — all commands)#
All defined in internal/global/global.go:Options.AddFlags():
| Flag | Short | Env var | Purpose |
|---|---|---|---|
--repo | -r | RESTIC_REPOSITORY | Repository location (URL or path) |
--repository-file | RESTIC_REPOSITORY_FILE | File containing repository location | |
--password-file | -p | RESTIC_PASSWORD_FILE | File containing repository password |
--password-command | RESTIC_PASSWORD_COMMAND | Shell command to obtain password | |
--key-hint | RESTIC_KEY_HINT | Key ID to try first | |
--quiet | -q | Suppress progress output | |
--verbose | -v | Increase verbosity (repeatable: -vv) | |
--json | Output in JSON format | ||
--no-lock | Skip repository locking (read-only safe) | ||
--no-cache | Disable local cache | ||
--cache-dir | Custom cache directory | ||
--cleanup-cache | Auto-remove old cache entries | ||
--cacert | RESTIC_CACERT | Root CA certificate files | |
--tls-client-cert | RESTIC_TLS_CLIENT_CERT | TLS client certificate | |
--insecure-tls | Skip TLS verification (insecure) | ||
--insecure-no-password | Use empty password (insecure) | ||
--limit-upload | Upload rate limit (KiB/s) | ||
--limit-download | Download rate limit (KiB/s) | ||
--option / -o | Extended backend options (k=v) | ||
--http-user-agent | Custom HTTP User-Agent | ||
--no-extra-verify | Skip pre-upload data verification | ||
--compression | Compression level (off, auto, max) | ||
--pack-size | RESTIC_PACK_SIZE | Target pack file size (MiB) |
Notable command flags#
backup — key flags:
--parent snapshot— use specific parent for delta comparison--force/-f— force full re-read (ignore parent)--exclude PATTERN/--include PATTERN— glob-based file filtering--exclude-if-present filename[:header]— directory exclusion by marker file--exclude-caches— auto-exclude CACHEDIR.TAG directories--exclude-larger-than SIZE— size-based exclusion--one-file-system/-x— no cross-filesystem traversal--stdin— backup from stdin--stdin-from-command— backup stdout of a command--files-from FILE— read target list from file--tag TAG— attach tags to snapshot--host/-H— override hostname in snapshot metadata--time TIMESTAMP— override backup timestamp--with-atime— include access time--ignore-inode/--ignore-ctime— change detection tuning--dry-run/-n— show what would be done--read-concurrency N— parallel file readers--skip-if-unchanged— skip if snapshot is identical to parent--use-fs-snapshot— use VSS (Windows) / APFS snapshots
forget — retention policy flags:
--keep-last N/-l— keep N most recent (orunlimited)--keep-hourly N/-H— keep N hourly--keep-daily N/-d— keep N daily--keep-weekly N/-w— keep N weekly--keep-monthly N/-m— keep N monthly--keep-yearly N/-y— keep N yearly--keep-within DURATION— keep all within duration (e.g.1y5m7d2h)--keep-within-hourly/daily/weekly/monthly/yearly DURATION— keep granular within duration--keep-tag TAGLIST— keep snapshots with matching tags--group-by HOST,PATHS,TAGS/-g— grouping key for policy application (default: host,paths)--unsafe-allow-remove-all— required safety flag to delete all snapshots--prune— automatically run prune after removing snapshots--dry-run/-n— preview only
restore — key flags:
--target/-t— target directory--include/--exclude PATTERN— partial restore--host/--path/--tag— snapshot selection filters--verify— verify restored files--delete— delete extra files not in snapshot--overwrite POLICY— overwrite policy (always, if-changed, if-newer, never)
copy — key flags:
--repo2/-2/RESTIC_REPOSITORY2— destination repository--password-file2/RESTIC_PASSWORD_FILE2— destination password- Applies the standard snapshot filter flags
Flag binding pattern#
Every backend scheme supports --option key=value extended options (collected by global.Options). Examples:
s3.bucket-lookup,s3.unsafe-anonymous-auth,s3.enable-restoresftp.command,sftp.argsrest.connections
These are parsed by internal/options and applied to driver config structs via options.ApplyEnvironment.
Output modes#
Human-readable (default): Progress bars, tables, human-friendly sizes.
JSON (--json global flag): Structured JSON output for machine consumption. Each command emits typed JSON objects with a message_type discriminator field. Supported by: backup, check, copy, diff, find, forget, ls, prune, restore, snapshots, stats. Error output also becomes structured JSON ({"message_type":"exit_error","code":N,"message":"..."}).
Exit codes#
Documented and stable — designed for scripting:
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Generic error |
| 3 | Incomplete operation (e.g. source data error during backup, failed snapshot removal) |
| 10 | No repository found |
| 11 | Repository already locked |
| 12 | Wrong password / no valid key found |
| 130 | SIGINT / context cancelled |
REST server protocol (restic as HTTP client)#
restic is not an HTTP server. However, its rest backend implements a well-defined HTTP protocol for talking to a compatible server (e.g. the rest-server project). Understanding this matters because third-party servers must implement these endpoints.
URL structure (from layout_rest.go and rest.go):
POST {base}/ -- create repository (version negotiation)
HEAD {base}/{type}/{id} -- check object existence
GET {base}/{type}/{id} -- read full object
GET {base}/{type}/{id} (Range header) -- read partial object
POST {base}/{type}/{id} -- write object
DELETE {base}/{type}/{id} -- delete object
GET {base}/{type}/ -- list objects of type (v1: JSON array, v2: NDJSON)
GET {base}/config -- read repository configType paths:
data/— pack files (encrypted data)snapshots/— snapshot metadataindex/— index fileslocks/— lock fileskeys/— encryption key filesconfig— repository configuration (no directory)
Protocol versions: v1 (list returns JSON array) and v2 (list returns NDJSON, one file per line). Version negotiated at Create time via query parameter.
Plugin / Extension system#
Backend extension point#
The primary extension point is the backend registry (internal/backend/location.Registry). Adding a storage backend requires:
- Implement
backend.Backendinterface - Implement
location.Factoryinterface withScheme() string,ParseConfig(s string) (Config, error),Open(ctx, cfg, rt, errLog) (Backend, error),Create(ctx, cfg, rt, errLog) (Backend, error) - Register via
registry.Register(factory)
All 9 built-in backends (azure, b2, gs, local, rclone, rest, s3, sftp, swift) use this mechanism. Registered at startup in backend/all/all.go.
The decorator wrappers (cache, retry, logger, sema, limiter, dryrun) are composed at startup in internal/global/global.go:wrapBackend() — they are not runtime-pluggable, but the backend.Unwrapper interface and backend.AsBackend[T]() generic function allow introspection through the decorator chain.
Feature flags extension point#
internal/feature provides a simple flag registry. Flags are defined at compile time in registry.go, but their enabled/disabled state is configurable at runtime via the RESTIC_FEATURES environment variable. This allows gradual rollout of new behavior (Alpha → Beta → Stable → (removal)).
Current flags (as of analysis):
backend-error-redesign(Beta) — new HTTP timeout/error handlingdeprecate-legacy-index(Stable) — drop support for 0.1.0 index formatdeprecate-s3-legacy-layout(Stable) — drop support for pre-0.7.0 S3 layoutdevice-id-for-hardlinks(Alpha) — reduced metadata churn for btrfsexplicit-s3-anonymous-auth(Stable) — require explicit anonymous S3 opt-insafe-forget-keep-tags(Stable) — safety check for--keep-tagwith nonexistent tagss3-restore(Alpha) — restore from S3 cold storage
rclone backend as a meta-extension#
The rclone backend (internal/backend/rclone) is unique: it shells out to the rclone binary, passing arguments via a private REST-like protocol over rclone serve restic. This effectively gives restic access to every storage provider that rclone supports (~40+) without native implementation.
Library API (if applicable)#
None. All packages are under internal/. restic explicitly does not offer a public Go API for embedding. The design rationale (visible from the architecture) is that restic manages encryption keys, repository locking, and data integrity — exposing these as a library would require callers to handle these invariants correctly. The CLI is the only supported interface.
The closest thing to a library interface is the backend.Backend interface in internal/backend, but it is internal-only.
Notable API design observations#
Global-options-as-configuration-carrier:
global.Optionsis passed by pointer frommain()through cobra’sPersistentPreRunEto every command. Commands receive it as a constructor argument rather than via a global variable. This is explicit dependency passing within a CLI framework that could easily have used package-level globals.Consistent snapshot filter flags: Commands that operate on snapshots (
forget,restore,copy,rewrite,ls,snapshots,tag,find) share a commonSnapshotFilterstruct with identical--host,--path,--tagflags, wired viainitMultiSnapshotFilter(). This is a rare example of deliberate API consistency across CLI subcommands.--dry-runis pervasive:backup,forget,prune,rewrite, andrestore(via--verify) all support dry-run modes. This is intentional for a backup tool where destructive operations need safe preview.Structured JSON output as a first-class API: The
--jsonflag transforms restic from a human-readable CLI into a structured data source. The JSON schema is stable enough that tools likeresticprofileand Prometheus exporters build on it. Each command’s JSON output uses typedmessage_typediscriminators — a clean approach to multiplexing different event types on a single stream.Extended options (
-o key=value) as an escape hatch: Backend-specific options that don’t warrant global flags are routed through--option. Theoptionscommand lists all available options. This prevents global flag explosion while still documenting all tunable parameters.No config file by design: There is no
~/.resticrcorrestic.yaml. All configuration must be explicit on the CLI or via environment variables. This is a principled choice for a security tool — configuration should be auditable and visible at the point of invocation.