← The writing archive

WRITING / agent-skills

I Backed Up My Agent Skills—Then Tested the Restore

A Git bundle, a post-commit hook, and a temporary restore gave me a way to check whether my agent skills were actually recoverable.

On September 27, I restored my agent-skills repository into a temporary folder and compared it with the working copy. The files matched, apart from Finder’s .DS_Store metadata. The backup file was 189 KB.

That was the result I wanted to record. A file named agent-skills.bundle sitting in iCloud Drive would have been much weaker evidence on its own.

My skills live in a local Git repository. They contain instructions and supporting files for repeatable work, and some depend on templates or scripts alongside the main SKILL.md. Restoring only the instruction files would leave parts of those workflows missing. I wanted the committed repository and its history together.

A backup tied to the commit

I kept the working repository outside iCloud Drive and put a single Git bundle in the synced folder. That gives the backup process one packaged file to replace, while the working Git directory stays local. It also lets me keep this repository private without adding an online Git remote.

The Git bundle documentation describes bundles as a way to package Git objects and references for transfer, including full repository backups. A self-contained bundle can be cloned into a new repository.

My implementation is a short shell script called by a post-commit hook. It creates a temporary bundle with git bundle create and --all, runs git bundle verify, and replaces the previous backup only if both commands succeed. If either fails, it prints a warning and leaves the previous backup in place.

That failure boundary matters. A commit can succeed while the backup fails. The warning means I need to repair the backup; it does not mean the work vanished from Git.

The habit this design requires from me is simple: commit the changes. An edited skill sitting in the working directory is outside this backup until I commit it. Untracked files are outside it too. I documented that limitation beside the procedure so that “backed up automatically” would not become shorthand for “everything on disk is protected.”

The restore had missing pieces to account for

The temporary clone answered whether the packaged repository could be read and reconstructed. Comparing its files with the working copy checked the result more directly than trusting a successful command exit.

Three later commits each refreshed the bundle. After each one, the commit ID in the backup matched the repository’s latest commit. Those checks covered both recovery from the initial bundle and whether subsequent work reached its replacement.

A recovered repository still needs some setup. The active Git hook lives under .git/hooks; cloning the bundle does not reinstall it. My recovery instructions therefore include reconnecting the tracked backup script as the post-commit hook. Otherwise the restored skills could work while future commits quietly stopped updating the backup.

The client symlinks are another separate step. In my setup, Claude Code sees the skills through links in its own skills directory. Those links live outside the repository. Restoring the source files does not recreate that connection, so the runbook includes it explicitly.

What this test actually established

The September 27 test established that I could reconstruct the committed skills locally from the bundle. It did not simulate losing the Mac, recovering access to iCloud, or downloading the file onto a replacement machine. Those are different failure scenarios, and I have not claimed to have tested them.

I also kept the backup’s scope narrow. It covers this skills repository, not my Obsidian vault, separate uploaded copies of skills, or every client’s configuration.

The maintenance check I left myself compares the repository’s current commit with the bundle’s references and checks for uncommitted work. The recovery instructions include the hook and symlinks because those are the pieces I would otherwise have to reconstruct after the files were already back.