Sync Repos
Manage public/private repository pairs. Verify parity between a dev (private) repo and its public counterpart, detect drift, run sync scripts, validate results, and ensure no PII or secrets leak to the public side.
Install
claude install-skill https://github.com/thatrebeccarae/claude-skills/tree/main/sync-repos
When to Use
- Before pushing a public repo — verify the sync is clean and current
- After major dev work — check whether the public repo has drifted behind
- On a periodic cadence — weekly or before releases, catch unsynced changes early
- When setting up a new public/private repo pair for the first time
Usage
/sync-repos check [dev-path] [public-path] — Compare repos and report drift
/sync-repos sync [dev-path] [public-path] — Run sync script and validate
/sync-repos setup [dev-path] [public-path] — Create initial sync-public.sh and config
If paths are omitted, prompt the user for them. Look for .syncignore or scripts/sync-public.conf in the dev repo to auto-detect the pair.
Procedure
Check Mode
Validate paths. Confirm both paths exist and contain .git/ directories. Abort with a clear message if either is not a git repo.
Detect sync script. Look for scripts/sync-public.sh, scripts/sync-public.conf, or .syncignore in the dev repo. Report whether a sync mechanism exists.
Compare file lists. Generate sorted file lists for both repos (excluding .git/, node_modules/, dist/). Categorize differences:
- Expected exclusions — files matching known exclusion patterns (see Common Exclusion Patterns below) or listed in
.syncignore / sync-public.conf
- Unexpected drift — files present in dev but missing from public that are NOT in any exclusion list
- Diverged files — files present in both repos but with different content (compare via
sha256sum or git hash-object)
- Public-only files — files in public but not in dev (legitimate: README, CONTRIBUTING, LICENSE, .github/)
Check last sync timestamp. If scripts/sync-public.sh exists, check its last execution time via the most recent commit in the public repo that matches a sync pattern. Compare against the latest commit in the dev repo.
Report. Present a summary table:
- Sync script: found / not found
- Files only in dev (expected): count
- Files only in dev (unexpected): count + list
- Diverged files: count + list
- Public-only files: count + list
- Estimated drift: number of dev commits since last sync
- Recommendation: "in sync", "minor drift", or "sync needed"
Sync Mode
Run check first. Execute the full check procedure above. If no drift is detected, report "already in sync" and stop.
Locate sync script. Look for scripts/sync-public.sh in the dev repo. If not found, ask the user whether to run setup mode to create one.
Preview the sync. Show what the sync script will do — files to copy, exclusions, text replacements. Require user confirmation before proceeding.
Execute the sync script. Run from the dev repo root:
bash scripts/sync-public.sh
Capture stdout and stderr. If the script exits non-zero, report the error and stop.
Post-sync validation. After the script completes:
- Run the check procedure again to confirm parity
- Scan the public repo diff for PII and secrets (see REFERENCE.md for scan patterns)
- Flag any findings and block until resolved
Report results. Summarize:
- Files synced: count
- Exclusions applied: count
- PII/secrets scan: clean or findings
- Next step: "Review changes in public repo, then
/safe-push when ready"
Setup Mode
Scan the dev repo. Identify files and directories that should NOT sync to public:
- Environment files:
.env, .env.* (except .env.example)
- Planning/internal:
.planning/, .claude/, CLAUDE_CONTEXT.md, briefs/
- Data/build artifacts:
data/, dist/, node_modules/, .git/
- Sync infrastructure:
scripts/sync-public.sh, scripts/sync-public.conf
- Sensitive config:
*.pem, *.key, *.plist, config/soul.md
- Project-specific patterns detected via
.gitignore analysis
Generate sync-public.conf. Create a config file with:
SOURCE_DIR and TARGET_DIR variables
PACKAGE_NAME for the public repo
EXCLUDE_PATHS array with all identified exclusions
PRESERVE_PATHS array for public-only files (README, LICENSE, .github/)
Generate sync-public.sh. Create the sync script using the rsync-based template from REFERENCE.md. Include:
- Config file sourcing
- Path validation
- Target cleanup (preserve
.git/ and PRESERVE_PATHS)
- rsync with
--delete-excluded and exclusion list
- Personal data leak check
- File count summary
User review. Display the generated config and script. Wait for explicit approval before writing.
Write files. Save scripts/sync-public.sh (chmod +x) and scripts/sync-public.conf to the dev repo.
Common Exclusion Patterns
These patterns are excluded from sync by default. Append project-specific patterns as needed.
| Pattern |
Reason |
.git/ |
Git history stays separate |
.env, .env.* |
Secrets and environment config |
.planning/ |
Internal planning docs |
.claude/ |
Claude Code project config |
CLAUDE_CONTEXT.md |
Internal agent context |
data/ |
Local data / databases |
dist/, node_modules/ |
Build artifacts |
*.pem, *.key |
Private key material |
*.plist |
macOS service config |
scripts/sync-public.* |
Sync infrastructure itself |
briefs/ |
Internal content briefs |
config/soul.md |
Personal agent config |
Key Principles
- Never auto-push. Sync writes files locally. Pushing to remote is always a separate, user-confirmed step via
/safe-push.
- Always validate after sync. Every sync run ends with a PII/secrets scan on the public repo. No exceptions.
- Exclusion list is append-only. Never remove exclusion patterns without explicit user approval. It is safer to exclude too much than too little.
- Preserve public-only files. The public repo may have its own README, LICENSE, CONTRIBUTING, .github/ workflows. Sync must never overwrite these.
- Conf is separate from script. Keep
sync-public.conf separate so exclusion lists are easy to review and update without touching script logic.
1---2name: sync-repos3description: Manage public/private repository pairs. Verify parity, detect drift, run sync scripts, and validate no sensitive data leaks to the public repo. Use for projects that maintain separate dev and public repositories.4license: MIT5---67# Sync Repos89Manage public/private repository pairs. Verify parity between a dev (private) repo and its public counterpart, detect drift, run sync scripts, validate results, and ensure no PII or secrets leak to the public side.1011## Install1213```bash14claude install-skill https://github.com/thatrebeccarae/claude-skills/tree/main/sync-repos15```1617## When to Use1819- Before pushing a public repo — verify the sync is clean and current20- After major dev work — check whether the public repo has drifted behind21- On a periodic cadence — weekly or before releases, catch unsynced changes early22- When setting up a new public/private repo pair for the first time2324## Usage2526- `/sync-repos check [dev-path] [public-path]` — Compare repos and report drift27- `/sync-repos sync [dev-path] [public-path]` — Run sync script and validate28- `/sync-repos setup [dev-path] [public-path]` — Create initial sync-public.sh and config2930If paths are omitted, prompt the user for them. Look for `.syncignore` or `scripts/sync-public.conf` in the dev repo to auto-detect the pair.3132## Procedure3334### Check Mode35361. **Validate paths.** Confirm both paths exist and contain `.git/` directories. Abort with a clear message if either is not a git repo.37382. **Detect sync script.** Look for `scripts/sync-public.sh`, `scripts/sync-public.conf`, or `.syncignore` in the dev repo. Report whether a sync mechanism exists.39403. **Compare file lists.** Generate sorted file lists for both repos (excluding `.git/`, `node_modules/`, `dist/`). Categorize differences:41 - **Expected exclusions** — files matching known exclusion patterns (see Common Exclusion Patterns below) or listed in `.syncignore` / `sync-public.conf`42 - **Unexpected drift** — files present in dev but missing from public that are NOT in any exclusion list43 - **Diverged files** — files present in both repos but with different content (compare via `sha256sum` or `git hash-object`)44 - **Public-only files** — files in public but not in dev (legitimate: README, CONTRIBUTING, LICENSE, .github/)45464. **Check last sync timestamp.** If `scripts/sync-public.sh` exists, check its last execution time via the most recent commit in the public repo that matches a sync pattern. Compare against the latest commit in the dev repo.47485. **Report.** Present a summary table:49 - Sync script: found / not found50 - Files only in dev (expected): count51 - Files only in dev (unexpected): count + list52 - Diverged files: count + list53 - Public-only files: count + list54 - Estimated drift: number of dev commits since last sync55 - Recommendation: "in sync", "minor drift", or "sync needed"5657### Sync Mode58591. **Run check first.** Execute the full check procedure above. If no drift is detected, report "already in sync" and stop.60612. **Locate sync script.** Look for `scripts/sync-public.sh` in the dev repo. If not found, ask the user whether to run setup mode to create one.62633. **Preview the sync.** Show what the sync script will do — files to copy, exclusions, text replacements. Require user confirmation before proceeding.64654. **Execute the sync script.** Run from the dev repo root:66 ```bash67 bash scripts/sync-public.sh68 ```69 Capture stdout and stderr. If the script exits non-zero, report the error and stop.70715. **Post-sync validation.** After the script completes:72 - Run the check procedure again to confirm parity73 - Scan the public repo diff for PII and secrets (see REFERENCE.md for scan patterns)74 - Flag any findings and block until resolved75766. **Report results.** Summarize:77 - Files synced: count78 - Exclusions applied: count79 - PII/secrets scan: clean or findings80 - Next step: "Review changes in public repo, then `/safe-push` when ready"8182### Setup Mode83841. **Scan the dev repo.** Identify files and directories that should NOT sync to public:85 - Environment files: `.env`, `.env.*` (except `.env.example`)86 - Planning/internal: `.planning/`, `.claude/`, `CLAUDE_CONTEXT.md`, `briefs/`87 - Data/build artifacts: `data/`, `dist/`, `node_modules/`, `.git/`88 - Sync infrastructure: `scripts/sync-public.sh`, `scripts/sync-public.conf`89 - Sensitive config: `*.pem`, `*.key`, `*.plist`, `config/soul.md`90 - Project-specific patterns detected via `.gitignore` analysis91922. **Generate sync-public.conf.** Create a config file with:93 - `SOURCE_DIR` and `TARGET_DIR` variables94 - `PACKAGE_NAME` for the public repo95 - `EXCLUDE_PATHS` array with all identified exclusions96 - `PRESERVE_PATHS` array for public-only files (README, LICENSE, .github/)97983. **Generate sync-public.sh.** Create the sync script using the rsync-based template from REFERENCE.md. Include:99 - Config file sourcing100 - Path validation101 - Target cleanup (preserve `.git/` and `PRESERVE_PATHS`)102 - rsync with `--delete-excluded` and exclusion list103 - Personal data leak check104 - File count summary1051064. **User review.** Display the generated config and script. Wait for explicit approval before writing.1071085. **Write files.** Save `scripts/sync-public.sh` (chmod +x) and `scripts/sync-public.conf` to the dev repo.109110## Common Exclusion Patterns111112These patterns are excluded from sync by default. Append project-specific patterns as needed.113114| Pattern | Reason |115|---------|--------|116| `.git/` | Git history stays separate |117| `.env`, `.env.*` | Secrets and environment config |118| `.planning/` | Internal planning docs |119| `.claude/` | Claude Code project config |120| `CLAUDE_CONTEXT.md` | Internal agent context |121| `data/` | Local data / databases |122| `dist/`, `node_modules/` | Build artifacts |123| `*.pem`, `*.key` | Private key material |124| `*.plist` | macOS service config |125| `scripts/sync-public.*` | Sync infrastructure itself |126| `briefs/` | Internal content briefs |127| `config/soul.md` | Personal agent config |128129## Key Principles130131- **Never auto-push.** Sync writes files locally. Pushing to remote is always a separate, user-confirmed step via `/safe-push`.132- **Always validate after sync.** Every sync run ends with a PII/secrets scan on the public repo. No exceptions.133- **Exclusion list is append-only.** Never remove exclusion patterns without explicit user approval. It is safer to exclude too much than too little.134- **Preserve public-only files.** The public repo may have its own README, LICENSE, CONTRIBUTING, .github/ workflows. Sync must never overwrite these.135- **Conf is separate from script.** Keep `sync-public.conf` separate so exclusion lists are easy to review and update without touching script logic.