feat(agents-vault): back up curated agent memory to a host-scoped vault repo #126
No Reviewers
Labels
Clear labels
Area/CI
Area/Completions
Area/Components
Area/Config
Area/Docs
Area/Functions
Area/Integrations
Area/Prompt & Theme
Area/Scripts
Area/Tests
Compat/Breaking
Kind/Bug
Kind/Chore
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Performance
Kind/Refactor
Kind/Security
Kind/Testing
good first issue
help wanted
.github/workflows and repository automation
completions/ - tab-completion scripts
The opinionated-component system (C1-C6)
config.fish and conf.d/ - startup and environment
docs/manual/ and the generated manual, man page, and site
functions/ - user-facing functions and helpers
integrations/ - third-party tool wiring
themes/ and prompt appearance
scripts/ - standalone helper scripts
tests/ - the syntax lint and functional suite
Breaking change that won't be backward compatible
Something is not working
Tooling, dependencies, and housekeeping
Documentation changes
Improve existing functionality
New functionality
Makes existing behavior faster or lighter
Restructures code without changing behavior
This is security issue
Issue or pull request related to testing
Priority
Critical
1
The priority is critical
Priority
High
2
The priority is high
Priority
Low
4
The priority is low
Priority
Medium
3
The priority is medium
Reviewed
Confirmed
1
Issue has been confirmed
Reviewed
Duplicate
2
This issue or pull request already exists
Reviewed
Invalid
3
Invalid issue
Reviewed
Won't Fix
3
This issue won't be fixed
Status
Abandoned
3
Somebody has started to work on this but abandoned work
Status
Blocked
1
Something is blocking this issue or pull request
Status
Need More Info
2
Feedback is required to reproduce issue or to continue work
Well-scoped and self-contained; a good place to start
Maintainer is looking for someone to pick this up
Milestone
No items
No Milestone
Projects
Clear projects
No projects
Assignees
rootiest (Rootiest)
Clear assignees
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: rootiest/fish-config#126
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Adds
agents-vault, a host-scoped git repo that backs up curated agent memory living outside any project tree.agents-initalready tracksAGENTS.md/CLAUDE.mdinside the repo, but the memories that matter most live under~/.claudeand were backed up by nothing.functions/agents-vault.fish— the tool. Per project,projects/<slug>/claude/memoryin the vault is the real directory and~/.claude/projects/<mangled>/memorybecomes a symlink into it, so backup and restore are the same code path. Modes: no-flag (scaffold + link + commit),--link,--status,--restore,--adopt=SLUG,--remote=URL,--push, plus-v/-q/-s.local-<basename>-<8hex>, and the entry migrates automatically if a remote is added later._agents_repo_slug,_agents_repo_local_slug,_agents_repo_ensure_symlink,_agents_repo_sync,_agents_repo_install_tools) extracted fromagents-init, which is refactored onto them.~/.claude/memoryis symlinked into the vault; the agy knowledge store is copied (not linked, since agy rewrites it wholesale).claudeandagywrappers behind the C1 guard, so it syncs on every launch.The vault is allowlist-only, never denylist.
~/.claudeand the agy root also hold.credentials.json,history.jsonl,sessions/,session-env/,shell-snapshots/, and conversation DBs with-wal/-shmsidecars. Only memory directories and an explicit extension allowlist are ever copied, so nothing an upstream release adds can leak into a repo that may be pushed.Why
Recovering from the loss of a machine meant rebuilding memory that existed only in session history — it was never in the tracked
AGENTS.md. A vault with a remote turns that from a rebuild into a clone.How it works
Because the live memory directory is a symlink into the vault, restore is emergent rather than a separate mechanism: cloning the vault onto a new machine and running
agents-vaultin a project re-points the link at the recovered content.--restoreis a convenience that walks every entry;--adoptrebinds an orphaned entry to the current project.Behavior
Launch commits but never pushes, keeping the network and any credential prompt off the critical path — measured at ~14 ms per launch with no remote configured, and the launch path makes zero network git calls. Pushing is explicit (
--push) or opt-in (__fish_agent_vault_autopush=1), and autopush is bounded at 20 s so a dead remote cannot stall a launch.Opinionated guard (C1)
Both wrappers stay inside the existing
__fish_config_op_enabledgate. With__fish_config_op_aliasesdisabled,claudeandagypass straight through to the real binary and the vault never runs.Notes
Deliberately deferred, and tracked locally rather than gating this PR:
SessionEndhook is not installed.~/.claude/settings.jsonis outside the repo. Until it exists, nothing leaves the machine except via an explicitagents-vault --push.$HERMETIC_HOME; relinking real memory from an unmerged branch was not worth the risk. To be done after merge.agents-initno longer pulls automatically. Removed with the launch-path network fix:GIT_TERMINAL_PROMPT=0closes the credential prompt but not the TCP connect timeout (measured 135 s against a blackholed address with it set), so a "non-fatal pull" would still hang every launch. Neither localAGENTS/sub-repo has a remote, so nothing is currently affected. If wanted back, the right shape is an opt-in flag or a backgrounded fetch — not a synchronous pull.Verification
fish tests/run-tests.fish— passes end to end, exit 0: lint 226/226, functional 13/13, vault 317/317. The vault suite is added to the runner as Phase 3 and its failure genuinely affects the overall exit status.python3 docs/verify-manual.py— 73/74. The sole failure istest_concat_roundtrips_original, becausedocs/fish-config.mdis a tracked generated file that CI regenerates and auto-commits on push (see the ordering comment in.github/workflows/ci.yml). No other failure.fish -nandfish_indentclean on every changed file (covered by the lint phase)..credentials.json,history.jsonl,sessions/,session-env/,shell-snapshots/,*.db+-wal/-shm) planted at the agy root, at two depths insideknowledge/, in the claude home, and beside per-project memory — plus six symlink escapes pointing back at the agy root and the claude home. Result: only legitimate files tracked, and zero planted content in any blob in the entire object database, not justHEAD.agents-vaultandagents-init.--adoptpath traversal.../../../etc,/etc/passwd,a/b,.,..,foo/../bar, and empty are all rejected with exit 1, vault untouched.git clone. A vault is built by running the tool, committed, then cloned;agents-vaultagainst the clone relinks memory correctly, including onto the origin-only entry shape that git produces for an entry whose memory was empty.__fish_config_op_aliases=0,claudeandagypass through to the real binary and no vault is created.docs/fish-config.md,docs/fish-config.1, and the component registry, and auto-commits them).