Smart sync of all Egregore repos. Fetches first, only pulls if behind.
When to invoke
User says: "/sync-repos", "sync all repos", "sync everything", "get every repo up to date"
Loom routing
Skip this section if your prompt contains LOOM-EXECUTOR — you are the executor; run the skill as specced below. Full protocol: .claude/context/loom.md.
- Resolve:
ROUTE=$(bash bin/loom.sh route sync-repos), thenDECISION_ID=$(printf '%s\n' "$ROUTE" | jq -r '.decision_id // empty'). - If
mode≠delegate, or the user signalled depth ("deep", "think hard",--deep) → run this skill inline as normal. On a depth override, printbash bin/loom.sh footer sync-repos --overrideafter the output and set"override":truein telemetry. - Otherwise delegate: spawn the Agent tool with
subagent_type: "loom-executor",model= the route'stier, prompt =LOOM-DECISION-ID: $DECISION_IDon its own first line, thenLOOM-EXECUTOR: Execute .claude/skills/sync-repos/SKILL.md, plus the user's arguments and any context the spec needs from the session. Print the executor's final output verbatim, then print the output ofbash bin/loom.sh footer sync-repos. - If the spawn fails or the executor's first line is
LOW_CONFIDENCE:— triage the reason: needs-user-interaction or a main-loop-only tool → take over and finish this skill inline (no escalation); genuine uncertainty or failure → reassignROUTE=$(bash bin/loom.sh escalate sync-repos "<reason>"), refreshDECISION_IDfromROUTE, then re-spawn once on the new tier carrying the returned decision ID (sticky for this session). - Telemetry (fire-and-forget):
bash bin/telemetry.sh emit "command" '{"command":"sync-repos","routed":true,"mode":"delegate","model":"<actual>","route_tier":"<table tier>","class":"<class>","escalated":<bool>,"override":<bool>,"source":"<source>"}' 2>/dev/null &
Repos to sync
../$MEMORY_DIR— shared knowledge (derived frommemory_repoinegregore.json)- Any repos listed in the
reposarray inegregore.json(as sibling directories../{repo}) - Current repo (egregore-core)
Read egregore.json first to get the dynamic list:
# Memory repo directory
MEMORY_DIR=$(basename "$(jq -r '.memory_repo' egregore.json)" .git)
# Managed repos
REPOS=$(jq -r '.repos[]? // empty' egregore.json)
Execution
For each repo, run these commands:
# 1. Fetch (always)
git -C /path/to/repo fetch origin --quiet
# 2. Compare local vs remote
LOCAL=$(git -C /path/to/repo rev-parse HEAD)
REMOTE=$(git -C /path/to/repo rev-parse origin/main)
# 3. Only pull if different
if [ "$LOCAL" != "$REMOTE" ]; then
git -C /path/to/repo pull origin main --quiet
# Count commits behind
BEHIND=$(git -C /path/to/repo rev-list HEAD..origin/main --count)
fi
For the current repo (egregore-core): sync the develop branch instead of main:
# Update local develop ref without switching branches (safe for concurrent sessions)
git fetch origin develop:develop --quiet
# If on dev/* branch, rebase onto develop
BRANCH=$(git branch --show-current)
if [[ "$BRANCH" == dev/* ]]; then
git rebase develop --quiet || (git rebase --abort && git merge develop -m "Sync with develop")
fi
Use absolute paths with git -C to avoid permission prompts.
Output format
Syncing Egregore repos...
{memory-dir} ↓ 3 commits → pulled
{repo-1} ✓ up to date
{repo-2} ✓ up to date
egregore-core ↓ 1 commit → pulled
Rules
- Use
git -C /absolute/path— nocdcommands - Fetch ALL repos first (parallel if possible), then compare/pull
- Show commit count when pulling
- Skip repos that don't exist (no error)