On this page

A backup command can finish successfully and still leave a few 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 the tool I’m building to help answer those questions. 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.

I wanted choosing a folder, checking yesterday’s backup, and restoring a file to be easy to find and follow. Getting the storage engine right is part of that; making it understandable is the other part.

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. I also spent time on the less visible parts: previewing a folder before backing it up, showing the available keyboard shortcuts, and making the next action easy to find.

The backup wizard has three steps:

  1. Choose a folder and preview what is inside it.
  2. Choose a one-time backup or an hourly, daily, weekly, or monthly schedule.
  3. Review and confirm the backup.

The dashboard shows recent snapshots, activity, and storage savings. In the Snapshots view, I can browse the history, start a restore, or compare two snapshots. The Schedules view shows which backups are set to run next.

Sentra’s dashboard showing demo backup activity, storage savings, retention settings, and recent snapshots.

The dashboard shown with demo data: recent activity, storage savings, and snapshot history.

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

I use the terminal app for browsing and the CLI for repeatable work in scripts. Both use the same storage engine.

Restore deserves as much attention as backup

A successful upload is useful only if I can get the files back. Restoring a snapshot deserves the same attention as creating it.

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, Sentra decrypts and decompresses chunks and checks their content hashes. The --verify option also checks the restored files against the snapshot. That checks both the stored pieces and the files written to disk.

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.

I want to see what retention cleanup will remove before it runs. 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.

Missed backups need handling too. 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.

The schedule still needs valid storage credentials and access to the repository passphrase. Installing a timer can’t fix an expired login, so the app needs to make those problems visible.

Be clear about what the AI can do

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.

File paths and snapshot labels can reveal private information even without file contents. An assistant’s permissions need to cover both the information it can read and the operations it can request.

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.

I keep these limits in the repository’s threat model so they can be read alongside the features.

Sentra brings together several things I enjoy building: Go, terminal interfaces, storage systems, and useful applications of AI. But the question I keep asking is simple: can I see what was saved and get a file back when I need it?