Back up Claude Code and Codex memory and instruction files to a private Git repository on a schedule, with a secret scan before every commit.
Claude Code writes what it learns about you and your projects into memory
files. You write instructions in CLAUDE.md and AGENTS.md. None of this is
in a Git repository by default, and a new laptop or a deleted folder loses
it. Session transcripts, by contrast, are large and often contain pasted
secrets, so backing up all of ~/.claude is the wrong fix.
agent-memory-sync copies only an allowlist of memory, instruction and config files into a separate Git repository you own. It scans the copies with Gitleaks and a built-in scanner, and commits only when both are clean. launchd or a systemd timer runs it every day.
Restore · What is copied · Security · Contributing · ollijunes.com
Read the story behind it: in English · suomeksi.
People who use Claude Code, Codex CLI or both on macOS or Linux and want their agents' memory to survive a lost machine, without putting transcripts or keys into Git.
You need Python 3.11+, Git and Gitleaks.
brew install gitleaks # or see the Gitleaks releases page
uv tool install git+https://github.com/ollijunes/agent-memory-sync
agent-memory-sync --versionpipx install git+https://github.com/ollijunes/agent-memory-sync works too.
Create an empty private repository on GitHub or any Git host first. Then:
agent-memory-sync init \
--repo ~/backups/agent-memory \
--machine laptop \
--remote https://github.com/YOUR-NAME/agent-memory.git
agent-memory-sync doctorinit writes a short README.md and .gitignore into the backup
repository. It leaves existing ones alone and commits nothing in a
repository that already has commits. The backup repository must be on a
branch, not a detached HEAD.
--machine is a short label of your choice. Each machine gets its own
folder, so several machines can share one backup repository. The config goes
to ~/.config/agent-memory-sync/config.toml. If the remote is on GitHub and
the gh CLI is installed, init and doctor warn when the repository is
public.
See what would be copied, without touching the repository:
agent-memory-sync planinclude claude/CLAUDE.md
include claude/projects/-home-alex-src-demo/memory/MEMORY.md
include codex/AGENTS.md
include codex/config.toml
skip claude/.credentials.json: excluded:**/.credentials.json
skip claude/projects/-home-alex-src-demo/transcript.jsonl: excluded:**/*.jsonl
skip claude/projects/-tmp-demo/memory/MEMORY.md: excluded:**/projects/-tmp-*/**
skip codex/auth.json: excluded:**/auth.json
Run the first backup:
agent-memory-sync runcopied=5 unchanged=0 removed=0 skipped=... commit=d7e0b7c...
The output above comes from the synthetic home folder in
examples/home.
agent-memory-sync schedule install --at 02:00On macOS this writes a launchd agent to ~/Library/LaunchAgents/ and loads
it. A run missed while the Mac sleeps happens at the next wake. macOS shows a
"Background item added" notice the first time. Logs go to
~/Library/Logs/agent-memory-sync/.
On Linux it writes a systemd user service and timer to
~/.config/systemd/user/ and enables the timer. Persistent=true catches up
a missed run at the next login. The timer runs only while you are logged in,
unless you enable lingering with loginctl enable-linger. Logs:
journalctl --user -u agent-memory-sync.service.
schedule print shows the files without installing them. schedule uninstall removes them. The same templates are in contrib/ if
you prefer to install by hand.
A scheduled job does not read your shell profile. Its PATH holds the
folders where git and gitleaks were found at install time, ~/.local/bin
and the system folders. Run schedule install again if you move either
program.
The scheduled job pushes with your normal Git credentials. On macOS the launchd agent runs in your login session, so the Keychain and your SSH agent work. On Linux an SSH agent is usually not available to a timer; use a deploy key or a credential helper.
| Exit | Meaning | What to do |
|---|---|---|
| 0 | Done, no changes, or another run was already in progress | Nothing |
| 1 | Usage, config or Git error | Read the message. Run agent-memory-sync doctor |
| 3 | Possible secret found | The output names the file, line and rule, never the value. Remove the secret from the source file, or allowlist a false positive (see below) |
| 4 | Uncommitted changes in the backup folder | Look at git status in the backup repository and commit or discard them |
| 5 | No Git identity in the backup repository | Set git config user.name and user.email there |
| 6 | Push failed | The commit is kept and the next run pushes it. Check the remote and your credentials |
| 7 | Gitleaks is not installed | Install it, or opt in to scanner = "builtin" in the config |
When a secret is found, the files and history in the backup repository stay as they were. The scan also covers file names, and a finding in a name is reported without the name.
False positives are common in memory files, because they are prose that
mentions tokens and keys. For Gitleaks, add an allowlist to .gitleaks.toml
in the backup repository. For the built-in scanner, end the line with
# agent-memory-sync: allow or <!-- agent-memory-sync: allow -->. The tool
never adds allowlist entries by itself.
repo = "~/backups/agent-memory"
machine = "laptop"
push = true
scanner = "gitleaks" # or "builtin"
max_file_bytes = 1048576
[sources.claude]
enabled = true
include = [] # extra globs relative to ~/.claude
exclude = []
[sources.codex]
enabled = true
include = []
exclude = []CLAUDE_CONFIG_DIR and CODEX_HOME are honoured. Your include globs add
files but cannot override a built-in exclusion. What is
copied lists every rule.
- The secret scan finds known key formats and obvious assignments. It cannot tell that a sentence in a memory file is private. Keep the backup repository private and treat it like the files themselves.
- Files are stored as plain text in Git. Your Git host can read them. Use a host you trust, or a self-hosted remote.
- Project-level
CLAUDE.md,AGENTS.mdandCLAUDE.local.mdfiles are not copied. They belong to each project's own repository. - Codex memories stored in SQLite are not copied, only Markdown files under
memories/. - Any file or folder whose name contains
token,secret,credentialorpasswordis skipped, even a harmless one such as a skill calledsecret-scanner. - macOS and Linux only. Windows is not supported.
- The backup is one way.
restorewrites files back only when you ask it to.
Several claude-code-backup scripts and chezmoi
style dotfile managers can back up the same files. The difference here is a
narrow allowlist for both Claude Code and Codex instead of the whole
folder, a secret scan that blocks the commit, filtering of temporary session
folders, and no cloud service beyond the Git remote you choose.
uv sync --locked
uv run python -m pytest --cov=agent_memory_sync --cov-fail-under=90
uv run ruff check .
uv run ruff format --check .
python3 scripts/check_public_tree.pyThe tests use a synthetic home folder in a temporary directory and never read
your real ~/.claude or ~/.codex.
MIT. Made by Olli Junes. Not affiliated with Anthropic or OpenAI.
