# Syncing Claude Code Automation Across Projects

This guide explains how to use the `persuade` CLI to distribute Claude Code automation from the persuade repository to your projects.

## Overview

The `persuade` CLI enables you to:
- **Install** automation to new projects
- **Update** existing projects with latest improvements
- **Maintain** consistency across your organization's projects
- **Preserve** custom project-specific permissions

## Installation

```bash
pip install persuade
```

## Quick Start

### Fresh Installation

Sync automation to a new project that doesn't have `.claude/` yet:

```bash
cd ~/projects/my-new-project
persuade sync .
```

This will:
- Create `.claude/` directory structure
- Copy all automation files (hooks, scripts, commands, prompts)
- **Install git hooks** to `.git/hooks/` automatically (via destination path mapping)
- Configure permissions for frictionless development
- Set up PostToolUse hook for PR automation
- Update `.gitignore` with Claude-specific entries

### Update Existing Project

Sync updates to a project that already has automation:

```bash
cd ~/projects/existing-project
persuade sync .
```

**Union Mode (default):** Preserves your custom permissions while adding new ones from the template. This is safe and recommended for most cases.

### Dry Run (Preview Changes)

See what would change without actually applying:

```bash
persuade sync --dry-run .
```

Output shows:
- Files that would be added/modified/removed
- Permissions that would be added
- Hooks that would be configured
- Summary statistics

## Commands

### `sync` - Main Sync Operation

```bash
persuade sync [OPTIONS] [TARGET_PATH]
```

**Arguments:**
- `TARGET_PATH` - Target project directory (defaults to git repository root)

**Options:**
- `--dry-run` - Show changes without applying them
- `--strict` - Remove non-template permissions (use with caution!)
- `--force` - Skip confirmation prompts
- `--no-backup` - Skip backup creation (NOT RECOMMENDED)
- `--exclude PATTERN` - Exclude files matching pattern (can be used multiple times)
- `--shadow` - Sync files but exclude from git (add `.claude/` to `.gitignore`)
- `-e, --editable` - Editable mode: symlink files instead of copying for live development
- `--git-commit` - Create atomic git commits for synced files
- `--branch` - Create a new branch for commits (implies `--git-commit`)
- `--allow-current-branch` - Allow committing on current branch instead of requiring `--branch`
- `--pr` - Create a PR after commits (requires `--branch` and `gh` CLI)
- `-v, --verbose` - Show detailed output
- `-q, --quiet` - Minimal output

**Examples:**

```bash
# Fresh install with preview
persuade sync --dry-run .

# Update existing project
persuade sync .

# Strict mode (enforce template-only permissions)
persuade sync --strict .

# Exclude specific files
persuade sync --exclude "*.local.*" .

# Verbose output for debugging
persuade sync -v .

# Shadow mode - sync files but keep them out of git
persuade sync --shadow .

# Editable mode - symlink for live development
persuade sync -e .
```

#### Shadow Mode

Shadow mode is designed for projects where you want to use Claude Code automation locally but keep it out of the git repository (e.g., open-source projects or public repositories where internal automation shouldn't be committed).

**Use Case:** Syncing to open-source projects where your company's engineering standards and configuration should remain private.

**What Shadow Mode Does:**
1. Syncs all `.claude/` files normally (commands, hooks, scripts, knowledge base, etc.)
2. Automatically adds `.claude/` to `.gitignore`
3. Creates a `.claude/.shadow` marker file
4. Provides commands to untrack already-tracked `.claude/` files if needed

**Example:**

```bash
# Enable shadow mode for an open-source project
persuade sync --shadow .
```

**Benefits:**
- Use powerful automation in any project type
- Keep internal standards confidential
- Prevent accidental commits of sensitive configuration
- Clean separation of concerns

#### Git Workflow Automation

The sync command can automatically create branches, commits, and pull requests for synced changes. This is useful for automated pipelines or bulk updates across many projects.

**Options:**
- `--git-commit` - Create atomic git commits for synced files
- `--branch` - Create a new branch (e.g., `persuade/sync-20260127`)
- `--pr` - Create a pull request after commits

**Example Workflow:**

```bash
# Sync with automatic branch, commits, and PR
persuade sync --pr .

# This will:
# 1. Create branch: persuade/sync-YYYYMMDD
# 2. Create atomic commits for each file category
# 3. Push branch to remote
# 4. Create PR via gh CLI
```

**Error Handling:**
- If all synced files are gitignored, no commits are created and PR creation is blocked with a clear error message
- If commits are created but PR creation fails, you receive an error status with details
- If commits fail but files were synced, you receive a "partial" status
- Files in `.gitignore` can still be committed using force-add when detected

**Requirements:**
- Git repository with a configured remote
- `gh` CLI installed for PR creation (see: https://cli.github.com/)
- Write access to the remote repository

### `doctor` - Validate and Fix Issues

```bash
persuade doctor [OPTIONS] [TARGET_PATH]
```

Runs comprehensive diagnostics:
- Required dependencies (jq, gh, bash)
- JSON syntax validation
- Permission pattern checking (`:*` wildcard syntax)
- Executable permissions on scripts
- `claude doctor` integration

**Options:**
- `--fix` - Automatically fix issues when possible
- `--check-only` - Only report issues, don't fix

**Examples:**

```bash
# Check for issues
persuade doctor .

# Auto-fix common issues
persuade doctor --fix .

# Just check, don't fix anything
persuade doctor --check-only .
```

### `help-command` - Show Installation State

```bash
persuade help-command [TARGET_PATH]
```

Displays beautiful overview of installed automation:
- Slash commands with descriptions
- Hooks configuration table
- Scripts listing
- Permissions summary

### `rollback` - Restore from Backup

```bash
persuade rollback [OPTIONS] [TARGET_PATH]
```

Backups are automatically created before sync operations. Use rollback to restore if something goes wrong.

**Options:**
- `--list` - List available backups
- `--timestamp TIMESTAMP` - Restore specific backup
- `--latest` - Restore most recent backup (default)

**Examples:**

```bash
# List available backups
persuade rollback --list .

# Restore latest backup
persuade rollback .

# Restore specific backup by timestamp
persuade rollback --timestamp 20251204_094915 .
```

## Sync Modes

### Union Mode (Default)

**Behavior:** Preserves custom permissions, adds new ones from template

**Use When:**
- Updating existing projects
- You have project-specific custom permissions
- You want safe, non-destructive updates

**Example:**
```bash
# Before sync:
#   Target has: "Bash(npm run custom-script)"
#   Template has: "Bash(git :*)", "Bash(npm run test)"
#
# After sync:
#   Result has: "Bash(npm run custom-script)", "Bash(git :*)", "Bash(npm run test)"
```

### Strict Mode

**Behavior:** Enforces template-only permissions (removes custom ones)

**Use When:**
- You want strict organizational standards
- You need to remove unauthorized permissions
- Setting up controlled environments

**Warning:** This will remove custom permissions! Always run with `--dry-run` first.

**Example:**
```bash
# Preview what would be removed
persuade sync --strict --dry-run .

# Apply strict mode (removes custom permissions)
persuade sync --strict .
```

## Destination Path Mapping

The sync engine supports **destination path mapping**, allowing files to be synced to locations outside `.claude/`. This is especially useful for:

### Git Hooks (Auto-Installed)

Git hooks are automatically synced from `.claude/git-hooks/` to `.git/hooks/`:

```
.claude/git-hooks/pre-push → .git/hooks/pre-push
.claude/git-hooks/pre-commit → .git/hooks/pre-commit
```

No manual installation required - hooks are set up automatically with correct permissions.

### How It Works

Configuration in `persuade/constants.py`:

```python
".claude/git-hooks/*": {
    "category": FileCategory.SYNC_ALWAYS,
    "destination": ".git/hooks/{filename}",
    "exclude": ["*.md", "README*"],  # Keep docs in .claude/
}
```

## File Categories

The sync tool handles different files intelligently:

### SYNC_ALWAYS (Overwrite Every Time)
- `commands/*.md` - Slash commands
- `hooks/*.sh` - Hook scripts
- `git-hooks/*` - Git hooks (synced to `.git/hooks/` via destination mapping)
- `prompts/*.md` - AI instruction templates
- `scripts/*.sh` - Shell scripts
- `scripts/*.py` - Python scripts
- `standards/*.md` - AI-optimized engineering standards
- `knowledge/**/*.md` - Tactical knowledge base
- `context/*` - Project context files

**Why:** These should match the template for consistency

### MERGE_SMART (Intelligent JSON Merge)
- `settings.json` - Permission and hook configuration

**Why:** Needs to merge template and project-specific settings

### SKIP_ALWAYS (Never Touch)
- `settings.local.json` - Personal overrides
- `state/` - Runtime state
- `logs/` - Debug logs
- `.backup/` - Backup directory

**Why:** Project-specific or temporary files

### COPY_IF_MISSING (Don't Overwrite)
- `README.md` - Documentation
- `CLAUDE.md` - Project-specific AI instructions

**Why:** Projects may have custom documentation or project-specific rules

## Safety Features

### Automatic Backups

Every sync operation automatically creates a timestamped backup:

```bash
# Sync creates backup automatically
persuade sync .

# Output shows:
# Creating backup...
# ✓ Backup created: 20251204_094915
```

Backups are stored in `.claude/.backup/TIMESTAMP/` and include:
- Complete `.claude/` directory snapshot
- Metadata (timestamp, file count, creation time)
- Automatic cleanup (keeps 10 most recent)

### Automatic Rollback on Errors

If sync fails, the tool automatically attempts rollback:

```
Sync failed: Invalid JSON syntax
Attempting rollback...
✓ Rollback completed
```

### Validation

Post-sync validation ensures:
- settings.json has valid JSON syntax
- Shell scripts have executable permissions
- Required dependencies are present
- Permission patterns use correct syntax

### Dry Run

Always available to preview changes safely:

```bash
persuade sync --dry-run .
```

## Common Workflows

### Onboarding New Project

```bash
cd ~/projects/new-project

# 1. Preview what would be installed
persuade sync --dry-run .

# 2. Perform installation
persuade sync .

# 3. Verify installation
persuade help-command .

# 4. Validate configuration
persuade doctor .
```

### Updating All Projects

```bash
#!/bin/bash
# update-all-projects.sh

PROJECTS=(
  ~/projects/app-1
  ~/projects/app-2
  ~/projects/app-3
)

for project in "${PROJECTS[@]}"; do
  echo "Syncing $project..."
  cd "$project"
  persuade sync .
done
```

### Troubleshooting Issues

```bash
cd ~/projects/my-app

# 1. Check for problems
persuade doctor .

# 2. Auto-fix common issues
persuade doctor --fix .

# 3. If still broken, restore backup
persuade rollback .

# 4. Try sync again with verbose output
persuade sync -v .
```

### Enforcing Standards

```bash
# Preview what custom permissions would be removed
persuade sync --strict --dry-run .

# Apply strict standards (after approval)
persuade sync --strict .
```

## Dependencies

### Required

- **Python 3.11+** - persuade runtime
- **click** - CLI framework (installed with persuade)
- **rich** - Terminal output formatting (installed with persuade)

### System Tools

- **jq** - JSON validation
- **gh** - GitHub CLI (for automation features)
- **bash** - Shell script execution

### Installation

```bash
pip install persuade
```

## Troubleshooting

### "Not inside a git repository"

**Cause:** Running persuade outside a git repository

**Fix:**
```bash
# Initialize git if needed
git init

# Or use --allow-non-git flag (not recommended)
persuade sync --allow-non-git .
```

### "Missing required dependencies"

**Cause:** jq, gh, or bash not installed

**Fix:**
```bash
# macOS
brew install jq gh

# Ubuntu/Debian
sudo apt install jq gh

# Verify
which jq gh bash
```

### "JSON syntax error"

**Cause:** Corrupted settings.json

**Fix:**
```bash
# Restore from backup
persuade rollback .

# Or validate manually
jq . .claude/settings.json
```

### "Permission denied" on scripts

**Cause:** Missing executable permissions

**Fix:**
```bash
# Auto-fix
persuade doctor --fix .

# Or manually
chmod +x .claude/scripts/*.sh
chmod +x .claude/hooks/*.sh
```

## Best Practices

### DO

- Always run `--dry-run` first on important projects
- Keep backups enabled (default behavior)
- Use union mode (default) for most cases
- Run `doctor` after major changes
- Document custom permissions in project README
- Test sync on development projects before production

### DON'T

- Don't use `--no-backup` unless you have external backups
- Don't use `--strict` without previewing with `--dry-run` first
- Don't commit `.claude/settings.local.json` to git
- Don't manually edit synced files (they'll be overwritten)
- Don't sync to non-existent paths

## Related Documentation

- [Claude Code Installation](../README.md#installation)
- [Permission Wildcards](../tips-and-tricks/configuration/claude-code-permission-wildcards.md)
- [PR Iteration Automation](../tips-and-tricks/automation/iterate-pr-reviews.md)
- [Python Virtual Environments](../tips-and-tricks/python/always-use-virtual-environments.md)
