feat: sync shared vault at session start
This commit is contained in:
@@ -13,6 +13,12 @@
|
|||||||
"source": "./plugins/openbao-session",
|
"source": "./plugins/openbao-session",
|
||||||
"description": "Provisions a short-lived OpenBao session token for interactive agents.",
|
"description": "Provisions a short-lived OpenBao session token for interactive agents.",
|
||||||
"version": "0.1.0"
|
"version": "0.1.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shared-vault-sync",
|
||||||
|
"source": "./plugins/shared-vault-sync",
|
||||||
|
"description": "Safely pulls the shared vault at session start.",
|
||||||
|
"version": "0.1.0"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,44 @@
|
|||||||
{
|
{
|
||||||
"name": "infra-plugins",
|
"name": "infra-plugins",
|
||||||
"interface": { "displayName": "Infra Plugins" },
|
"interface": {
|
||||||
|
"displayName": "Infra Plugins"
|
||||||
|
},
|
||||||
"plugins": [
|
"plugins": [
|
||||||
{
|
{
|
||||||
"name": "taiga-auto-sync",
|
"name": "taiga-auto-sync",
|
||||||
"source": { "source": "local", "path": "./plugins/taiga-auto-sync" },
|
"source": {
|
||||||
"policy": { "installation": "AVAILABLE", "authentication": "ON_INSTALL" },
|
"source": "local",
|
||||||
|
"path": "./plugins/taiga-auto-sync"
|
||||||
|
},
|
||||||
|
"policy": {
|
||||||
|
"installation": "AVAILABLE",
|
||||||
|
"authentication": "ON_INSTALL"
|
||||||
|
},
|
||||||
"category": "Productivity"
|
"category": "Productivity"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "openbao-session",
|
"name": "openbao-session",
|
||||||
"source": { "source": "local", "path": "./plugins/openbao-session" },
|
"source": {
|
||||||
"policy": { "installation": "AVAILABLE", "authentication": "ON_INSTALL" },
|
"source": "local",
|
||||||
|
"path": "./plugins/openbao-session"
|
||||||
|
},
|
||||||
|
"policy": {
|
||||||
|
"installation": "AVAILABLE",
|
||||||
|
"authentication": "ON_INSTALL"
|
||||||
|
},
|
||||||
"category": "Security"
|
"category": "Security"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shared-vault-sync",
|
||||||
|
"source": {
|
||||||
|
"source": "local",
|
||||||
|
"path": "./plugins/shared-vault-sync"
|
||||||
|
},
|
||||||
|
"policy": {
|
||||||
|
"installation": "AVAILABLE",
|
||||||
|
"authentication": "ON_INSTALL"
|
||||||
|
},
|
||||||
|
"category": "Productivity"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
7
plugins/shared-vault-sync/.claude-plugin/plugin.json
Normal file
7
plugins/shared-vault-sync/.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "shared-vault-sync",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Safely pulls the shared vault at interactive session start.",
|
||||||
|
"author": { "name": "Senkensha" },
|
||||||
|
"hooks": "./hooks/claude-codex-hooks.json"
|
||||||
|
}
|
||||||
20
plugins/shared-vault-sync/.codex-plugin/plugin.json
Normal file
20
plugins/shared-vault-sync/.codex-plugin/plugin.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "shared-vault-sync",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Safely pulls the shared vault at interactive session start.",
|
||||||
|
"author": {
|
||||||
|
"name": "Local developer"
|
||||||
|
},
|
||||||
|
"hooks": "./hooks/claude-codex-hooks.json",
|
||||||
|
"interface": {
|
||||||
|
"displayName": "Shared Vault Sync",
|
||||||
|
"shortDescription": "Safely pull the shared vault at session start.",
|
||||||
|
"longDescription": "Fast-forwards a clean shared vault at session start without blocking the agent when the network is unavailable.",
|
||||||
|
"developerName": "Local developer",
|
||||||
|
"category": "Productivity",
|
||||||
|
"capabilities": [
|
||||||
|
"Lifecycle hooks"
|
||||||
|
],
|
||||||
|
"defaultPrompt": "Synchronize the shared vault."
|
||||||
|
}
|
||||||
|
}
|
||||||
15
plugins/shared-vault-sync/README.md
Normal file
15
plugins/shared-vault-sync/README.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# shared-vault-sync
|
||||||
|
|
||||||
|
Pulls a clean shared vault at `SessionStart` without blocking Claude Code or Codex when the network is unavailable.
|
||||||
|
|
||||||
|
Set `SHARED_VAULT_DIR` to the vault directory to sync it from any working directory. Without it, the hook acts only when the session starts inside a repository whose `AGENTS.md` identifies it as the shared persistent vault.
|
||||||
|
|
||||||
|
The hook skips a dirty worktree and uses `git pull --ff-only`; it never rebases, merges, or pushes.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
Install `shared-vault-sync` from the `infra-plugins` marketplace, then open a new session to activate its `SessionStart` hook.
|
||||||
|
|
||||||
|
## Recommended push automation
|
||||||
|
|
||||||
|
Keep pushes commit-driven. A scheduled local job may run `git fetch` and `git push` only when the vault is clean and the local branch is ahead; it must never rebase, force-push, or resolve conflicts. Let this hook handle the next safe pull after a rejected push.
|
||||||
16
plugins/shared-vault-sync/hooks/claude-codex-hooks.json
Normal file
16
plugins/shared-vault-sync/hooks/claude-codex-hooks.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"hooks": {
|
||||||
|
"SessionStart": [
|
||||||
|
{
|
||||||
|
"hooks": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/pull-shared-vault.sh\"",
|
||||||
|
"timeout": 15,
|
||||||
|
"statusMessage": "Synchronizing shared vault..."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
25
plugins/shared-vault-sync/hooks/pull-shared-vault.sh
Executable file
25
plugins/shared-vault-sync/hooks/pull-shared-vault.sh
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Pull only the designated shared vault; never block a new agent session.
|
||||||
|
set -u
|
||||||
|
|
||||||
|
vault_dir="${SHARED_VAULT_DIR:-${PWD:-}}"
|
||||||
|
|
||||||
|
emit() {
|
||||||
|
printf '{"continue":true,"suppressOutput":true,"hookSpecificOutput":{"additionalContext":"%s"}}\n' "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ ! -f "$vault_dir/AGENTS.md" ] || ! grep -Fq 'This is the shared persistent vault' "$vault_dir/AGENTS.md" || ! git -C "$vault_dir" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||||
|
emit 'Shared vault sync skipped: set SHARED_VAULT_DIR or start the session from the shared vault.'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$(git -C "$vault_dir" status --porcelain)" ]; then
|
||||||
|
emit 'Shared vault sync skipped: the worktree has local changes.'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if GIT_TERMINAL_PROMPT=0 git -C "$vault_dir" pull --ff-only --quiet; then
|
||||||
|
emit 'Shared vault sync completed.'
|
||||||
|
else
|
||||||
|
emit 'Shared vault sync failed; run git pull --ff-only from the vault when it is safe to do so.'
|
||||||
|
fi
|
||||||
Reference in New Issue
Block a user