github.com/cloudstic/cli package exposes a high-level Go API that mirrors the CLI commands. Use it to embed backup, restore, and repository management directly into your Go programs.
Installation
pkg/config holds resolved configuration values and performs no I/O against a
store or a provider, so reading and validating configuration pulls in no cloud
SDK. pkg/open constructs stores, sources, keychains and clients from those
values, and necessarily links whichever provider SDK you use. If you only need to
inspect configuration, import the first and not the second.
Quick Start
Storage Backends
All backends implementstore.ObjectStore. Pass the raw store to InitRepo and NewClient.
Local
Amazon S3 (and S3-compatible)
Backblaze B2
SFTP
Keychain
The keychain resolves credentials to a master key. Build akeychain.Chain before calling InitRepo or NewClient.
Initializing a Repository
InitRepo is a package-level function that runs on the raw (unencrypted) store. It only needs to be called once per repository.
Init Options
InitResult
Example
Inspecting a Repository
These package-level functions read repository state from the raw store without requiring the encryption key — useful for deciding whether to prompt for credentials before callingNewClient.
LoadRepoConfig(ctx, rawStore, encryptionKey) (*RepoConfig, error) reads the full marker (not just its status) and requires the encryption key for a sealed repository. UpgradeRepoFormat stamps the on-disk format version; NewClient/Backup/Prune/Forget call it for you as part of normal operation, so most callers never need it directly.Creating a Client
NewClient reads the repository config, resolves the master key via the keychain, and builds the encryption/compression/packfile decorator chain internally.
Client Options
WithEncryptionKey is intended for SaaS scenarios where the master key is resolved externally. For typical use, prefer WithKeychain.client.Store() returns the underlying store.ObjectStore (the fully decorated store NewClient built), for callers that need lower-level access alongside the Client API.
Backup
Backup Options
BackupResult
Example
Sources
Sources implementsource.Source. Available implementations:
Restore
w. Pass io.Discard for a dry run.
snapshotRef accepts "", "latest", a bare hash or unique hash prefix, or
"snapshot/<hash-or-prefix>".
Restore Options
RestoreResult
Example
Restoring directly to a directory
outputDir instead of a ZIP archive. Takes the same RestoreOptions and returns the same RestoreResult.
List
List Options
ListResult
SnapshotEntry.Snap is a core.Snapshot, which carries Seq int, Source *core.SourceInfo (Type, Account, Path, …), Tags []string, and Meta map[string]string. SourceInfo may be nil for snapshots written before source identity was tracked.
These types are declared in Because a Go alias denotes the identical type, these are interchangeable with what the
github.com/cloudstic/cli/internal/core, which external modules cannot import directly — Go’s internal/ rule blocks the import statement. You don’t need to. The root cloudstic package re-exports each of them as a type alias, so you can name them explicitly:Client API returns — you can declare variables, write helper function signatures, and implement interfaces against them. Reading exported fields off returned values (entry.Snap.Seq, meta.Name) works without naming the types at all, as this example does.Example
LsSnapshot
"latest", a bare hash or unique hash prefix, or
"snapshot/<hash-or-prefix>".
LsSnapshot Options
LsSnapshotResult
core.Snapshot/core.FileMeta and the internal/ import restriction.
Find
Find takes a snapshot as output rather than input: by default it searches every snapshot and reports, for each matching file, the versions it has had and which snapshots each version lives in. It is a pure read path — no lock is taken and nothing is written.
Find Options
Entry predicates (all given predicates must match):
Snapshot selectors (which snapshots are searched):
Presentation and execution:
Two helpers parse the string forms the CLI accepts, for callers building
SizeCompare/time values programmatically:
FindResult
FileMatch has two convenience methods: Path() returns the newest version’s first path, and LatestSnapshot() returns the newest snapshot holding the newest version — the one a follow-up Restore would target.
Example
Diff
"latest", a full hash, or a unique hash prefix.
Diff Options
Snapshot reference errors
Snapshot readers return sentinel errors that you can inspect witherrors.Is:
Restore, RestoreToDir, LsSnapshot, and
snapshot selectors passed to Find.
DiffResult
Example
Prune
Forget to reclaim storage.
Prune Options
PruneResult
Forget
Remove a specific snapshot
Apply a retention policy
Forget Options
PolicyResult
GroupKey and KeepReason are internal types you can read fields from (as in the example below) without importing them — see the note under List.
Example
Check
Check Options
CheckResult
Example
BreakLock
ErrRepoLocked
Backup, Restore, and Prune return ErrRepoLocked when the repository is already held by another operation. Check for it with errors.Is and prompt the caller toward BreakLock rather than treating it as a generic failure:
Cat
CatResult
Object Key Namespaces
Example
Key Management
These package-level functions operate on the raw (unencrypted) store.List key slots
Change password
kc must unlock the current master key. pwd supplies the new password.
Use PasswordString for a known value at call time:
PasswordProviderFunc when the new password must be obtained lazily (e.g. interactive prompt):
Add recovery key
kc must unlock the current master key.
Label lets a repository hold several recovery keys, all valid at once. Without Replace: true, adding a recovery key under a label that already exists returns a *keychain.SlotExistsError and writes nothing — this protects a previously issued mnemonic from being silently invalidated.
Workstation Setup and Source Discovery
Backup Profiles
The profiles YAML format lives ingithub.com/cloudstic/cli/pkg/profile. It is
a separate package from the client precisely so that reading or writing a
user’s profiles does not require opening a repository:
Save validates before writing, so a malformed secret reference is rejected
there rather than at backup time. The failure is a *secretref.Error, so you
can branch on Kind rather than matching on the message:
profile.DefaultPath("") returns where the file lives when the user names no
path — profiles.yaml inside the config directory, honouring
CLOUDSTIC_CONFIG_DIR. Use it so your program reads the same file the
cloudstic CLI does rather than a second one that silently disagrees. It
resolves a path without touching the filesystem, so asking the question creates
nothing.
Acting on a Profile
Reading a profile is one thing; using one is another.pkg/open turns a named
profile into a connected client in one call:
Layering Your Own Configuration
If your program has a configuration mechanism of its own — command-line flags, its own file, a form —WithDecided layers it over the profile, with the same
precedence the cloudstic CLI applies to its flags. Every field you name is
taken from your value, and the profile supplies the rest:
config.FieldsSetIn reports which fields your value is non-empty for, which is
the right answer when your mechanism has no notion of “present but empty”.
When empty is a choice you need to keep — -password "" meaning “no
password”, as the CLI treats it — name the fields explicitly instead:
s3_access_key against
-s3-access-key — and a misspelled string silently meant “not decided”, which
would connect you with a credential you had not chosen. config.StoreFields()
and config.BackupFields() enumerate the complete set, so iterating them keeps
your mapping current as fields are added; Field.ProfileKey() renders the
profiles-file spelling for an error message.
Two groups of fields behave differently on purpose. Location and KMS settings
are taken only when the profile actually names one, so a silent profile leaves
what you had. Credentials are taken whenever you have not decided them, empty
included — selecting a profile clears an ambient credential, because a profile
is an explicit choice of which store to talk to, and reaching it with half a
credential set inherited from the environment would be worse than failing to
reach it.
Backing Up From a Profile
The same layering applies to what a profile says to back up.config.Backup
holds the resolved form, and open.Backup constructs both the source and the
options a backup runs with:
open.Backup returns the source and the options together rather than as two
calls, because they share a derived value. The snapshot records a hash of the
active exclude patterns, and the next backup compares its own against it to
decide between an incremental scan and a full rescan. The patterns come from two
places — Excludes and the file named by ExcludeFile — so a hash computed
without reading that file describes a different exclude set than the one in
force, and every subsequent run reads the difference as “the patterns changed”.
Getting the source and the options from one call is what keeps them consistent.
If you supply your own source.Source implementation, use
open.BackupOptions(cfg) for the options and apply cfg.Source.Excludes
yourself — otherwise the recorded hash describes filtering that is not happening.
source.ExcludeHash is exported if you need to compute it directly.
Secret References
Store and source credentials can be written asscheme://path references
instead of inline secrets. github.com/cloudstic/cli/pkg/secretref resolves
them, and pkg/secretref/backends holds the schemes Cloudstic ships with:
env://, file://, config-token://, keychain://, secret-service:// and
wincred://.
Adding your own scheme
Backend is a single method, so a custom scheme — Vault, a cloud KMS, your own
service — is small. backends.Default() returns a fresh map on every call,
which is what lets you extend the built-in set rather than replace it:
secretref.NewError for failures so callers can branch on Kind the same
way they do for the built-in backends.
Implement
WritableBackend as well (adding Scheme, DisplayName,
WriteSupported, DefaultRef, Exists and Store) if the scheme should
also be offered when the CLI and TUI write a secret, rather than only when
resolving one.Choosing where managed tokens live
Theconfig-token:// backend stores tokens itself, encrypted at rest, and by
default puts them in Cloudstic’s own config directory — CLOUDSTIC_CONFIG_DIR
or the OS default. For an embedding program that is usually the wrong place,
and an environment variable is a poor way for a library to be configured:
Progress Reporting
cloudstic.Reporter receives progress events during long-running operations:
NewClient:
WithReporter is omitted, all progress output is suppressed (no-op default).
Complete Example: Automated Backup
See Also
- Source Interface: Implement a custom backup source
- Storage Model: How objects are stored and addressed
- HAMT Structure: The file index data structure
- Backup Flow: End-to-end walkthrough of the backup process