⏳ This skill is pending AI review.
Scores will appear once the review pipeline completes.
vault-sync
Use when a user wants an AI agent to install Vault Sync, mirror an existing Vault Git repository to local files, keep it refreshed, or consume an already-synced Vault with normal filesystem tools.
Choose how to use this skill
You do not need every option. Choose the path your AI client supports. The stable page stays the same; versioned files are immutable.
1. Native installer
This listing has no registered native installer command. Use the complete package or source fallback below, depending on what your client supports.
Do not guess an installer command or replace an existing version without reviewing the diff.
2. Complete package recommended
Download the ZIP when available. It includes SKILL.md plus the references, security notes and version metadata.
No complete ProSkills package is published for this listing yet.3. Prompt-only
Copy the prompt above when the agent can read the stable page or when you want to adopt the workflow without installing a skill.
Need only the instruction file?
Download SKILL.md only if your client requires a single file. The complete ZIP is safer for a full installation because it preserves the references and release context.
No path installs or executes anything by itself. Your agent still needs access to the project files. Before updating, compare the installed version and review the diff.
// RATINGS
Not yet listed on ClawHub or SkillsMP
// README
Vault Sync
Vault Sync keeps a Vault Git repository synced to your computer.
A Vault is a Git repository of Markdown files: notes, source material, transcripts, summaries, observations, and other context exported from your app. Vault Sync keeps those files fresh locally so AI tools can read them without needing a live app connection.
Who It Helps
Personal knowledge Vaults can keep everyday context available to local AI tools:
- students with lecture notes, readings, and research papers
- researchers cross-referencing papers, citations, and notes
- freelancers juggling client docs, project notes, and emails
- homemakers organizing recipes, household docs, school info, and planning
- job seekers tracking resumes, cover letters, postings, and interview prep
- hobbyists and makers collecting tutorials, references, and project logs
- writers working across drafts, research, notes, and source material
Team and business Vaults can keep operational context available locally:
- engineering and product teams reviewing incident context and feature history
- account executives preparing for calls and relationship updates
- support teams researching incidents, escalations, and account history
- leaders preparing for board meetings, partner syncs, or investor updates
- customer success teams preparing QBRs and account reviews
- deal teams and investors reviewing diligence material and portfolio context
What It Does
- clones an existing Vault repository to your computer
- pulls updates on demand
- can install a recurring local pull schedule
- reports sync status and local health
- keeps the Vault ready for file-based AI tools
What It Does Not Do
- does not create or manage your Vault
- does not call back to the app that generated the Vault
- does not search, chat, summarize, rank, or index
- does not edit generated Vault files
- does not push changes back to the Vault repository
Vault Sync is the mirror. Your AI tool is the reader.
Supported Platforms
Vault Sync currently supports:
- macOS
- Linux
- WSL2 Ubuntu and similar WSL2 Linux distributions
Native Windows PowerShell and Command Prompt usage are not currently supported. If you use Windows, run Vault Sync inside WSL2 and keep the Vault under the WSL filesystem, such as ~/vaults/<name>, especially when your AI tool also runs in WSL2.
Agent-First Install
Vault Sync is designed so an AI agent can set up the local mirror with your approval. You provide the Vault repository URL from your app; the agent installs the small vault-sync script, clones the repository, and optionally configures a recurring pull schedule.
If your agent supports skill installation from GitHub, install the setup and usage skills:
npx skills add graphlit/vault-sync --skill vault-sync-setup
npx skills add graphlit/vault-sync --skill vault-sync-use
Then ask your agent:
Set up Vault Sync for my Vault at <your-vault-repo-url>.
For agents that support direct skill URLs, point them at:
https://raw.githubusercontent.com/graphlit/vault-sync/main/skill.md
App-hosted skill entrypoints can also be served at:
https://www.zine.ai/skill.md
https://www.dossium.ai/skill.md
Codex CLI 0.121.0 or newer can also consume this repository as a plugin marketplace:
codex plugin marketplace add graphlit/vault-sync
After install, Codex refers to the marketplace by the name in this repo's metadata:
codex plugin marketplace upgrade graphlit-vault-sync
codex plugin marketplace remove graphlit-vault-sync
Install
Clone this repository and install the script somewhere on your PATH:
git clone https://github.com/graphlit/vault-sync
cd vault-sync
install -m 0755 bin/vault-sync ~/.local/bin/vault-sync
If ~/.local/bin is not on your PATH, either add it or run the script directly from this checkout:
bash bin/vault-sync status ~/vaults/my-vault
Quick Start
Use the Vault repository URL from your app:
vault-sync init <your-vault-repo-url> ~/vaults/my-vault
vault-sync pull ~/vaults/my-vault
vault-sync status ~/vaults/my-vault
Then point your AI tool at the local folder:
~/vaults/my-vault
Ask your tool to inspect the Markdown files directly. For example, in Claude Code, Codex, OpenClaw, Cursor, or VS Code:
Use the local Vault in ~/vaults/my-vault to answer this. Start by reading README.md, then search the Markdown files.
You can also search the files yourself:
rg -n "your search terms" ~/vaults/my-vault
Commands
vault-sync init <repo-url> [path]
vault-sync pull [path]
vault-sync status [path]
vault-sync schedule install [path] --every 5m
vault-sync schedule remove [path]
vault-sync doctor [path]
The command surface is intentionally small. Search and reading are handled by your AI tool's normal file access.
Working With AI Tools
Vault Sync works well with file-aware tools such as:
- Claude Code
- Codex
- OpenClaw
- Cursor
- VS Code
Suggested prompt:
The Vault is a local folder of Markdown files. Read README.md first. Ignore hidden control folders like .git, .zine, .dossium, .graphlit, .claude, and .codex. Use normal file tools to search and read the Markdown files.
Optional: Search Companion With QMD
QMD is a local search companion for folders full of Markdown. Vault Sync and QMD fit together well:
- Vault Sync keeps the Vault Git repository current on disk.
- QMD can make the synced Markdown easier to search.
- Your agent can still open the actual files whenever it needs the full source.
The workflow is simple: sync the Vault first, then let QMD search the local folder. Install QMD separately, then add the local Vault folder:
npm install -g @tobilu/qmd
vault-sync pull ~/vaults/my-vault
qmd collection add ~/vaults/my-vault --name my-vault --mask "**/*.md"
qmd context add qmd://my-vault "Local Vault synced by Vault Sync"
qmd embed
Then agents can use QMD as an optional search helper:
qmd query "customer escalation patterns" -c my-vault --json -n 10
qmd get "path/from/result.md" --full
QMD is not required. Vault Sync does not install, configure, or depend on QMD; it just keeps the local files fresh so tools like QMD can use them.
Keeping It Fresh
Pull updates manually:
vault-sync pull ~/vaults/my-vault
Or install a recurring pull schedule:
vault-sync schedule install ~/vaults/my-vault --every 5m
Remove the schedule later:
vault-sync schedule remove ~/vaults/my-vault
Security
- plain Bash script
- no opaque binary
- no credentials stored by Vault Sync
- Git authentication stays in your existing Git or GitHub setup
- scheduled jobs only run
vault-sync pull <path> - local Vault files are not uploaded by this tool
Troubleshooting
Run:
vault-sync doctor ~/vaults/my-vault
This checks for Git, repository health, local changes, remote reachability, optional rg, and scheduler state.
Agent Install Notes
See:
These examples are intentionally focused on agent setup and consumption. Vault creation and management stay in the app that generated the Vault.
Development
Run the smoke test with:
bash tests/smoke.sh
The test creates a temporary local Git repository and does not touch your real Vaults.
// HOW IT'S BUILT
// FILES
19 files shipped with this skill. Inline text is the catalog copy. The upstream link is the source repository.
plugins/vault-sync/skills/vault-sync-setup/SKILL.md2.0 KBceeef92f4235upstream ↗
--- name: vault-sync-setup description: Use when the user wants to install Vault Sync, connect an existing Vault Git repository to a local folder, refresh it, configure a recurring pull schedule, or make a local Vault available to an AI agent through filesystem files. --- # Vault Sync Setup Vault Sync mirrors an existing Vault Git repository to local files. It does not create Vaults, manage replicas, call app APIs, search, query, summarize, rank, index, or push changes. ## Workflow 1. Confirm the environment is macOS, Linux, or WSL2. For Windows users, recommend WSL2 and keep the Vault under the WSL filesystem. 2. Check for `bash` and `git`. `rg` is optional but useful for later consumption. 3. Install `vault-sync` if it is not already on `PATH`. Prefer the bundled script: ```bash bash skills/vault-sync-setup/scripts/install-vault-sync.sh ``` If the bundled script is unavailable, install from GitHub: ```bash mkdir -p ~/.local/bin curl -fsSL https://raw.githubusercontent.com/graphlit/vault-sync/main/bin/vault-sync -o ~/.local/bin/vault-sync chmod +x ~/.local/bin/vault-sync ``` 4. Ask for the Vault Git repository URL and preferred local folder if missing. Use `~/vaults/<repo-name>` as the default. 5. Do not infer the local Vault path from the current working directory, app name, or repository owner. Do not invent hidden app folders such as `~/.zine/vault`, `~/.dossium/vault`, or `~/.graphlit/vault`. 6. Initialize and verify: ```bash vault-sync init <vault-repo-url> <path> vault-sync pull <path> vault-sync doctor <path> ``` 7. Ask before installing a recurring schedule. If approved: ```bash vault-sync schedule install <path> --every 5m ``` ## Agent Behavior - Treat the Vault as generated, read-only context. - Do not edit Vault files unless the user explicitly asks to modify local copies. - Do not use `vault-sync` as a search or read API. After setup, use normal filesystem tools. - If Git authentication fails, let the user complete their normal Git or GitHub CLI authentication flow.plugins/vault-sync/skills/vault-sync-use/SKILL.md1.4 KB48d5b49122f9upstream ↗
--- name: vault-sync-use description: Use when the user wants an AI agent to answer questions or perform research from an already-synced Vault folder using local Markdown files and normal filesystem tools. --- # Vault Sync Use Use an already-synced Vault as local, read-only context. Vault Sync provides files; the agent does the reading and reasoning. ## Workflow 1. If `vault-sync` is available and the user has not asked to avoid updates, refresh the Vault: ```bash vault-sync pull <path> ``` 2. Read `<path>/README.md` first to learn the Vault source and conventions. 3. Ignore hidden control folders: `.git`, `.zine`, `.dossium`, `.graphlit`, `.claude`, and `.codex`. 4. Search and read Markdown directly with normal filesystem tools: ```bash rg -n "<terms>" <path> ls <path> sed -n '1,160p' <file> ``` 5. Cite local file paths in responses when useful. ## Boundaries - Do not call app APIs for Vault consumption. - Do not use `vault-sync` for search, query, read, summarize, rank, or index. - Do not edit generated Vault files unless the user explicitly asks for local modifications. - If QMD is installed, it can be an optional local search helper. Add the Vault folder with `qmd collection add <path> --name <name> --mask "**/*.md"`, add context with `qmd context add qmd://<name> "Local Vault synced by Vault Sync"`, then run `qmd embed`. Use QMD to find likely files and local file reads for the full source. Do not require QMD.skill.md2.3 KB22896e837a5bupstream ↗
--- name: vault-sync description: Use when a user wants an AI agent to install Vault Sync, mirror an existing Vault Git repository to local files, keep it refreshed, or consume an already-synced Vault with normal filesystem tools. --- # Vault Sync Vault Sync mirrors an existing Vault Git repository onto the user's local filesystem. Use it only for file sync and local readiness. Do not use it for search, query, chat, indexing, Vault creation, or Vault management. ## When Setting Up 1. Confirm the environment is macOS, Linux, or WSL2. Native Windows PowerShell and Command Prompt are out of scope. 2. Check for `bash` and `git`. `rg` is optional but useful after sync. 3. Install `vault-sync` if it is not already on `PATH`: ```bash mkdir -p ~/.local/bin curl -fsSL https://raw.githubusercontent.com/graphlit/vault-sync/main/bin/vault-sync -o ~/.local/bin/vault-sync chmod +x ~/.local/bin/vault-sync ``` 4. Ask for the Vault Git repository URL and local folder if the user did not provide them. Use `~/vaults/<repo-name>` as the default. 5. Do not infer the local Vault path from the current working directory, app name, or repository owner. Do not invent hidden app folders such as `~/.zine/vault`, `~/.dossium/vault`, or `~/.graphlit/vault`. 6. Run: ```bash vault-sync init <vault-repo-url> <path> vault-sync pull <path> vault-sync doctor <path> ``` 7. If the user wants recurring refreshes, install a pull schedule: ```bash vault-sync schedule install <path> --every 5m ``` ## When Using A Synced Vault 1. Refresh first when practical: ```bash vault-sync pull <path> ``` 2. Read `<path>/README.md` first. 3. Ignore hidden control folders such as `.git`, `.zine`, `.dossium`, `.graphlit`, `.claude`, and `.codex`. 4. Use ordinary filesystem tools: `ls`, `rg`, `sed`, `cat`, and native file reads. 5. Treat the Vault as read-only unless the user explicitly asks to edit local files. ## Optional QMD Search Companion If QMD is installed and the user wants a stronger local search helper, add the synced Vault folder as a QMD collection: ```bash qmd collection add <path> --name <name> --mask "**/*.md" qmd context add qmd://<name> "Local Vault synced by Vault Sync" qmd embed ``` Use QMD to find likely files; use file reads for the full source. Vault Sync is the mirror. The agent is the reader.skills/vault-sync-setup/SKILL.md2.0 KBceeef92f4235upstream ↗
--- name: vault-sync-setup description: Use when the user wants to install Vault Sync, connect an existing Vault Git repository to a local folder, refresh it, configure a recurring pull schedule, or make a local Vault available to an AI agent through filesystem files. --- # Vault Sync Setup Vault Sync mirrors an existing Vault Git repository to local files. It does not create Vaults, manage replicas, call app APIs, search, query, summarize, rank, index, or push changes. ## Workflow 1. Confirm the environment is macOS, Linux, or WSL2. For Windows users, recommend WSL2 and keep the Vault under the WSL filesystem. 2. Check for `bash` and `git`. `rg` is optional but useful for later consumption. 3. Install `vault-sync` if it is not already on `PATH`. Prefer the bundled script: ```bash bash skills/vault-sync-setup/scripts/install-vault-sync.sh ``` If the bundled script is unavailable, install from GitHub: ```bash mkdir -p ~/.local/bin curl -fsSL https://raw.githubusercontent.com/graphlit/vault-sync/main/bin/vault-sync -o ~/.local/bin/vault-sync chmod +x ~/.local/bin/vault-sync ``` 4. Ask for the Vault Git repository URL and preferred local folder if missing. Use `~/vaults/<repo-name>` as the default. 5. Do not infer the local Vault path from the current working directory, app name, or repository owner. Do not invent hidden app folders such as `~/.zine/vault`, `~/.dossium/vault`, or `~/.graphlit/vault`. 6. Initialize and verify: ```bash vault-sync init <vault-repo-url> <path> vault-sync pull <path> vault-sync doctor <path> ``` 7. Ask before installing a recurring schedule. If approved: ```bash vault-sync schedule install <path> --every 5m ``` ## Agent Behavior - Treat the Vault as generated, read-only context. - Do not edit Vault files unless the user explicitly asks to modify local copies. - Do not use `vault-sync` as a search or read API. After setup, use normal filesystem tools. - If Git authentication fails, let the user complete their normal Git or GitHub CLI authentication flow.skills/vault-sync-use/SKILL.md1.4 KB48d5b49122f9upstream ↗
--- name: vault-sync-use description: Use when the user wants an AI agent to answer questions or perform research from an already-synced Vault folder using local Markdown files and normal filesystem tools. --- # Vault Sync Use Use an already-synced Vault as local, read-only context. Vault Sync provides files; the agent does the reading and reasoning. ## Workflow 1. If `vault-sync` is available and the user has not asked to avoid updates, refresh the Vault: ```bash vault-sync pull <path> ``` 2. Read `<path>/README.md` first to learn the Vault source and conventions. 3. Ignore hidden control folders: `.git`, `.zine`, `.dossium`, `.graphlit`, `.claude`, and `.codex`. 4. Search and read Markdown directly with normal filesystem tools: ```bash rg -n "<terms>" <path> ls <path> sed -n '1,160p' <file> ``` 5. Cite local file paths in responses when useful. ## Boundaries - Do not call app APIs for Vault consumption. - Do not use `vault-sync` for search, query, read, summarize, rank, or index. - Do not edit generated Vault files unless the user explicitly asks for local modifications. - If QMD is installed, it can be an optional local search helper. Add the Vault folder with `qmd collection add <path> --name <name> --mask "**/*.md"`, add context with `qmd context add qmd://<name> "Local Vault synced by Vault Sync"`, then run `qmd embed`. Use QMD to find likely files and local file reads for the full source. Do not require QMD.README.md7.4 KB41a3ffc0aac7upstream ↗
# Vault Sync Vault Sync keeps a Vault Git repository synced to your computer. A Vault is a Git repository of Markdown files: notes, source material, transcripts, summaries, observations, and other context exported from your app. Vault Sync keeps those files fresh locally so AI tools can read them without needing a live app connection. ## Who It Helps Personal knowledge Vaults can keep everyday context available to local AI tools: - students with lecture notes, readings, and research papers - researchers cross-referencing papers, citations, and notes - freelancers juggling client docs, project notes, and emails - homemakers organizing recipes, household docs, school info, and planning - job seekers tracking resumes, cover letters, postings, and interview prep - hobbyists and makers collecting tutorials, references, and project logs - writers working across drafts, research, notes, and source material Team and business Vaults can keep operational context available locally: - engineering and product teams reviewing incident context and feature history - account executives preparing for calls and relationship updates - support teams researching incidents, escalations, and account history - leaders preparing for board meetings, partner syncs, or investor updates - customer success teams preparing QBRs and account reviews - deal teams and investors reviewing diligence material and portfolio context ## What It Does - clones an existing Vault repository to your computer - pulls updates on demand - can install a recurring local pull schedule - reports sync status and local health - keeps the Vault ready for file-based AI tools ## What It Does Not Do - does not create or manage your Vault - does not call back to the app that generated the Vault - does not search, chat, summarize, rank, or index - does not edit generated Vault files - does not push changes back to the Vault repository Vault Sync is the mirror. Your AI tool is the reader. ## Supported Platforms Vault Sync currently supports: - macOS - Linux - WSL2 Ubuntu and similar WSL2 Linux distributions Native Windows PowerShell and Command Prompt usage are not currently supported. If you use Windows, run Vault Sync inside WSL2 and keep the Vault under the WSL filesystem, such as `~/vaults/<name>`, especially when your AI tool also runs in WSL2. ## Agent-First Install Vault Sync is designed so an AI agent can set up the local mirror with your approval. You provide the Vault repository URL from your app; the agent installs the small `vault-sync` script, clones the repository, and optionally configures a recurring pull schedule. If your agent supports skill installation from GitHub, install the setup and usage skills: ```bash npx skills add graphlit/vault-sync --skill vault-sync-setup npx skills add graphlit/vault-sync --skill vault-sync-use ``` Then ask your agent: ```text Set up Vault Sync for my Vault at <your-vault-repo-url>. ``` For agents that support direct skill URLs, point them at: ```text https://raw.githubusercontent.com/graphlit/vault-sync/main/skill.md ``` App-hosted skill entrypoints can also be served at: ```text https://www.zine.ai/skill.md https://www.dossium.ai/skill.md ``` Codex CLI `0.121.0` or newer can also consume this repository as a plugin marketplace: ```bash codex plugin marketplace add graphlit/vault-sync ``` After install, Codex refers to the marketplace by the name in this repo's metadata: ```bash codex plugin marketplace upgrade graphlit-vault-sync codex plugin marketplace remove graphlit-vault-sync ``` ## Install Clone this repository and install the script somewhere on your `PATH`: ```bash git clone https://github.com/graphlit/vault-sync cd vault-sync install -m 0755 bin/vault-sync ~/.local/bin/vault-sync ``` If `~/.local/bin` is not on your `PATH`, either add it or run the script directly from this checkout: ```bash bash bin/vault-sync status ~/vaults/my-vault ``` ## Quick Start Use the Vault repository URL from your app: ```bash vault-sync init <your-vault-repo-url> ~/vaults/my-vault vault-sync pull ~/vaults/my-vault vault-sync status ~/vaults/my-vault ``` Then point your AI tool at the local folder: ```text ~/vaults/my-vault ``` Ask your tool to inspect the Markdown files directly. For example, in Claude Code, Codex, OpenClaw, Cursor, or VS Code: ```text Use the local Vault in ~/vaults/my-vault to answer this. Start by reading README.md, then search the Markdown files. ``` You can also search the files yourself: ```bash rg -n "your search terms" ~/vaults/my-vault ``` ## Commands ```bash vault-sync init <repo-url> [path] vault-sync pull [path] vault-sync status [path] vault-sync schedule install [path] --every 5m vault-sync schedule remove [path] vault-sync doctor [path] ``` The command surface is intentionally small. Search and reading are handled by your AI tool's normal file access. ## Working With AI Tools Vault Sync works well with file-aware tools such as: - Claude Code - Codex - OpenClaw - Cursor - VS Code Suggested prompt: ```text The Vault is a local folder of Markdown files. Read README.md first. Ignore hidden control folders like .git, .zine, .dossium, .graphlit, .claude, and .codex. Use normal file tools to search and read the Markdown files. ``` ## Optional: Search Companion With QMD [QMD](https://github.com/tobi/qmd) is a local search companion for folders full of Markdown. Vault Sync and QMD fit together well: - Vault Sync keeps the Vault Git repository current on disk. - QMD can make the synced Markdown easier to search. - Your agent can still open the actual files whenever it needs the full source. The workflow is simple: sync the Vault first, then let QMD search the local folder. Install QMD separately, then add the local Vault folder: ```bash npm install -g @tobilu/qmd vault-sync pull ~/vaults/my-vault qmd collection add ~/vaults/my-vault --name my-vault --mask "**/*.md" qmd context add qmd://my-vault "Local Vault synced by Vault Sync" qmd embed ``` Then agents can use QMD as an optional search helper: ```bash qmd query "customer escalation patterns" -c my-vault --json -n 10 qmd get "path/from/result.md" --full ``` QMD is not required. Vault Sync does not install, configure, or depend on QMD; it just keeps the local files fresh so tools like QMD can use them. ## Keeping It Fresh Pull updates manually: ```bash vault-sync pull ~/vaults/my-vault ``` Or install a recurring pull schedule: ```bash vault-sync schedule install ~/vaults/my-vault --every 5m ``` Remove the schedule later: ```bash vault-sync schedule remove ~/vaults/my-vault ``` ## Security - plain Bash script - no opaque binary - no credentials stored by Vault Sync - Git authentication stays in your existing Git or GitHub setup - scheduled jobs only run `vault-sync pull <path>` - local Vault files are not uploaded by this tool ## Troubleshooting Run: ```bash vault-sync doctor ~/vaults/my-vault ``` This checks for Git, repository health, local changes, remote reachability, optional `rg`, and scheduler state. ## Agent Install Notes See: - [Agent Install Guide](docs/agent-install-guide.md) - [Claude Code](examples/install-claude-code.md) - [Codex](examples/install-codex.md) - [OpenClaw](examples/install-openclaw.md) These examples are intentionally focused on agent setup and consumption. Vault creation and management stay in the app that generated the Vault. ## Development Run the smoke test with: ```bash bash tests/smoke.sh ``` The test creates a temporary local Git repository and does not touch your real Vaults..agents/plugins/marketplace.json379 Bed3accd8f137upstream ↗
{ "name": "graphlit-vault-sync", "interface": { "displayName": "Vault Sync" }, "plugins": [ { "name": "vault-sync", "source": { "source": "local", "path": "./plugins/vault-sync" }, "policy": { "installation": "AVAILABLE", "authentication": "ON_INSTALL" }, "category": "Productivity" } ] }bin/vault-sync17 KB3828acb07675upstream ↗
#!/usr/bin/env bash set -euo pipefail VERSION="0.1.0" APP_NAME="vault-sync" CONFIG_DIR="${VAULT_SYNC_CONFIG_DIR:-$HOME/.config/vault-sync}" STATE_DIR="$CONFIG_DIR/vaults" LOCK_DIR="$CONFIG_DIR/locks" SCHEDULE_DIR="$CONFIG_DIR/schedules" LOG_DIR="${VAULT_SYNC_LOG_DIR:-$CONFIG_DIR/logs}" ACTIVE_LOCK="" die() { printf 'vault-sync: %s\n' "$*" >&2 exit 1 } note() { printf '%s\n' "$*" } usage() { cat <<'EOF' vault-sync keeps an existing Vault Git repository mirrored onto the local filesystem. Usage: vault-sync init <repo-url> [path] vault-sync pull [path] vault-sync status [path] [--json] vault-sync schedule install [path] [--every 5m] vault-sync schedule remove [path] vault-sync doctor [path] vault-sync version Vault Sync mirrors files only. It does not search, query, read, summarize, rank, index, call Graphlit APIs, create Vaults, or push changes. EOF } ensure_dirs() { mkdir -p "$STATE_DIR" "$LOCK_DIR" "$SCHEDULE_DIR" "$LOG_DIR" } require_command() { command -v "$1" >/dev/null 2>&1 || die "Required command [$1] was not found." } expand_path() { case "${1:-}" in "~") printf '%s\n' "$HOME" ;; "~/"*) printf '%s/%s\n' "$HOME" "${1#~/}" ;; "") printf '%s\n' "" ;; *) printf '%s\n' "$1" ;; esac } absolute_path() { local raw parent base raw="$(expand_path "$1")" parent="$(dirname "$raw")" base="$(basename "$raw")" mkdir -p "$parent" parent="$(cd "$parent" && pwd -P)" printf '%s/%s\n' "$parent" "$base" } script_path() { local source_dir source_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" printf '%s/%s\n' "$source_dir" "$(basename "${BASH_SOURCE[0]}")" } repo_name_from_url() { local url name url="${1%/}" name="${url##*/}" name="${name%.git}" [[ -n "$name" ]] || die "Could not infer a repository name from [$1]." printf '%s\n' "$name" } default_vault_path() { printf '%s/Vaults/%s\n' "$HOME" "$(repo_name_from_url "$1")" } state_id_for_path() { local path checksum base path="$1" checksum="$(printf '%s' "$path" | cksum | awk '{print $1}')" base="$(basename "$path" | tr -c 'A-Za-z0-9._-' '_')" printf '%s-%s\n' "$checksum" "$base" } state_file_for_path() { printf '%s/%s.env\n' "$STATE_DIR" "$(state_id_for_path "$1")" } state_get() { local path key file path="$1" key="$2" file="$(state_file_for_path "$path")" [[ -f "$file" ]] || return 0 awk -F= -v key="$key" '$1 == key { sub(/^[^=]*=/, ""); print; exit }' "$file" } state_set() { local path key value file temp path="$1" key="$2" value="$3" ensure_dirs file="$(state_file_for_path "$path")" temp="$file.tmp.$$" if [[ -f "$file" ]]; then awk -F= -v key="$key" '$1 != key { print }' "$file" >"$temp" else : >"$temp" fi printf '%s=%s\n' "$key" "$value" >>"$temp" mv "$temp" "$file" } state_paths() { ensure_dirs find "$STATE_DIR" -type f -name '*.env' -print 2>/dev/null | while IFS= read -r file; do awk -F= '$1 == "path" { sub(/^[^=]*=/, ""); print; exit }' "$file" done } normalize_remote() { local remote remote="${1%/}" remote="${remote%.git}" printf '%s\n' "$remote" } remote_matches() { [[ "$(normalize_remote "$1")" == "$(normalize_remote "$2")" ]] } require_git_repo() { local path="$1" [[ -d "$path/.git" ]] || die "Path [$path] is not a Git repository." } worktree_dirty() { local path="$1" [[ -n "$(git -C "$path" status --porcelain)" ]] } markdown_count() { local path="$1" find "$path" -type f -name '*.md' \ ! -path '*/.git/*' \ ! -path '*/.zine/*' \ ! -path '*/.dossium/*' \ ! -path '*/.graphlit/*' \ 2>/dev/null | wc -l | tr -d ' ' } resolve_vault_path() { local provided paths count path_line provided="${1:-}" if [[ -n "$provided" ]]; then absolute_path "$provided" return fi if [[ -d ".git" ]]; then pwd -P return fi paths=() while IFS= read -r path_line; do paths+=("$path_line") done < <(state_paths) count="${#paths[@]}" if [[ "$count" -eq 1 ]]; then printf '%s\n' "${paths[0]}" return fi if [[ "$count" -gt 1 ]]; then die "Multiple Vaults are configured. Pass a path explicitly." fi die "No Vault path was provided and no configured Vault was found." } json_escape() { local value="$1" value="${value//\\/\\\\}" value="${value//\"/\\\"}" value="${value//$'\n'/\\n}" value="${value//$'\r'/\\r}" printf '%s\n' "$value" } interval_to_seconds() { local value number unit value="${1:-5m}" if [[ "$value" =~ ^([0-9]+)([smhd]?)$ ]]; then number="${BASH_REMATCH[1]}" unit="${BASH_REMATCH[2]:-s}" case "$unit" in s) printf '%s\n' "$number" ;; m) printf '%s\n' "$((number * 60))" ;; h) printf '%s\n' "$((number * 3600))" ;; d) printf '%s\n' "$((number * 86400))" ;; *) die "Unsupported interval [$value]." ;; esac else die "Unsupported interval [$value]. Use values such as [5m], [30s], or [1h]." fi } interval_to_cron_minutes() { local seconds="$1" if (( seconds < 60 )); then die "Cron fallback requires an interval of at least 1 minute." fi if (( seconds % 60 != 0 )); then die "Cron fallback requires a whole-minute interval." fi if (( seconds > 3540 )); then die "Cron fallback supports intervals up to 59 minutes." fi printf '%s\n' "$((seconds / 60))" } schedule_id_for_path() { printf 'vault-sync-%s\n' "$(state_id_for_path "$1")" } make_schedule_wrapper() { local path interval_seconds id wrapper script jitter log script_arg path_arg log_arg path="$1" interval_seconds="$2" id="$(schedule_id_for_path "$path")" wrapper="$SCHEDULE_DIR/$id.sh" script="$(script_path)" jitter="$(( $(printf '%s' "$path" | cksum | awk '{print $1}') % 30 ))" log="$LOG_DIR/$id.log" printf -v script_arg '%q' "$script" printf -v path_arg '%q' "$path" printf -v log_arg '%q' "$log" ensure_dirs cat >"$wrapper" <<EOF #!/usr/bin/env bash set -euo pipefail sleep "$jitter" exec $script_arg pull $path_arg >>$log_arg 2>&1 EOF chmod +x "$wrapper" note "$wrapper" } install_launchd_schedule() { local path interval_seconds id wrapper plist label path="$1" interval_seconds="$2" id="$(schedule_id_for_path "$path")" wrapper="$(make_schedule_wrapper "$path" "$interval_seconds")" label="com.graphlit.$id" plist="$HOME/Library/LaunchAgents/$label.plist" mkdir -p "$HOME/Library/LaunchAgents" cat >"$plist" <<EOF <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>$label</string> <key>ProgramArguments</key> <array> <string>/bin/bash</string> <string>$wrapper</string> </array> <key>StartInterval</key> <integer>$interval_seconds</integer> <key>RunAtLoad</key> <true/> </dict> </plist> EOF launchctl unload "$plist" >/dev/null 2>&1 || true launchctl load "$plist" state_set "$path" scheduler "launchd" state_set "$path" scheduler_id "$id" note "Installed launchd schedule [$label] for [$path]." } systemd_user_available() { command -v systemctl >/dev/null 2>&1 && systemctl --user status >/dev/null 2>&1 } install_systemd_schedule() { local path interval_seconds id wrapper unit timer unit_dir path="$1" interval_seconds="$2" id="$(schedule_id_for_path "$path")" wrapper="$(make_schedule_wrapper "$path" "$interval_seconds")" unit_dir="$HOME/.config/systemd/user" unit="$unit_dir/$id.service" timer="$unit_dir/$id.timer" mkdir -p "$unit_dir" cat >"$unit" <<EOF [Unit] Description=Vault Sync pull for $path [Service] Type=oneshot ExecStart=/bin/bash $wrapper EOF cat >"$timer" <<EOF [Unit] Description=Vault Sync timer for $path [Timer] OnBootSec=1min OnUnitActiveSec=${interval_seconds}s Unit=$id.service [Install] WantedBy=timers.target EOF systemctl --user daemon-reload systemctl --user enable --now "$id.timer" state_set "$path" scheduler "systemd" state_set "$path" scheduler_id "$id" note "Installed systemd user timer [$id.timer] for [$path]." } install_cron_schedule() { local path interval_seconds minutes id wrapper temp path="$1" interval_seconds="$2" minutes="$(interval_to_cron_minutes "$interval_seconds")" id="$(schedule_id_for_path "$path")" wrapper="$(make_schedule_wrapper "$path" "$interval_seconds")" temp="$(mktemp)" if crontab -l >/dev/null 2>&1; then crontab -l | grep -v "# $id\$" >"$temp" || true else : >"$temp" fi printf '*/%s * * * * /bin/bash %q # %s\n' "$minutes" "$wrapper" "$id" >>"$temp" crontab "$temp" rm -f "$temp" state_set "$path" scheduler "cron" state_set "$path" scheduler_id "$id" note "Installed cron schedule [$id] for [$path]." } remove_launchd_schedule() { local path id label plist path="$1" id="$(schedule_id_for_path "$path")" label="com.graphlit.$id" plist="$HOME/Library/LaunchAgents/$label.plist" if [[ -f "$plist" ]]; then launchctl unload "$plist" >/dev/null 2>&1 || true rm -f "$plist" fi } remove_systemd_schedule() { local path id unit_dir path="$1" id="$(schedule_id_for_path "$path")" unit_dir="$HOME/.config/systemd/user" if command -v systemctl >/dev/null 2>&1; then systemctl --user disable --now "$id.timer" >/dev/null 2>&1 || true fi rm -f "$unit_dir/$id.service" "$unit_dir/$id.timer" if command -v systemctl >/dev/null 2>&1; then systemctl --user daemon-reload >/dev/null 2>&1 || true fi } remove_cron_schedule() { local path id temp path="$1" id="$(schedule_id_for_path "$path")" temp="$(mktemp)" if crontab -l >/dev/null 2>&1; then crontab -l | grep -v "# $id\$" >"$temp" || true crontab "$temp" fi rm -f "$temp" } remove_schedule() { local path id path="$1" id="$(schedule_id_for_path "$path")" remove_launchd_schedule "$path" remove_systemd_schedule "$path" remove_cron_schedule "$path" rm -f "$SCHEDULE_DIR/$id.sh" state_set "$path" scheduler "" state_set "$path" scheduler_id "" note "Removed schedule for [$path]." } acquire_lock() { local path id lock path="$1" ensure_dirs id="$(state_id_for_path "$path")" lock="$LOCK_DIR/$id.lock" if ! mkdir "$lock" 2>/dev/null; then die "Another vault-sync process is already running for [$path]." fi ACTIVE_LOCK="$lock" trap 'rm -rf "$ACTIVE_LOCK"' EXIT } cmd_init() { local repo_url path remote repo_url="${1:-}" [[ -n "$repo_url" ]] || die "Usage: vault-sync init <repo-url> [path]" path="$(absolute_path "${2:-$(default_vault_path "$repo_url")}")" require_command git ensure_dirs if [[ -d "$path/.git" ]]; then remote="$(git -C "$path" config --get remote.origin.url || true)" [[ -n "$remote" ]] || die "Existing repository [$path] has no origin remote." remote_matches "$remote" "$repo_url" || die "Existing repository [$path] points at [$remote], not [$repo_url]." note "Using existing Vault mirror [$path]." else if [[ -e "$path" ]] && [[ -n "$(find "$path" -mindepth 1 -maxdepth 1 -print -quit 2>/dev/null)" ]]; then die "Path [$path] exists and is not an empty Git repository." fi mkdir -p "$(dirname "$path")" git clone "$repo_url" "$path" note "Cloned Vault repository to [$path]." fi state_set "$path" path "$path" state_set "$path" repo_url "$repo_url" state_set "$path" initialized_at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" note "Vault configured. Run [vault-sync pull \"$path\"] to refresh it." } cmd_pull() { local path commit path="$(resolve_vault_path "${1:-}")" require_command git require_git_repo "$path" acquire_lock "$path" if worktree_dirty "$path"; then die "Refusing to pull because [$path] has local changes." fi git -C "$path" fetch --prune git -C "$path" pull --ff-only commit="$(git -C "$path" rev-parse HEAD)" state_set "$path" path "$path" state_set "$path" repo_url "$(git -C "$path" config --get remote.origin.url || true)" state_set "$path" last_success "$(date -u +%Y-%m-%dT%H:%M:%SZ)" state_set "$path" last_commit "$commit" note "Vault [$path] is current at [$commit]." } cmd_status() { local path json remote branch commit dirty last_success scheduler count json="false" path="" while [[ "$#" -gt 0 ]]; do case "$1" in --json) json="true" ;; *) path="$1" ;; esac shift done path="$(resolve_vault_path "$path")" require_git_repo "$path" remote="$(git -C "$path" config --get remote.origin.url || true)" branch="$(git -C "$path" symbolic-ref --short HEAD 2>/dev/null || git -C "$path" rev-parse --short HEAD)" commit="$(git -C "$path" rev-parse HEAD)" dirty="false" worktree_dirty "$path" && dirty="true" last_success="$(state_get "$path" last_success || true)" scheduler="$(state_get "$path" scheduler || true)" count="$(markdown_count "$path")" if [[ "$json" == "true" ]]; then printf '{\n' printf ' "path": "%s",\n' "$(json_escape "$path")" printf ' "remote": "%s",\n' "$(json_escape "$remote")" printf ' "branch": "%s",\n' "$(json_escape "$branch")" printf ' "commit": "%s",\n' "$(json_escape "$commit")" printf ' "dirty": %s,\n' "$dirty" printf ' "lastSuccessfulSync": "%s",\n' "$(json_escape "$last_success")" printf ' "scheduler": "%s",\n' "$(json_escape "$scheduler")" printf ' "markdownFileCount": %s\n' "$count" printf '}\n' return fi note "Path: $path" note "Remote: $remote" note "Branch: $branch" note "Commit: $commit" note "Dirty: $dirty" note "Last successful sync: ${last_success:-never}" note "Scheduler: ${scheduler:-not installed}" note "Markdown files: $count" } cmd_schedule_install() { local path interval interval_seconds os path="" interval="5m" while [[ "$#" -gt 0 ]]; do case "$1" in --every) shift interval="${1:-}" [[ -n "$interval" ]] || die "Missing value for [--every]." ;; *) path="$1" ;; esac shift done path="$(resolve_vault_path "$path")" require_git_repo "$path" interval_seconds="$(interval_to_seconds "$interval")" os="$(uname -s)" case "$os" in Darwin) require_command launchctl install_launchd_schedule "$path" "$interval_seconds" ;; Linux) if systemd_user_available; then install_systemd_schedule "$path" "$interval_seconds" else require_command crontab install_cron_schedule "$path" "$interval_seconds" fi ;; *) die "Unsupported platform [$os]. Use macOS, Linux, or WSL2." ;; esac } cmd_schedule_remove() { local path path="$(resolve_vault_path "${1:-}")" remove_schedule "$path" } doctor_line() { local level message level="$1" message="$2" printf '[%s] %s\n' "$level" "$message" } cmd_doctor() { local raw_path path failures remote os first_path raw_path="${1:-}" failures=0 os="$(uname -s)" case "$os" in Darwin|Linux) doctor_line OK "Platform [$os] is supported." ;; *) doctor_line FAIL "Platform [$os] is unsupported. Use macOS, Linux, or WSL2."; failures=$((failures + 1)) ;; esac if command -v git >/dev/null 2>&1; then doctor_line OK "git is installed." else doctor_line FAIL "git is required." failures=$((failures + 1)) fi if command -v rg >/dev/null 2>&1; then doctor_line OK "rg is installed." else doctor_line WARN "rg is recommended for Vault consumption." fi if command -v gh >/dev/null 2>&1; then doctor_line OK "gh is installed." else doctor_line WARN "gh is optional and only helps diagnose GitHub authentication." fi first_path="$(state_paths | head -n 1 || true)" if [[ -n "$raw_path" ]] || [[ -d ".git" ]] || [[ -n "$first_path" ]]; then path="$(resolve_vault_path "$raw_path")" if [[ -d "$path/.git" ]]; then doctor_line OK "Vault path [$path] is a Git repository." if worktree_dirty "$path"; then doctor_line FAIL "Vault path [$path] has local changes." failures=$((failures + 1)) else doctor_line OK "Vault worktree is clean." fi remote="$(git -C "$path" config --get remote.origin.url || true)" if [[ -n "$remote" ]]; then doctor_line OK "Origin remote is [$remote]." if git ls-remote "$remote" HEAD >/dev/null 2>&1; then doctor_line OK "Origin remote is reachable." else doctor_line WARN "Origin remote was not reachable from this environment." fi else doctor_line FAIL "No origin remote configured." failures=$((failures + 1)) fi if [[ -n "$(state_get "$path" scheduler || true)" ]]; then doctor_line OK "Scheduler is recorded as [$(state_get "$path" scheduler)]." else doctor_line WARN "No scheduler is recorded for this Vault." fi else doctor_line WARN "Vault path [$path] does not exist yet or is not a Git repository." fi else doctor_line WARN "No Vault path provided and no configured Vault was found." fi if [[ "$failures" -gt 0 ]]; then exit 1 fi } main() { local command="${1:-}" if [[ -z "$command" ]]; then usage exit 1 fi shift || true case "$command" in init) cmd_init "$@" ;; pull) cmd_pull "$@" ;; status) cmd_status "$@" ;; schedule) case "${1:-}" in install) shift; cmd_schedule_install "$@" ;; remove) shift; cmd_schedule_remove "$@" ;; *) die "Usage: vault-sync schedule install|remove [path]" ;; esac ;; doctor) cmd_doctor "$@" ;; version|--version|-v) note "$APP_NAME $VERSION" ;; help|--help|-h) usage ;; search|query|read|summarize|rank|index) die "[$command] is intentionally unsupported. Use filesystem tools such as [rg], [ls], [cat], and [sed]." ;; *) die "Unknown command [$command]. Run [vault-sync help]." ;; esac } main "$@"docs/agent-install-guide.md5.8 KB8a1af17bda95upstream ↗
# Agent Install Guide This guide explains how to make Vault Sync available to Codex, Claude Code, and OpenClaw. Vault Sync is only for consuming an existing Vault Git repository as local files. Vault creation and management stay in the app that generated the Vault. ## What You Need - A Vault Git repository URL. - A local destination folder, such as `~/vaults/my-vault`. - macOS, Linux, or WSL2. - Git authentication already set up for the Vault repository. Native Windows PowerShell and Command Prompt are not currently supported. On Windows, run the agent and Vault Sync inside WSL2, and keep the Vault under the WSL filesystem. ## Recommended Paths Use the most native install path your agent supports: | Agent | Recommended path | Fallback | |---|---|---| | Codex | Plugin marketplace in Codex CLI `0.121.0` or newer | Skills or manual CLI | | Claude Code | Agent skills | Direct skill URL or manual CLI | | OpenClaw | Agent skills or direct skill URL | Manual CLI | The agent should set up the local mirror, then use normal filesystem tools to read it. It should not use Vault Sync as a search or query layer. ## Codex ### Plugin Marketplace This path requires Codex CLI `0.121.0` or newer. Add the Vault Sync marketplace: ```bash codex plugin marketplace add graphlit/vault-sync ``` After install, use the marketplace name `graphlit-vault-sync` for maintenance: ```bash codex plugin marketplace upgrade graphlit-vault-sync codex plugin marketplace remove graphlit-vault-sync ``` Then ask Codex: ```text Use the Vault Sync plugin to set up my Vault from <your-vault-repo-url>. ``` Codex should install `vault-sync`, initialize the local folder, run `vault-sync doctor`, and ask before installing a recurring pull schedule. ### Skills Fallback If plugin marketplace support is not available in your Codex CLI version, install the skills directly: ```bash npx skills add graphlit/vault-sync --skill vault-sync-setup npx skills add graphlit/vault-sync --skill vault-sync-use ``` Then ask Codex: ```text Use Vault Sync to set up my Vault from <your-vault-repo-url>. ``` ### Direct Skill URL If Codex supports reading a skill from a URL, use one of: ```text https://raw.githubusercontent.com/graphlit/vault-sync/main/skill.md https://www.zine.ai/skill.md https://www.dossium.ai/skill.md ``` ## Claude Code ### Agent Skills Install the setup and usage skills: ```bash npx skills add graphlit/vault-sync --skill vault-sync-setup npx skills add graphlit/vault-sync --skill vault-sync-use ``` Then ask Claude Code: ```text Set up Vault Sync for my Vault from <your-vault-repo-url>. ``` Claude Code should install `vault-sync`, initialize the local folder, run `vault-sync doctor`, and ask before installing a recurring pull schedule. ### Direct Skill URL If your Claude Code environment supports direct skill URLs, use one of: ```text https://raw.githubusercontent.com/graphlit/vault-sync/main/skill.md https://www.zine.ai/skill.md https://www.dossium.ai/skill.md ``` ## OpenClaw ### Skill Install If OpenClaw supports GitHub-based skill installation, install: ```bash npx skills add graphlit/vault-sync --skill vault-sync-setup npx skills add graphlit/vault-sync --skill vault-sync-use ``` Then ask OpenClaw: ```text Set up Vault Sync for my Vault from <your-vault-repo-url>. ``` ### Direct Skill URL If OpenClaw supports direct skill URLs, use one of: ```text https://raw.githubusercontent.com/graphlit/vault-sync/main/skill.md https://www.zine.ai/skill.md https://www.dossium.ai/skill.md ``` ## Manual Fallback Use this path when an agent cannot install skills or plugins directly: ```bash git clone https://github.com/graphlit/vault-sync cd vault-sync install -m 0755 bin/vault-sync ~/.local/bin/vault-sync vault-sync init <your-vault-repo-url> ~/vaults/<name> vault-sync pull ~/vaults/<name> vault-sync doctor ~/vaults/<name> ``` To keep the Vault fresh: ```bash vault-sync schedule install ~/vaults/<name> --every 5m ``` ## After Install Once the Vault is local, point the agent at the folder and say: ```text Use the local Vault in ~/vaults/<name>. Read README.md first. Ignore hidden control folders like .git, .zine, .dossium, .graphlit, .claude, and .codex. Use normal file tools to search and read the Markdown files. ``` The agent can use `ls`, `rg`, `sed`, `cat`, and native file reads. Vault Sync should only be used to initialize, pull, check status, schedule pulls, or run diagnostics. ## Optional: Search Companion With QMD [QMD](https://github.com/tobi/qmd) can make a synced Vault folder easier to search. The roles are separate: - Vault Sync handles Git clone, pull, status, schedule, and diagnostics. - QMD searches the local Markdown files after they exist on disk. - The agent should use QMD to find likely files, then open the files directly when it needs the full source. If QMD is installed, add the Vault folder as a collection: ```bash vault-sync pull ~/vaults/<name> qmd collection add ~/vaults/<name> --name <name> --mask "**/*.md" qmd context add qmd://<name> "Local Vault synced by Vault Sync" qmd embed ``` Useful QMD commands for agents: ```bash qmd search "<keywords>" -c <name> --json -n 10 qmd vsearch "<natural-language question>" -c <name> --json -n 10 qmd query "<research question>" -c <name> --json -n 10 qmd get "path/from/result.md" --full ``` QMD is optional. Do not install or require it unless the user asks for a stronger local search companion. ## Validation Checklist After setup, run: ```bash vault-sync status ~/vaults/<name> vault-sync doctor ~/vaults/<name> rg -n "<known term>" ~/vaults/<name> ``` Expected result: - `vault-sync status` reports the current local revision. - `vault-sync doctor` reports Git and repository health. - `rg` can find text in Markdown files. If Git authentication fails, authenticate through your normal Git or GitHub CLI flow and retry `vault-sync pull`.examples/install-claude-code.md1.2 KB4250b1b0eda4upstream ↗
# Claude Code Install Use this when a Vault already exists in Git and Claude Code can access your local filesystem. ## Preferred: Agent Skills Install the setup and usage skills: ```bash npx skills add graphlit/vault-sync --skill vault-sync-setup npx skills add graphlit/vault-sync --skill vault-sync-use ``` Then ask Claude Code: ```text Set up Vault Sync for my Vault from <your-vault-repo-url>. ``` Claude Code should install `vault-sync`, initialize the local folder, run `vault-sync doctor`, and ask before installing a recurring pull schedule. ## Direct Skill Fallback If your environment uses direct skill URLs, point Claude Code at: ```text https://raw.githubusercontent.com/graphlit/vault-sync/main/skill.md ``` ## Manual Fallback ```bash git clone https://github.com/graphlit/vault-sync cd vault-sync install -m 0755 bin/vault-sync ~/.local/bin/vault-sync vault-sync init <your-vault-repo-url> ~/vaults/<name> vault-sync schedule install ~/vaults/<name> --every 5m ``` After setup, Claude Code should read `README.md` in the local Vault first, ignore hidden control folders, and inspect Markdown files directly with normal filesystem tools. Treat the Vault as read-only unless you explicitly want local edits.examples/install-codex.md1.5 KB5b9689f6d6e2upstream ↗
# Codex Install Use this when a Vault already exists in Git and Codex can access your local filesystem. ## Preferred: Codex Plugin Marketplace This path requires Codex CLI `0.121.0` or newer. Add the Vault Sync marketplace: ```bash codex plugin marketplace add graphlit/vault-sync ``` After install, use the marketplace name `graphlit-vault-sync` for maintenance: ```bash codex plugin marketplace upgrade graphlit-vault-sync codex plugin marketplace remove graphlit-vault-sync ``` Then ask Codex: ```text Use the Vault Sync plugin to set up my Vault from <your-vault-repo-url>. ``` Codex should install `vault-sync`, initialize the local folder, run `vault-sync doctor`, and ask before installing a recurring pull schedule. ## Skill Fallback If plugin marketplace support is not available in your Codex CLI version, install the skills directly: ```bash npx skills add graphlit/vault-sync --skill vault-sync-setup npx skills add graphlit/vault-sync --skill vault-sync-use ``` You can also point Codex at the direct skill entrypoint: ```text https://raw.githubusercontent.com/graphlit/vault-sync/main/skill.md ``` ## Manual Fallback ```bash git clone https://github.com/graphlit/vault-sync cd vault-sync install -m 0755 bin/vault-sync ~/.local/bin/vault-sync vault-sync init <your-vault-repo-url> ~/vaults/<name> vault-sync schedule install ~/vaults/<name> --every 5m ``` After setup, Codex should read `README.md` in the local Vault first, ignore hidden control folders, and inspect Markdown files directly with normal filesystem tools.examples/install-openclaw.md1.1 KBffb6333cbaceupstream ↗
# OpenClaw Install Use this when a Vault already exists in Git and OpenClaw can access your local filesystem. ## Preferred: Skill Entry If OpenClaw can install agent skills from GitHub, install: ```bash npx skills add graphlit/vault-sync --skill vault-sync-setup npx skills add graphlit/vault-sync --skill vault-sync-use ``` If it uses direct skill URLs, point it at: ```text https://raw.githubusercontent.com/graphlit/vault-sync/main/skill.md ``` Then ask OpenClaw: ```text Set up Vault Sync for my Vault from <your-vault-repo-url>. ``` OpenClaw should install `vault-sync`, initialize the local folder, run `vault-sync doctor`, and ask before installing a recurring pull schedule. ## Manual Fallback ```bash git clone https://github.com/graphlit/vault-sync cd vault-sync install -m 0755 bin/vault-sync ~/.local/bin/vault-sync vault-sync init <your-vault-repo-url> ~/vaults/<name> vault-sync schedule install ~/vaults/<name> --every 5m ``` After setup, OpenClaw should read `README.md` in the local Vault first, ignore hidden control folders, and inspect Markdown files directly with normal filesystem tools.LICENSE1.0 KBf227b16be112upstream ↗
MIT License Copyright (c) 2026 Graphlit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.plugins/vault-sync/.codex-plugin/plugin.json975 B50861295a93fupstream ↗
{ "name": "vault-sync", "version": "0.1.0", "description": "Install and use Vault Sync for filesystem-based Vault consumption.", "author": { "name": "Graphlit", "url": "https://github.com/graphlit/vault-sync" }, "homepage": "https://github.com/graphlit/vault-sync", "repository": "https://github.com/graphlit/vault-sync", "license": "MIT", "keywords": [ "vault", "git", "sync", "filesystem", "agent" ], "skills": "./skills/", "interface": { "displayName": "Vault Sync", "shortDescription": "Mirror Vault Git repositories locally.", "longDescription": "Vault Sync helps Codex install a small Git-based sync script, mirror an existing Vault to local Markdown files, and consume those files with normal filesystem tools.", "developerName": "Graphlit", "category": "Productivity", "defaultPrompt": [ "Set up Vault Sync for my Vault.", "Use my local Vault folder to answer this." ] } }plugins/vault-sync/skills/vault-sync-setup/scripts/install-vault-sync.sh1.2 KBa459fe2ff128upstream ↗
#!/usr/bin/env bash set -euo pipefail install_dir="${VAULT_SYNC_INSTALL_DIR:-$HOME/.local/bin}" target="$install_dir/vault-sync" case "$(uname -s)" in Darwin|Linux) ;; *) echo "Vault Sync currently supports macOS, Linux, and WSL2 Linux environments." >&2 exit 1 ;; esac if ! command -v git >/dev/null 2>&1; then echo "git is required before installing Vault Sync." >&2 exit 1 fi mkdir -p "$install_dir" script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" repo_root="${VAULT_SYNC_REPO_ROOT:-$(cd "$script_dir/../../.." && pwd)}" if [[ -f "$repo_root/bin/vault-sync" ]]; then install -m 0755 "$repo_root/bin/vault-sync" "$target" elif command -v curl >/dev/null 2>&1; then curl -fsSL https://raw.githubusercontent.com/graphlit/vault-sync/main/bin/vault-sync -o "$target" chmod 0755 "$target" elif command -v wget >/dev/null 2>&1; then wget -qO "$target" https://raw.githubusercontent.com/graphlit/vault-sync/main/bin/vault-sync chmod 0755 "$target" else echo "Install from a checkout or install curl/wget to download Vault Sync." >&2 exit 1 fi echo "Installed vault-sync at $target" case ":$PATH:" in *":$install_dir:"*) ;; *) echo "Note: $install_dir is not on PATH for this shell." >&2 ;; esacplugins/vault-sync/skills/vault-sync-setup/scripts/setup-vault.sh1.1 KBe9ae08c0f83fupstream ↗
#!/usr/bin/env bash set -euo pipefail usage() { cat <<'USAGE' Usage: setup-vault.sh <vault-repo-url> [path] [--schedule] [--every 5m] USAGE } if [[ $# -lt 1 ]]; then usage >&2 exit 1 fi repo_url="$1" shift path="" schedule="false" every="5m" while [[ $# -gt 0 ]]; do case "$1" in --schedule) schedule="true" shift ;; --every) every="${2:-}" if [[ -z "$every" ]]; then usage >&2 exit 1 fi shift 2 ;; -*) usage >&2 exit 1 ;; *) if [[ -n "$path" ]]; then usage >&2 exit 1 fi path="$1" shift ;; esac done if [[ -z "$path" ]]; then name="${repo_url##*/}" name="${name%.git}" path="$HOME/vaults/$name" fi if ! command -v vault-sync >/dev/null 2>&1; then script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" bash "$script_dir/install-vault-sync.sh" fi vault-sync init "$repo_url" "$path" vault-sync pull "$path" vault-sync doctor "$path" if [[ "$schedule" == "true" ]]; then vault-sync schedule install "$path" --every "$every" fi echo "Vault ready at $path"skills/vault-sync-setup/scripts/install-vault-sync.sh1.2 KBa459fe2ff128upstream ↗
#!/usr/bin/env bash set -euo pipefail install_dir="${VAULT_SYNC_INSTALL_DIR:-$HOME/.local/bin}" target="$install_dir/vault-sync" case "$(uname -s)" in Darwin|Linux) ;; *) echo "Vault Sync currently supports macOS, Linux, and WSL2 Linux environments." >&2 exit 1 ;; esac if ! command -v git >/dev/null 2>&1; then echo "git is required before installing Vault Sync." >&2 exit 1 fi mkdir -p "$install_dir" script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" repo_root="${VAULT_SYNC_REPO_ROOT:-$(cd "$script_dir/../../.." && pwd)}" if [[ -f "$repo_root/bin/vault-sync" ]]; then install -m 0755 "$repo_root/bin/vault-sync" "$target" elif command -v curl >/dev/null 2>&1; then curl -fsSL https://raw.githubusercontent.com/graphlit/vault-sync/main/bin/vault-sync -o "$target" chmod 0755 "$target" elif command -v wget >/dev/null 2>&1; then wget -qO "$target" https://raw.githubusercontent.com/graphlit/vault-sync/main/bin/vault-sync chmod 0755 "$target" else echo "Install from a checkout or install curl/wget to download Vault Sync." >&2 exit 1 fi echo "Installed vault-sync at $target" case ":$PATH:" in *":$install_dir:"*) ;; *) echo "Note: $install_dir is not on PATH for this shell." >&2 ;; esacskills/vault-sync-setup/scripts/setup-vault.sh1.1 KBe9ae08c0f83fupstream ↗
#!/usr/bin/env bash set -euo pipefail usage() { cat <<'USAGE' Usage: setup-vault.sh <vault-repo-url> [path] [--schedule] [--every 5m] USAGE } if [[ $# -lt 1 ]]; then usage >&2 exit 1 fi repo_url="$1" shift path="" schedule="false" every="5m" while [[ $# -gt 0 ]]; do case "$1" in --schedule) schedule="true" shift ;; --every) every="${2:-}" if [[ -z "$every" ]]; then usage >&2 exit 1 fi shift 2 ;; -*) usage >&2 exit 1 ;; *) if [[ -n "$path" ]]; then usage >&2 exit 1 fi path="$1" shift ;; esac done if [[ -z "$path" ]]; then name="${repo_url##*/}" name="${name%.git}" path="$HOME/vaults/$name" fi if ! command -v vault-sync >/dev/null 2>&1; then script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" bash "$script_dir/install-vault-sync.sh" fi vault-sync init "$repo_url" "$path" vault-sync pull "$path" vault-sync doctor "$path" if [[ "$schedule" == "true" ]]; then vault-sync schedule install "$path" --every "$every" fi echo "Vault ready at $path"tests/smoke.sh1.3 KB68e1dbea9706upstream ↗
#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)" TMPDIR_ROOT="$(mktemp -d)" SRC="$TMPDIR_ROOT/source" VAULT="$TMPDIR_ROOT/vault" CONFIG="$TMPDIR_ROOT/config" cleanup() { rm -rf "$TMPDIR_ROOT" } trap cleanup EXIT git init -b main "$SRC" >/dev/null git -C "$SRC" config user.email [email protected] git -C "$SRC" config user.name "Vault Sync Test" printf '# Test Vault\n\nhello vault\n' >"$SRC/README.md" git -C "$SRC" add README.md git -C "$SRC" commit -m 'initial vault' >/dev/null VAULT_SYNC_CONFIG_DIR="$CONFIG" bash "$ROOT_DIR/bin/vault-sync" init "$SRC" "$VAULT" VAULT_SYNC_CONFIG_DIR="$CONFIG" bash "$ROOT_DIR/bin/vault-sync" status "$VAULT" >/dev/null VAULT_SYNC_CONFIG_DIR="$CONFIG" bash "$ROOT_DIR/bin/vault-sync" status "$VAULT" --json >/dev/null printf '\nsecond line\n' >>"$SRC/README.md" git -C "$SRC" add README.md git -C "$SRC" commit -m 'update vault' >/dev/null VAULT_SYNC_CONFIG_DIR="$CONFIG" bash "$ROOT_DIR/bin/vault-sync" pull "$VAULT" VAULT_SYNC_CONFIG_DIR="$CONFIG" bash "$ROOT_DIR/bin/vault-sync" doctor "$VAULT" if VAULT_SYNC_CONFIG_DIR="$CONFIG" bash "$ROOT_DIR/bin/vault-sync" search "$VAULT" >/dev/null 2>&1; then printf 'search unexpectedly succeeded\n' >&2 exit 1 fi printf 'vault-sync smoke test passed\n'
Plain-text copy, no login: /skill-bundles/graphlit-vault-sync.md