System Brief
SG-06 / PRODUCT ENGINEERING
Building a Go backup tool around encrypted snapshots, a synthwave terminal, and the practical work of knowing what is backed up and how to get it back.
A backup command can finish successfully and still leave useful questions unanswered. Which folders did it include? How much of that upload was new? Did the scheduled job run while the laptop was closed? How do I get one file back without restoring everything around it?
Sentra is my project for bringing those questions into one tool. It backs up local directories to S3 or S3-compatible storage as encrypted, deduplicated snapshots. It is written in Go and runs as both a command-line tool and a full-screen terminal app.
The storage engine matters, but so does everything around it. Choosing a folder, checking yesterday’s snapshot, and restoring a file should be ordinary actions that are easy to find. That is the part of building Sentra I want to explain.
A snapshot is a record of the folder
Sentra splits file contents into chunks, identifies each chunk by its SHA-256 hash, and stores the pieces a snapshot needs. A manifest records the files, their metadata, and the chunk references required to reconstruct them.
The chunk boundaries come from FastCDC, which follows the content rather than cutting every file into fixed blocks. Inserting something near the beginning of a file can shift fixed boundaries through the rest of it. Content-defined chunking can find matching regions again, allowing unchanged data to be reused.
New chunks are compressed with zstd, then encrypted before upload. A later snapshot can refer to chunks already in the repository instead of uploading another copy. The amount saved depends on what changed and how well the data compresses; a folder of edited text behaves differently from a folder of new photos.
Each snapshot has its own manifest describing the captured folder tree. Restoring it follows that manifest and retrieves the referenced chunks. I can think in terms of “the Documents folder from Tuesday” while the storage layer handles which pieces are shared.
Make the routine visible
Running sentra opens the terminal interface. It starts with setup when there
is no configuration, asks for the repository passphrase when needed, and opens
the dashboard once the repository is available.
The interface uses Bubble Tea, with a synthwave palette and a pixel sun above the navigation. I like giving a practical tool some character. The more useful design work is in the small interactions underneath it: a folder preview, visible keyboard hints, and places to look for the next action.
The backup wizard has three steps:
- Choose a folder and preview what is inside it.
- Choose a one-time backup or an hourly, daily, weekly, or monthly schedule.
- Review and confirm the backup.
The dashboard brings together recent snapshots, activity, and storage savings. The Snapshots view lets me browse the history and start a restore or compare two snapshots. Schedules has its own view, so the configuration of future work is visible alongside the record of completed work.

A dashboard capture from Sentra’s documentation, using demo data. The activity and snapshot history give the repository a shape I can read at a glance.
The CLI remains available for the same work. After setting up a repository, a small workflow looks like this:
sentra backup ./Documents --tag docs
sentra snapshots
That pairing matters to me. The terminal app helps with exploration and infrequent actions; the CLI gives scripts a direct way to do repeatable work. Both use the same repository core.
Restore deserves as much attention as backup
A list of successful uploads is only part of the story. I also want a clear path from a snapshot to files I can open.
Sentra supports restoring a whole snapshot or selected files and subtrees. A
dry run previews the operation before it writes anything. For a snapshot ID
copied from sentra snapshots, the sequence is:
sentra restore <snapshot-id> ./restored-files --dry-run
sentra restore <snapshot-id> ./restored-files --verify
During restore, chunks are decrypted and decompressed, and their content hashes
are checked. The --verify option adds a check of the restored files. Those are
different questions: whether the stored pieces are intact, and whether the
written result matches what the snapshot describes.
Maintenance has a similar distinction. sentra check audits repository
structure, including manifests and chunk references. sentra check --read-data
also reads and verifies chunk data. The deeper check does more I/O, which is
why it is an explicit choice.
Retention is another place where seeing the decision matters. sentra prune
defaults to a dry run, and --explain shows the retention reasons. Deleting
snapshots requires --apply. Snapshots can also be pinned to keep them out of
retention cleanup.
A schedule has to survive an ordinary laptop
Scheduling sounds simple until the machine is asleep, shut down, or waiting for someone to sign in.
Sentra stores repeatable backup settings as named policies and installs them into the operating system’s user scheduler: launchd on macOS and systemd user timers on Linux. It does not need a resident Sentra daemon. The install command also activates the timer, and schedule status checks whether the OS actually loaded it.
There is a second piece for missed work. When a timer loads, an --if-due run
compares the most recent scheduled slot with the policy’s snapshot history. If
a backup already covers that slot, it exits. If the slot was missed while the
machine was off, it can catch up at the next login. A short startup delay gives
the session time to settle.
That behavior still depends on usable storage credentials and access to the repository passphrase. Installing a timer cannot make an expired login valid. Surfacing those conditions is part of making scheduling understandable.
Keep the AI contribution bounded
Sentra includes optional AI assistance for reviewing repository information and suggesting maintenance. Local heuristics produce findings first; the optional model receives summaries rather than file contents or secret values. The ordinary backup and restore workflows do not need a model.
It also exposes an MCP server through sentra mcp. An MCP client can list
snapshots, inspect file metadata, compare snapshots, and get repository stats.
Backup and restore use separate planning and confirmation calls with a
single-use token.
That protocol makes the operation explicit before it runs. It does not, by itself, prove that a person reviewed the plan; the client is responsible for putting the appropriate approval in front of its user. Inside Sentra’s terminal assistant, requested actions go through the app’s confirmation flow.
Metadata deserves care too. File paths and snapshot labels can reveal context even when no file contents are shared. The useful boundary is specific about what an assistant can see and what it can ask the tool to do.
Be precise about what encryption protects
Sentra encrypts file chunks and manifests on the client with XChaCha20-Poly1305. A random repository key protects the data; a key derived from the passphrase with Argon2id wraps that repository key. This lets a passphrase change rewrap the key without rewriting every stored chunk.
Those protections have limits. Object counts, sizes, and access patterns remain visible to the storage provider. Someone with bucket write access can delete objects or roll the repository back. Losing access to the passphrase is also a recovery problem that a successful upload cannot solve.
The repository’s threat model records these boundaries. For a tool that holds backups, explaining them belongs alongside explaining the features.
Sentra brings together several things I enjoy building: Go, terminal interfaces, storage systems, and constrained uses of AI. The standard I keep coming back to is practical: I should be able to see what was saved, understand what will run next, and bring a file back when I need it.