Skip to content

armadillo-sync

Use when installing armadillo for the first time, updating an existing installation, or syncing .claude/ with armadillo’s latest. Replaces both onboarding and updating-armadillo. Also use when the user says “sync”, “onboard”, “init”, “setup”, “install armadillo”, “update armadillo”, “upgrade”, “check for updates”, or “doctor”.

ModelSourceCategory
opuscoreMeta

Tools: Read, Glob, Grep, Bash, Write, Edit, Task, AskUserQuestion, WebFetch, Skill

Context: fork

One skill that always converges to the same end state: your .claude/ is a perfect 1:1 replica of armadillo’s latest. For fresh installs, nuke & replace. For existing armadillo installs, Smart Sync — hash-aware selective updating that auto-accepts untouched files and only prompts for files you modified.

Mandatory Announcement — FIRST OUTPUT before anything else:

┏━ 🛡 armadillo-sync ━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ [syncing .claude/ with armadillo's latest] ┃
┗━━━━━━━━━━━━━━━━━━━━
- First time installing armadillo (no `.claude/` or no manifest)
- Updating an existing armadillo installation (manifest exists, SHA stale)
- Migrating a non-armadillo `.claude/` setup to armadillo standard
- User says "sync armadillo", "update armadillo", "install armadillo", "onboard", "init", "setup", "upgrade", "check for updates", "doctor"
<details>
<summary><strong>Full Reference</strong></summary>
# armadillo-sync
## Overview
One skill that always converges to the same end state: your `.claude/` is a perfect 1:1 replica of armadillo's latest. For fresh installs, nuke & replace. For existing armadillo installs, Smart Sync — hash-aware selective updating that auto-accepts untouched files and only prompts for files you modified.
**Mandatory Announcement — FIRST OUTPUT before anything else:**

┏━ 🛡 armadillo-sync ━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ [syncing .claude/ with armadillo’s latest] ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

Replace the bracket content with the detected context (e.g., "fresh install", "updating v0.5.2 → v0.6.0", "migrating non-armadillo .claude/").
**Model requirement:** This skill involves deep classification, semantic analysis, and contribution pipeline decisions. Use **Opus 4.6** (`claude-opus-4-6`) for any subagent dispatches.
## When to Use
- First time installing armadillo (no `.claude/` or no manifest)
- Updating an existing armadillo installation (manifest exists, SHA stale)
- Migrating a non-armadillo `.claude/` setup to armadillo standard
- User says "sync armadillo", "update armadillo", "install armadillo", "onboard", "init", "setup", "upgrade", "check for updates", "doctor"
## When NOT to Use
- User is mid-task and just wants to use a skill — route to the appropriate skill instead
- User wants to create a new skill — use `writing-skills` or `writing-reference-skills`
## Repo Constant
The upstream repo is always:
```bash
REPO="Armadillo-Nation/armadillo-main-brains"

Never infer the repo slug from local directory names. Never append -cli or any other suffix. This constant is the single source of truth.

Step 1: PREFLIGHT — gh auth, detect entry state
Step 2: NOTIFY — tell user what's about to happen (destructive warning)
Step 3: SCAN — opt-in: check for unique stuff before nuking
Step 4: PRESERVE & CLASSIFY — backup sacreds, hash-compare files, classify into buckets
Step 5: SYNC — smart sync for armadillo state, nuke & replace for empty/non-armadillo
Step 6: RESTORE — put sacreds back, generate CLAUDE.md, wire hooks, write manifest
Step 7: CONTRIBUTE — if scan found unique stuff, auto-PR to master repo

Steps 1–6 always run (some are no-ops for certain entry states). Step 7 only runs if Step 3 found unique artifacts.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Before any GitHub API calls, verify gh CLI is installed and authenticated.

Terminal window
# 1. Check gh CLI is installed
command -v gh >/dev/null 2>&1 || { echo "gh CLI not found. Install from https://cli.github.com"; exit 1; }
# 2. Check keyring auth (not Claude Code's limited GITHUB_TOKEN)
env -u GITHUB_TOKEN gh auth status 2>&1

If command -v gh fails:

gh CLI not installed. Install it first:
brew install gh # macOS
https://cli.github.com # other platforms
Then re-invoke this skill.

If env -u GITHUB_TOKEN gh auth status exits non-zero:

GitHub CLI not authenticated. Run:
gh auth login
Then re-invoke this skill.

If both pass: Continue silently to entry state detection.

StateDetectionBehavior (PLUGIN_DEFAULT=true)
EmptyNo .claude/ directoryPlugin-first install — no file-copy option
Non-armadillo.claude/ exists, no .armadillo-manifest.jsonPlugin install — no file-copy
Armadillo (stale)Manifest exists, version differs from latest⚠ Deprecation warning → auto-migrate to plugin mode
CurrentManifest version matches latest (no marketplace)Suggest migration to plugin mode
plugin-modeManifest has mode: "plugin"Run armadillo-doctor → exit (unchanged)
plugin-readyManifest version matches latest + marketplace reachableAuto-migrate — no prompt

Phase 3 status: PLUGIN_DEFAULT = true — plugin mode is the default path for all new installs and syncs.

Routing logic: scripts/lib/sync-router.js exports routeForState(state, opts) — pass { pluginDefault: false } to restore legacy file-copy behavior.

Deprecation warning (shown on armadillo stale state):

⚠ File-copy sync is deprecated as of vX.Y.0.
armadillo now uses Claude Code's plugin system for faster updates and zero-conflict installs.
Migrating to plugin mode now...

Programmatic detection: scripts/lib/detect-entry-state.js exports detectEntryState(projectDir) — returns one of the 6 state strings above.

Detect entry state: For full detection including plugin states (plugin-mode, plugin-ready), use detectEntryState() from scripts/lib/detect-entry-state.js. Simplified bash example for the 4 base states:

Terminal window
# Check .claude/ exists
if [ ! -d ".claude" ]; then
STATE="empty"
elif [ ! -f ".claude/.armadillo-manifest.json" ]; then
STATE="non-armadillo"
else
# Read current version from manifest
CURRENT_SHA=$(cat .claude/.armadillo-manifest.json | python3 -c "import sys,json; print(json.load(sys.stdin).get('version',''))")
LATEST_SHA=$(env -u GITHUB_TOKEN gh api repos/Armadillo-Nation/armadillo-main-brains/commits/main --jq '.sha')
if [ "$CURRENT_SHA" = "$LATEST_SHA" ]; then
STATE="current"
else
STATE="armadillo"
fi
fi

If state is current: Report “You’re on [SHA] — latest. Nothing to do.” Then run git-setup health check and exit.

Resume detection: If the manifest exists but completed is absent or false, this is an interrupted sync. Read the phase field and resume from there. Inform user: “Found interrupted sync at phase [N]. Resuming.”

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Tell the user exactly what’s about to happen before touching anything.

For Empty state:

armadillo is not installed here.
I'm about to:
▪ Fetch the latest armadillo from GitHub (Armadillo-Nation/armadillo-main-brains)
▪ Write all core skills, agents, hooks, rules, and lib files to .claude/
▪ Install all skill packs
▪ Generate CLAUDE.md and wire hooks
This is a fresh install — nothing will be destroyed.

For Non-armadillo state:

⚠ You have an existing .claude/ directory without an armadillo manifest.
I'm about to:
▪ Optionally scan for anything unique worth keeping (you decide)
▪ Delete the entire .claude/ directory
▪ Replace it with armadillo's latest
Sacreds (agent-memory, context/, progress/, docs/ with real content) are always preserved.
This is destructive for non-sacred files. No per-file negotiation — armadillo replaces everything it covers.

For Armadillo (stale) state:

armadillo is installed but not current.
Current SHA: [current SHA]
Latest SHA: [latest SHA]
I'm about to:
▪ Optionally scan for unique stuff you've added (you decide)
▪ Delete the entire .claude/ directory
▪ Replace it with armadillo's latest
▪ Restore sacreds and re-generate CLAUDE.md
Sacreds (agent-memory, context/, progress/, docs/ with real content) are always preserved.

After presenting the NOTIFY message, proceed to Step 3 (or skip to Step 4 if state is Empty).

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Skip this step entirely if state is Empty — nothing to scan.

Ask the user:

▸ Want me to scan for anything truly unique in your .claude/ before I nuke it?
(custom skills, project-specific agents, codebase-specific stuff)
yes → I'll check what's worth keeping / contributing upstream
no → Skip to nuke & replace (fastest path)

Use AskUserQuestion to capture yes/no. If no → skip to Step 4.

Pass A: Inventory .claude/

For each file in .claude/, classify as either:

BucketMeaningAction
ArmadilloMatches any armadillo skill/agent/hook/rule by name OR semantically (semantic matching)Will be replaced — no question
UniqueDoes something armadillo has no equivalent forQueue for contribution pipeline

Binary classification only — no per-file walkthrough. Path match is fast. For anything that doesn’t path-match, read the content and compare semantically against armadillo’s known skill descriptions.

Semantic matching rule: If the file’s core purpose is 100% covered by an existing armadillo skill or agent, classify as Armadillo. If it does something armadillo has no equivalent for, classify as Unique.

Pass B: Inventory codebase

Scan the actual project (not .claude/) for patterns suggesting custom artifacts should be created:

SignalCreates
Framework not covered by existing packsNew pack skill
Unique API integrationsReference skill via writing-reference-skills
Complex deploy pipelineDeploy skill
Domain-specific patternsDomain agent
Business data (NAP, brand)nap-ninja / brand flow recommendation

Output scan results:

Unique .claude/ artifacts (will be contributed upstream):
▪ skills/acuity-booking/ — appointment flow not in armadillo
▪ agents/seo-auditor.md — custom SEO reviewer
Codebase-driven recommendations:
▪ Detected: Payload CMS + custom collections → recommend payload skill
▪ Detected: Cloudflare Workers deploy via wrangler → recommend wrangler-deploy skill
These will be created to armadillo spec and auto-PR'd to the master repo after sync.
Proceed?

If scan finds nothing unique: “Nothing unique found — nothing to contribute. Proceeding to nuke & replace.”

Store the list of unique artifacts in memory for Step 7.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

4a. Sacred Files — Always Backed Up First

Section titled “4a. Sacred Files — Always Backed Up First”

These survive every sync. Back them up before anything else.

PathWhy Sacred
agent-memory/*/MEMORY.mdAccumulated agent knowledge — irreplaceable domain expertise
context/Runtime state written by hooks (SWARM-STATE.md, logs, audit snapshots)
progress/Session handoffs, plans, designs, optimization logs
docs/ with real content (>10 lines, not templates)Brand guides, architecture docs, research
.armadillo-manifest.jsonVersion tracking — restored with updated SHA
CLAUDE.md content below <!-- armadillo:end -->User’s project-specific instructions

Backup procedure:

Terminal window
mkdir -p /tmp/armadillo-sync-preserve
[ -d ".claude/agent-memory" ] && cp -r .claude/agent-memory /tmp/armadillo-sync-preserve/
[ -d ".claude/context" ] && cp -r .claude/context /tmp/armadillo-sync-preserve/
[ -d ".claude/progress" ] && cp -r .claude/progress /tmp/armadillo-sync-preserve/
[ -d ".claude/docs" ] && cp -r .claude/docs /tmp/armadillo-sync-preserve/
if [ -f "CLAUDE.md" ]; then
python3 -c "
content = open('CLAUDE.md').read()
marker = '<!-- armadillo:end -->'
idx = content.find(marker)
if idx != -1:
custom = content[idx + len(marker):]
if custom.strip():
open('/tmp/armadillo-sync-preserve/claude-md-custom.txt', 'w').write(custom)
"
fi

Skip Steps 4b–4d for Empty and Non-armadillo states — go straight to Step 5 (nuke & replace path).

4b. Hash Every Non-Sacred File (Armadillo state only)

Section titled “4b. Hash Every Non-Sacred File (Armadillo state only)”

For each file in .claude/ that is NOT a sacred path, compute a sha256 hash and compare against the manifest:

Terminal window
find .claude -type f \
! -path '.claude/agent-memory/*' \
! -path '.claude/context/*' \
! -path '.claude/progress/*' \
! -path '.claude/docs/*' \
! -name '.armadillo-manifest.json' \
| while read f; do
shasum -a 256 "$f" | cut -d' ' -f1
done

Compare each file’s current hash against the hash value stored in the manifest’s files map.

Use the GitHub Compare API to get which files changed between the installed SHA and the latest:

Terminal window
CURRENT_SHA=$(cat .claude/.armadillo-manifest.json | python3 -c "import sys,json; print(json.load(sys.stdin)['version'])")
LATEST_SHA=$(env -u GITHUB_TOKEN gh api repos/Armadillo-Nation/armadillo-main-brains/commits/main --jq '.sha')
env -u GITHUB_TOKEN gh api "repos/Armadillo-Nation/armadillo-main-brains/compare/${CURRENT_SHA}...${LATEST_SHA}" \
--jq '.files[] | {filename: .filename, status: .status}'

For each non-sacred .claude/ file, classify using local hash vs manifest + upstream diff status:

Local hash == manifestUpstream changedBucketAction
Yes (untouched)YesuntouchedAuto-replace with upstream
Yes (untouched)NoskipAlready current, no action
No (modified)YesmodifiedPrompt user
No (modified)Nouser-onlyKeep user’s version
Added upstreamnewAuto-add
Removed upstreamremovedAuto-delete
Sacred pathsacredAlready backed up, skip

Sync Summary — output bucket counts before proceeding:

Sync Summary
────────────
untouched (auto-replace) 42 files
new (auto-add) 3 files
removed (auto-delete) 1 file
user-only (keeping yours) 5 files
modified (needs decision) 4 files ← prompt required
sacred (preserved) 3 paths

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Two paths depending on entry state.


Path A — Blind Nuke & Replace (Empty or Non-armadillo states)

Section titled “Path A — Blind Nuke & Replace (Empty or Non-armadillo states)”

No manifest = no hash baseline. Delete and start fresh.

Terminal window
rm -rf .claude/

Then fetch the full armadillo tree and write everything (see fetch commands in Path B → 5c).


Path B — Smart Sync (Armadillo state — selective)

Section titled “Path B — Smart Sync (Armadillo state — selective)”

For existing armadillo installs, SMART SYNC replaces the blind nuke. Only touch what needs touching.

No prompts for these — just execute:

BucketAction
untouchedFetch upstream version, overwrite local
newFetch upstream file, write to local path
removedDelete local file
user-onlyLeave untouched — user modified, upstream didn’t
sacredSkip — already backed up in Step 4a

When the modified bucket is non-empty, ask the user how to handle them as a group via AskUserQuestion:

4 files changed both locally and upstream:
skills/armadillo-sync/SKILL.md
rules/output-style.md
hooks/session-start.sh
agents/code-reviewer.md
How do you want to handle these?
1. Accept all upstream — take armadillo's version for all
2. Keep all mine — keep your local version for all
3. Walk through each — decide file by file (with Show diff option)
4. Accept by category — accept by file type (skills, rules, hooks, agents)

Option 3 — Walk through each: For each modified file, show filename and prompt:

skills/armadillo-sync/SKILL.md
a. Accept upstream
b. Keep mine
c. Show diff ← renders a unified diff before deciding

Option 4 — Accept by category: Group files by type (skills/, rules/, hooks/, agents/) and prompt once per group.

Files the user keeps locally are flagged userKept: true in the manifest (see Step 6d).

Terminal window
REPO="Armadillo-Nation/armadillo-main-brains"
# Fetch .claude/ file tree
env -u GITHUB_TOKEN gh api repos/Armadillo-Nation/armadillo-main-brains/git/trees/main --field recursive=1 --jq '.tree[] | select(.path | startswith(".claude/")) | .path'
# Fetch all pack files
env -u GITHUB_TOKEN gh api repos/Armadillo-Nation/armadillo-main-brains/git/trees/main --field recursive=1 --jq '.tree[] | select(.path | startswith("packs/")) | .path'

For each file, fetch content and write locally. Packs install to .claude/skills/<name>/SKILL.md.

Method 1 — GitHub CLI (preferred):

Terminal window
env -u GITHUB_TOKEN gh api repos/Armadillo-Nation/armadillo-main-brains/contents/.claude/skills/brainstorming/SKILL.md --jq '.content' | base64 -d

Method 2 — WebFetch (fallback):

https://raw.githubusercontent.com/Armadillo-Nation/armadillo-main-brains/main/.claude/skills/brainstorming/SKILL.md
Terminal window
mkdir -p .claude/context .claude/agent-memory .claude/progress .claude/docs

Progress report during sync:

Syncing armadillo...
✓ untouched (42 auto-replaced)
✓ new (3 added)
✓ removed (1 deleted)
✓ user-only (5 kept)
✓ modified (4 resolved by user)
✓ Packs: frontend (16), backend (4), database (6), ... [all packs]
Total: [N] skills across [N] packs

Path C — Migrate to Plugin Mode (plugin-ready state)

Section titled “Path C — Migrate to Plugin Mode (plugin-ready state)”

When detectEntryState returns plugin-ready, offer migration:

armadillo detected marketplace connectivity.
▸ Migrate to plugin mode? (skills load from registry, not file copies)
yes → run 8-step migration below
no → continue with standard file-copy sync

8-step migration (powered by scripts/lib/migrate-to-plugin.js):

  1. BACKUP sacred dirs: agent-memory, context, progress, docs
  2. CONFIGURE plugin settings: marketplace URL, enabled plugins list
  3. MARK managed rules with # armadillo:managed comment
  4. REMOVE armadillo-managed files: skills/, agents/, hooks/, lib/
  5. SLIM CLAUDE.md to plugin-mode format via generate-claude-md.js
  6. RESTORE sacred dirs from backup
  7. MANIFEST update: set mode: "plugin", write marketplace URL
  8. DOCTOR run health checks via scripts/lib/doctor-plugin.js

If state is plugin-mode: Skip sync entirely — run armadillo-doctor skill and exit. Plugin-mode projects are managed by the marketplace, not file-copy sync.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Terminal window
# Restore preserved sacred files
[ -d "/tmp/armadillo-sync-preserve/agent-memory" ] && cp -r /tmp/armadillo-sync-preserve/agent-memory .claude/
[ -d "/tmp/armadillo-sync-preserve/context" ] && cp -r /tmp/armadillo-sync-preserve/context .claude/
[ -d "/tmp/armadillo-sync-preserve/progress" ] && cp -r /tmp/armadillo-sync-preserve/progress .claude/
[ -d "/tmp/armadillo-sync-preserve/docs" ] && cp -r /tmp/armadillo-sync-preserve/docs .claude/
# Clean up temp directory
rm -rf /tmp/armadillo-sync-preserve
  1. Write armadillo section between <!-- armadillo:start --> and <!-- armadillo:end --> markers:

    • Skills list (organized by category)
    • Pack table listing installed packs
    • Rules table
    • Model selection table
    • Permissions section
  2. Restore custom section below the markers:

    • If user had custom CLAUDE.md content (backed up in Step 4) → place it below
    • Add comment: <!-- Add your project-specific instructions below this line -->

hooks.json sync:

Fetch the latest .claude/hooks/hooks.json from GitHub (already done in Step 5b). This is already written. No merge needed — it’s a clean install.

settings.json hooks section:

Rebuild from hooks.json — hooks.json is the source of truth for the hooks section.

bypassPermissions:

Offer the permission mode:

armadillo works best with bypassPermissions mode.
▪ Auto-approves all tool calls except the deny-list
▪ Deny-list still blocks catastrophic commands (rm -rf /, force push, etc.)
▸ Enable bypassPermissions? (Recommended)

Use AskUserQuestion:

  • “Yes, enable it (Recommended)” → set defaultMode to "bypassPermissions" in .claude/settings.json
  • “No, keep acceptEdits” → leave as-is

Hook scripts (.sh):

All hook scripts are already written in Step 5b. Ensure they’re executable:

Terminal window
chmod +x .claude/hooks/*.sh

Rules sync:

Rules are already written in Step 5b as part of the full .claude/ sync. No additional action needed.

git-setup integration:

Invoke the git-setup skill to detect and configure the project’s git strategy:

Invoke Skill tool with skill="git-setup"

This checks for branch protection, git-workflow rule, conventional commits, and version-bump automation. Skips components that are already in place.

{
"version": "<latest commit SHA from GitHub>",
"repoUrl": "https://github.com/Armadillo-Nation/armadillo-main-brains",
"installedAt": "<ISO 8601 timestamp>",
"updatedAt": "<ISO 8601 timestamp>",
"completed": true,
"installedPacks": ["frontend", "backend", "database", "...all packs"],
"files": {
"skills/brainstorming/SKILL.md": {
"owner": "armadillo",
"hash": "<sha256>"
},
"skills/armadillo-sync/SKILL.md": {
"owner": "armadillo",
"hash": "<sha256>",
"userKept": true
},
"agent-memory/seo-specialist/MEMORY.md": {
"owner": "user",
"hash": "<sha256>"
}
}
}

userKept: true is set on any file where the user chose “Keep all mine” or “Keep mine” during the modified-file prompt in Step 5b. It signals that on the next sync, this file’s local hash will differ from the manifest hash by design — the comparison logic skips re-flagging it as modified unless upstream changes again after the userKept was recorded.

**Get latest SHA:**
```bash
env -u GITHUB_TOKEN gh api repos/Armadillo-Nation/armadillo-main-brains/commits/main --jq '.sha'

Compute file hashes:

Terminal window
shasum -a 256 .claude/skills/brainstorming/SKILL.md | cut -d' ' -f1

Track ALL files — both armadillo-owned and user-owned sacreds. Write manifest to .claude/.armadillo-manifest.json.

## Sync Complete
Installed:
▪ armadillo core (29 skills)
▪ [N] packs, [N] total skills
▪ [N] agents
▪ Hooks configured (session-start, reinject-after-compact, task-completed)
▪ hooks.json wired
▪ settings.json updated
▪ CLAUDE.md generated
▪ Manifest written (SHA: [sha])
Preserved:
▪ agent-memory/ (N agents)
▪ context/ (runtime state)
▪ progress/ (N files)
▪ docs/ (N files)
▪ CLAUDE.md custom section
● ahh, that felt good didn't it?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Only runs if Step 3 found unique artifacts.

If the scan was skipped or found nothing unique, skip this step entirely.

For each unique artifact identified in Step 3, use armadillo-maker to create it to armadillo spec:

Invoke Skill tool with skill="armadillo-maker"
args: "Create [artifact type]: [name] — [description from scan]"

armadillo-maker runs its full 10-phase pipeline:

  1. Recon — understand the domain
  2. Research — gather technical context
  3. Design — spec the artifact
  4. TDD — write tests first
  5. Implement — write the skill/agent/rule
  6. Register — wire into armadillo.json
  7. Document — update CLAUDE.md
  8. Verify — run tests, confirm quality
  9. Commit — local commit
  10. Deliver — ready for contribution

Each artifact created locally in .claude/ works immediately — the user doesn’t have to wait for the PR to merge.

After artifact creation, push to the master armadillo repo:

Terminal window
# Create a contribution branch on the master repo
REPO="Armadillo-Nation/armadillo-main-brains"
ARTIFACT_NAME="<kebab-case artifact name>"
BRANCH="contrib/${ARTIFACT_NAME}"
# Push the artifact files to the contribution branch
env -u GITHUB_TOKEN git push "https://github.com/${REPO}.git" HEAD:"refs/heads/${BRANCH}"

If user lacks push access: Skip gracefully.

No push access to Armadillo-Nation/armadillo-main-brains.
Artifact [name] works locally in your .claude/.
Submit manually: https://github.com/Armadillo-Nation/armadillo-main-brains/pulls

If push succeeded, create a PR:

Terminal window
SLUG="Armadillo-Nation/armadillo-main-brains"
env -u GITHUB_TOKEN gh api "repos/${SLUG}/pulls" \
--method POST \
--field title="feat(pack): add <artifact-name>" \
--field head="contrib/<artifact-name>" \
--field base="main" \
--field body="$(cat <<'EOF'
## Why
Auto-contributed from armadillo-sync. User's project had a unique artifact worth sharing.
## Changes
▪ Added <artifact-type>: <artifact-name>
▪ <description of what it does>
## Test plan
▪ Run: node --test tests/<artifact-name>.test.js
▪ Verify skill announcement renders correctly
▪ Confirm no banned terminology (plugin refs, restart instructions)
Generated with [Claude Code](https://claude.com/claude-code)
EOF
)"

Use writing-prs for full PR description guidance when crafting the contribution PR body.

Branch naming: contrib/<artifact-name>

Contribution flow:

User's project Master armadillo repo
───────────── ─────────────────────
Scan finds unique stuff
armadillo-maker creates artifact
Artifact works immediately locally
Push branch → contrib/<artifact-name>
Auto-PR → feat(pack): add <artifact>
Owner reviews + merges
Next release includes it → vX.Y.Z
All Armadilloers get it on next sync

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

The NUKE & SYNC (Step 5) + RESTORE (Step 6) together handle complete infrastructure replacement. Key details:

The full hooks.json is fetched from the master repo and written directly — it’s a clean replace, not a merge. After restore, any user-added hooks that were in the old hooks.json are lost (they weren’t sacred files). If the user had custom hooks in .claude/hooks/, those scripts would need to be contributed upstream or re-wired manually.

The settings.json is fetched from the master repo. The bypassPermissions preference is re-applied in Step 6c via user prompt — it doesn’t carry over automatically since the file was nuked.

hooks section in settings.json is always rebuilt from hooks.jsonhooks.json is the source of truth.

All .sh hook scripts are fetched from the master repo and written in Step 5b:

  • session-start.sh
  • reinject-after-compact.sh
  • run-hook.cmd
  • task-completed.sh

All made executable via chmod +x in Step 6c.

All files under .claude/rules/ are fetched from the master repo and written in Step 5b. User-added rules (not in the master repo) are lost — they should be contributed upstream via the contribution pipeline if worth keeping.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

When the PLUGIN_DEFAULT=true env flag is set:

  • New installs use scripts/lib/plugin-first-install.js — plugin mode from the start, no file copies
  • Existing armadillo installs get a migration offer on next sync (Step 5C)
  • File-copy mode remains available via PLUGIN_DEFAULT=false override

This flag gates the transition period. When unset (current default), behavior is unchanged — file-copy sync runs as normal.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Edge CaseHandling
No internet / gh not authedPreflight catches, clear error with fix instructions
.claude/ but no gitSync works — just file operations, no git required
Custom CLAUDE.md contentPreserved below armadillo markers in Step 4 → restored in Step 6b
Interrupted syncManifest tracks completed: false + phase: N, resume next run
No push access to armadillo repoContribution skipped gracefully, artifact stays local
User says no to scanSkip Step 3, proceed directly to Step 4
Scan finds nothing uniqueReport “nothing unique” → proceed to Step 4
Already current (SHA matches)Report “up to date” → exit after git-setup health check
Empty project (greenfield)Fresh install → after sync, offer fresh-project flow
Manifest says completed: falseInterrupted sync detected — resume from saved phase
Writing-skills needed for codebase artifactsUse writing-skills for generic skills, writing-reference-skills for API/external tool reference skills

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  1. One flow for all states — install, update, migrate all follow the same 7 steps
  2. Sacred files are inviolable — agent-memory, context/, progress/, docs/ (>10 lines) always survive the nuke
  3. No per-file conflict resolution — the answer is always “use armadillo’s version”; unique things go through Step 3 scan
  4. All packs installed unconditionally — every Armadilloer gets the complete library
  5. REPO constant is fixed — always Armadillo-Nation/armadillo-main-brains, never inferred from local paths
  6. Manifest tracks everything — every file in .claude/ gets an entry with owner and hash
  7. Contribution is the philosophy — unique artifacts don’t stay local-only; if worth keeping, worth sharing
  8. bypassPermissions is recommended — always offer it; never force it
  9. git-setup runs after every sync — ensures git hygiene is current
  10. Resume on interrupt — manifest’s completed and phase fields enable safe re-entry
  11. Smart Sync for existing installs — when manifest exists, classify files by hash comparison instead of blind nuke. Only prompt for files the user actually modified AND upstream also changed.
MistakeFix
Asking per-file keep/replace decisionsNo — Smart Sync is the default for existing installs; only modified+upstream-changed files get a prompt
Forgetting to backup sacreds before nukeStep 4 always runs before Step 5
Inferring repo slug from local directory nameAlways use the REPO constant — local dir name is irrelevant
Interactive pack selectionGone — all packs always installed
Instructing users to open a new Claude Code sessionNever — armadillo-sync takes effect immediately, no new session needed
Leaving unique artifacts local-onlyStep 7 pushes them upstream — nothing stays local-only
Nuking .claude/ without checking for sacredsStep 4 explicitly backs them up first
Missing the manifest completed fieldAlways write it as true on success; update it to false + phase number on interrupt
Not wiring git-setup after syncStep 6c always invokes git-setup
Leaving hook scripts non-executableStep 6c always runs chmod +x .claude/hooks/*.sh
Using plugin or marketplace terminologyarmadillo is git-native file copy — no plugin system, no marketplace, no registry files