From ghengis-skills
Use after completing a major work batch (plan execution, feature build, multi-task subagent run) to update CLAUDE.md, MEMORY.md, project indexes, documentation, and propagate new permissions to global settings. Captures lessons learned, marks completed plans, ratchets reusable permissions across all projects, and keeps project DNS in sync with reality.
How this skill is triggered — by the user, by Claude, or both
Slash command
/ghengis-skills:auto-project-syncThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Update project documentation after a significant work batch completes, so the next session starts with current context. The "project DNS keeps drifting from the code" problem — solved.
Update project documentation after a significant work batch completes, so the next session starts with current context. The "project DNS keeps drifting from the code" problem — solved.
Mandatory triggers:
superpowers:subagent-driven-development finishes all taskssuperpowers:finishing-a-development-branch is invoked/sync slash commandOptional triggers:
Do NOT invoke:
<SUBAGENT-STOP>)| File | What Changes |
|---|---|
| CLAUDE.md | Active phase, recent decisions, current focus, agent count if changed |
| MEMORY.md | New feedback/preferences captured this session, lessons learned |
| CONTEXT.md | Workspace routing if new modules added |
| docs/superpowers/specs/INDEX.md | List of specs with status (draft/approved/implemented) |
| docs/superpowers/plans/INDEX.md | List of plans with completion status (% tasks done) |
| README.md | Top-level project description if scope changed |
| ~/.claude/settings.json | New reusable permissions promoted from project-local to global (permission ratchet) |
| .claude/last_sync | Timestamp of this sync (used by hooks for threshold checks) |
LAST_SYNC=$(cat .claude/last_sync 2>/dev/null || echo "1970-01-01")
NEW_COMMITS=$(git log --since="$LAST_SYNC" --oneline | wc -l)
CHANGED_FILES=$(git log --since="$LAST_SYNC" --name-only --pretty=format: | sort -u | grep -v '^$')
If NEW_COMMITS == 0, exit early — nothing to sync.
For each commit since last sync, classify by conventional commit prefix:
feat: → new feature addedfix: → bug fixdocs: → documentation updatechore: → maintenancerefactor: → code restructuretest: → test additionsBuild summary:
Since last sync (2026-04-15):
- 18 features added (modules: outreach, state_local, gsa_application, analytics, documents)
- 3 bug fixes
- 5 doc updates
- 0 refactors
Read current versions:
CLAUDE.mdMEMORY.mdCONTEXT.md (if exists)docs/superpowers/specs/ (list)docs/superpowers/plans/ (list)CLAUDE.md updates:
MEMORY.md updates:
Spec/Plan indexes:
docs/superpowers/specs/*.md and docs/superpowers/plans/*.mdINDEX.md in each directory with:
- [x] vs - [ ])CONTEXT.md updates:
Propagate reusable permissions from this project's .claude/settings.local.json to the global ~/.claude/settings.json so they apply across ALL projects. Over time, the user gets fewer and fewer approval prompts.
Process:
<project>/.claude/settings.local.json → permissions.allow list~/.claude/settings.json → permissions.allow and permissions.deny lists*) — e.g., Bash(brew install *), WebFetch(domain:arxiv.org)Read, Edit, Write, WebSearchWebFetch(domain:docs.anthropic.com)*, long paths, specific filenames) — these are session artifacts, not reusable patterns~/.claude/settings.json permissions.allowpermissions.deny — the deny list from setup is permanentFilter heuristic (what counts as "reusable"):
Broad strokes: accept anything with a wildcard unless it's pinned to an exact home-directory file. Generalize project-specific names (venvs, dated paths) so one approval covers similar future patterns.
import re
def generalize(perm: str) -> str:
"""Rewrite project-specific tokens into patterns so one allow covers future siblings."""
# venv_kronos, venv_weather, env_myproject -> venv*, env*
perm = re.sub(r"\b(venv|env)_[A-Za-z0-9_-]+", r"\1_*", perm)
# Date-stamped paths: 2026-04-17 -> *
perm = re.sub(r"\b20\d{2}-\d{2}-\d{2}\b", "*", perm)
# Specific python version pinning: [email protected]/3.13.7 -> python@*/**
perm = re.sub(r"python@\d+\.\d+/\d+\.\d+\.\d+", "python@*", perm)
return perm
def is_reusable_permission(perm: str) -> bool:
# Tool-level allows are always reusable
if perm in ("Read", "Edit", "Write", "WebSearch", "WebFetch"):
return True
# Domain-scoped WebFetch is always reusable
if perm.startswith("WebFetch(domain:"):
return True
# No wildcard = one-off exact command, skip
if "*" not in perm:
return False
# Wildcard patterns are reusable UNLESS they pin to a home-specific file
# (broad paths like /Users/**/Library/** or /usr/local/** are still useful)
if re.search(r"/Users/[^/*]+/(Desktop|Documents|Downloads)/[^/*]+/[^*]*\.", perm):
return False # e.g. /Users/kae/Desktop/project/specific-file.txt
if "/private/tmp" in perm or "/tmp/" in perm:
return False
return True
Run every candidate through generalize() before is_reusable_permission() so promoted entries cover similar future paths. Dedup against the global allow list after generalization to avoid duplicate patterns.
Why this matters: After 10 sessions, the user's global allow list has grown organically from their actual usage. New projects start with all the permissions they've ever found useful. The deny list never shrinks — dangerous operations always require confirmation.
Scan recent commits and conversation context for:
Use the user's existing memory system at memory/ directory. Don't create duplicates.
date -u +"%Y-%m-%dT%H:%M:%SZ" > .claude/last_sync
Output a 3-5 line summary:
"Synced project state. Updated CLAUDE.md (active phase → Phase 2 execution), MEMORY.md (added 2 lessons learned), plan index (Phase 1 marked 100% complete, Phase 2 plans drafted). Next session will see current state."
| Don't | Why |
|---|---|
| Rewrite CLAUDE.md from scratch | Loses user customizations and history |
| Add commit details into CLAUDE.md | That's what git log is for |
| Create new files unprompted | Sync updates existing structure, doesn't expand scope |
| Run sync mid-task | Creates noise; sync is a terminal action |
| Sync without checking last_sync timestamp | Wastes effort if nothing changed |
| Modify spec/plan content | Only the INDEX is auto-generated; specs/plans are source of truth |
Runs at session end. Doesn't perform full sync — just writes a marker if changes pending:
#!/usr/bin/env bash
# .claude/hooks/session-end-sync-check.sh
LAST_SYNC=$(cat .claude/last_sync 2>/dev/null || echo "1970-01-01")
NEW_COMMITS=$(git log --since="$LAST_SYNC" --oneline 2>/dev/null | wc -l)
if [ "$NEW_COMMITS" -ge 5 ]; then
echo "Auto-sync recommended: $NEW_COMMITS commits since last sync" > .claude/pending_sync.md
fi
Runs at session start. If pending_sync exists, surface it:
#!/usr/bin/env bash
# .claude/hooks/session-start-sync-prompt.sh
if [ -f .claude/pending_sync.md ]; then
cat .claude/pending_sync.md
echo "Run /sync to update project docs."
fi
User can always run /sync to force a sync regardless of triggers or threshold.
This skill complements (does not replace):
superpowers:finishing-a-development-branch — handles git/PR workflow at branch completionghengis-skills:project-scaffold — initial project structure (one-time)ghengis-skills:agent-identity — separate concern (user preferences)Run this AFTER finishing-a-development-branch if both apply.
npx claudepluginhub kgan01/ghengis-skills --plugin ghengis-skillsSaves coding session progress by appending timestamped summaries to CLAUDE-activeContext.md, decisions.md, patterns.md, troubleshooting.md, and MEMORY.md. Prints update summary. Supports /sync --full for capability inventory.
Sync tracking documents based on current conversation results. Updates subtask, progress, findings, task_plan, project CLAUDE.md. Use when finishing a task or reaching a milestone.
Implements two-phase workflow to analyze code changes via git diff and update project documentation. Use before merging branches, after features/bugfixes, or when docs stale.