Manages code synchronization between templates and forks using git subtree.

Install

mkdir -p .claude/skills/foundation-sync && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/11574" && unzip -o skill.zip -d .claude/skills/foundation-sync && rm skill.zip

Installs to .claude/skills/foundation-sync

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Bidirectional sync between a fork project and Foundation_template using git subtree. Pull canonical skills/agents/lessons into the fork, or push contributions back. Use when Caleb says 'run foundation-sync pull/push/status'.
224 chars✓ has a “when” trigger
Intermediate

Key capabilities

  • Initialize a git subtree relationship for a fork project
  • Pull upstream changes from Foundation_template into a fork
  • Push contributions from a fork back to Foundation_template
  • Show the current sync status between a fork and Foundation_template
  • Handle merge conflicts during pull operations
  • Scan for project-specific language on push and pull

How it works

The skill uses `git subtree` commands to manage bidirectional synchronization between a fork project and an upstream template, handling merges and tracking contributions.

Inputs & outputs

You give it
Command (init, pull, push, status) and optional local project path
You get back
Updated local repository, pushed contributions, or sync status report

When to use foundation-sync

  • Syncing template updates to a fork
  • Contributing changes back to upstream
  • Checking sync status

About this skill

Foundation Sync (git subtree)

Bidirectional sync between a fork project and Foundation_template using git subtree.

Why git subtree (not file-copy)

The previous file-copy approach silently overwrote fork customizations on every pull ("drop, log, continue"). Git subtree uses real 3-way merge — fork edits and upstream changes merge automatically when they don't conflict, and surface as standard git merge conflicts when they do. No more silent data loss.

Usage

EDI, run foundation-sync init [local-project-path]   # first-time setup
EDI, run foundation-sync pull [local-project-path]    # pull upstream changes
EDI, run foundation-sync push [local-project-path]    # push contributions back
EDI, run foundation-sync status [local-project-path]  # show sync state

Concepts

  • Foundation_template: The upstream template repo (https://github.com/Echo8Lore/Foundation_template.git)
  • Fork (local project): A project that uses Foundation_template's skills/agents
  • Subtree prefix: .foundation/ — a directory in the fork containing synced Foundation_template content
  • Pull: git subtree pull — merges upstream changes into .foundation/, preserving fork edits
  • Push: git subtree push — extracts .foundation/ commits back to Foundation_template

Why two sync channels?

git subtree push only transmits content inside its --prefix. Contributions at the root level (e.g., skills/contributions/) are invisible to a subtree push with --prefix=.foundation.

The solution: two subtree prefixes, two contribution channels.

WhatWhere it livesPushed via
Canonical content.foundation/git subtree push --prefix=.foundation
Fork contributionsskills/contributions/ (root)git subtree push --prefix=skills/contributions

Both run on every push. Each uses a SEPARATE subtree prefix and pushes to a SEPARATE contribution branch. The PR merges both.

Rule: Fork contributions MUST live in skills/contributions/ (root). They will NOT be picked up by .foundation/ subtree operations.

Sync Contract

DirectionMechanismWhat syncsConflict handling
Foundation → Forkgit subtree pullEverything under .foundation/Git 3-way merge; conflicts surface for manual resolution
Fork → FoundationTwo subtree pushes.foundation/ + skills/contributions/Both pushed to contrib/<project> branch for review

Portability Check (BL-013)

Foundation_template content must be project-agnostic. Both directions scan for project-specific language.

On push (blocks): Before pushing, scan .foundation/ for the fork's project name. If found, STOP — fix before pushing.

On pull (warns): After pulling, scan .foundation/ for all known fork project names from projects.json. If found, WARN — this means Foundation_template has leaked project-specific language upstream. Report it but don't block (the fork still needs the update).

# Build list of known fork names from projects.json
fork_names = [entry.name for entry in projects.json]

grep -ri "<fork-name-1>\|<fork-name-2>\|..." .foundation/

init — First-Time Setup

Run this once per fork to establish the subtree relationship.

Step 0 — Resolve project path

if [local-project-path not provided]:
  use current directory
else if [path exists]:
  cd to that path
else:
  ERROR: Project path not found
  STOP

Step 1 — Check preconditions

# Must be a git repo
if [not a git repo]:
  ERROR: Not a git repository
  STOP

# Must not already have .foundation/
if [.foundation/ exists]:
  ERROR: .foundation/ already exists — subtree already initialized.
  Hint: Use 'pull' to update, not 'init'.
  STOP

# Must have clean working tree
if [git status shows uncommitted changes]:
  WARN: Dirty working tree. Stash or commit first.
  STOP

Step 2 — Add Foundation remote

# Check if remote already exists
existing = git remote -v | grep Foundation_template

if [not exists]:
  git remote add foundation https://github.com/Echo8Lore/Foundation_template.git
  git fetch foundation
else:
  echo "Remote 'foundation' already configured."
  git fetch foundation

Step 3 — Add subtree

git subtree add --prefix=.foundation foundation main --squash \
  -m "chore: init foundation subtree from Foundation_template"

--squash collapses Foundation_template history into a single merge commit, keeping fork history clean.

Step 4 — Set up local references

After the subtree is added, .foundation/ contains the full Foundation_template content:

.foundation/
├── .agent/          # agent roles, skills, AI config
├── .claude/         # Claude Code wrappers
├── skills/          # canonical skill implementations
├── CATALOG.md
├── README.md
└── ...

The fork can now:

  1. Symlink from .foundation/.claude/skills/ into its own .claude/skills/ for skills it wants
  2. Copy and customize specific skills (edits persist across pulls via merge)
  3. Reference directly — point tool configs at .foundation/ paths

Step 5 — Update projects.json (two registries)

Fork-local registry — update the fork's own projects.json (or create it at the repo root) to track this sync:

{
  "name": "<fork-name>",
  "url": "<fork-repo-url>",
  "prefix": ".foundation",
  "remote": "foundation",
  "lastSync": "<today's date>"
}

Foundation_template registry — after the fork syncs for the first time, the fork should contribute a PR to Foundation_template adding its entry to Foundation_template/projects.json. This enables the portability check (BL-013) to detect if the fork leaks project-specific language upstream.

Why two registries? Foundation_template/projects.json must not contain fork-specific data (BL-016). It exists solely to support the portability scan — so it starts empty and is only populated when forks voluntarily add themselves. The fork's own projects.json is for local tracking and can contain fork-specific details.

Step 6 — Log and commit

Append to SYNC_LOG.md:

## YYYY-MM-DD HH:MM UTC — init
- Direction: init (git subtree add)
- Prefix: .foundation
- Remote: foundation (Foundation_template main)
- Notes: First-time subtree setup

Report: "Foundation subtree initialized at .foundation/. Use pull to get future updates."


pull — Pull Upstream Changes

Merge Foundation_template updates into the fork's .foundation/ directory.

Step 0 — Resolve project path

Same as init Step 0.

Step 1 — Check preconditions

# .foundation/ must exist
if [.foundation/ does not exist]:
  ERROR: No .foundation/ directory. Run 'init' first.
  STOP

# 'foundation' remote must exist
if [git remote -v does not show 'foundation']:
  ERROR: No 'foundation' remote. Run 'init' first.
  STOP

# Clean working tree required
if [git status shows uncommitted changes]:
  WARN: Dirty working tree. Stash or commit first.
  STOP

Step 2 — Fetch and show what changed

git fetch foundation

# Show what's new upstream
git log --oneline HEAD..foundation/main -- .foundation/

If no new commits: "Already up to date." STOP.

Show user the summary of incoming changes.

Step 3 — Subtree pull

git subtree pull --prefix=.foundation foundation main --squash \
  -m "chore: sync from Foundation_template $(date -u +%Y-%m-%d)"

If merge succeeds: Report files changed, continue to Step 4.

If merge conflicts:

echo "Merge conflicts detected in .foundation/:"
git diff --name-only --diff-filter=U

echo "Resolve conflicts, then run: git add <files> && git commit"
echo "After resolving, re-run 'foundation-sync pull' to verify."
STOP (do not auto-resolve — user must decide)

This is the key improvement over file-copy: conflicts are visible and user-resolved, not silently dropped.

Step 4 — Post-pull report

# Show what changed
git diff --stat HEAD~1..HEAD -- .foundation/

# Check for new skills added upstream
new_skills = diff between .foundation/skills/ listing before and after
if [new skills found]:
  echo "New skills available from Foundation_template:"
  for skill in new_skills:
    echo "  - skill (see .foundation/skills/skill/SKILL.md)"

Step 5 — Post-pull portability check (BL-013)

# Load known fork project names from projects.json (in .foundation/ or local)
fork_names = [entry.name for entry in projects.json]

# Scan pulled content for project-specific language
for name in fork_names:
  matches = grep -ri "$name" .foundation/
  if [matches found]:
    WARN: "Found references to fork project '$name' in upstream content:"
    show matches
    echo "Foundation_template may contain project-specific language."
    echo "Consider filing an issue or fixing upstream."

This is a warning, not a blocker. The fork needs the update regardless — but leaked project names in the template should be reported and fixed upstream.

Step 6 — Update sync log

Append to SYNC_LOG.md:

## YYYY-MM-DD HH:MM UTC — pull
- Direction: pull (git subtree pull)
- Prefix: .foundation
- Files changed: <count>
- New skills: <list or "none">
- Conflicts: <count or "none">
- Portability warnings: <count or "none">
- Notes: ...

Update lastSync in projects.json.


push — Push Contributions Back

Extract commits from .foundation/ and push to Foundation_template for review.

Step 0 — Resolve project path

Same as init Step 0.

Step 1 — Check preconditions

# .foundation/ must exist
if [.foundation/ does not exist]:
  ERROR: No .foundation/ directory. Run 'init' first.
  STOP

# 'foundation' remote must exist and user must have push access
if [git remote -v does not show 'foundation']:
  ERROR: No 'foundation' remote. Run 'init' first.
  STOP

# Clean working tree
if [git status shows uncommitted changes]:
  WARN: Dirty working tree. Stash or commit first.
  STOP


Content truncated.

When not to use it

  • When the user needs to sync content without using git subtree
  • When the user needs to perform actions not related to bidirectional syncing
  • When the user needs to push contributions outside the defined subtree prefixes

Limitations

  • Fork contributions MUST live in `skills/contributions/` (root) to be pushed.
  • On push, the skill blocks if project-specific language is found in `.foundation/`.
  • On pull, the skill warns if project-specific language is found in `.foundation/`.

How it compares

This skill uses `git subtree` for a real 3-way merge, preserving fork edits and surfacing conflicts, which is more reliable than a file-copy approach that silently overwrites changes.

Compared to similar skills

foundation-sync side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
foundation-sync (this skill)04moReviewIntermediate
tmux202moReviewIntermediate
jira116moNo flagsBeginner
triaging-issues52moReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

Search skills

Search the agent skills registry