update-target-projects
Discover and sync all toolkit-using projects with the latest skills. Use when skills are modified, after the post-commit hook reminds you, or to batch-sync multiple projects.
SKILL.md
| Name | update-target-projects |
| Description | Discover and sync all toolkit-using projects with the latest skills. Use when skills are modified, after the post-commit hook reminds you, or to batch-sync multiple projects. |
name: update-target-projects description: Discover and sync all toolkit-using projects with the latest skills. Use when skills are modified, after the post-commit hook reminds you, or to batch-sync multiple projects. toolkit-only: true
Update Target Projects
Discover and sync all toolkit-using projects, the Codex CLI skill pack, and global Conductor skill symlinks with the latest skills.
Trigger
Use this skill when:
- The post-commit hook reminds you to sync after skill changes
- You want to batch-sync multiple projects at once
- You need to check which projects are out of date
- You want to update the Codex CLI skill pack
- You want to verify global skill symlinks for Conductor autocomplete
Configuration
Codex skill pack location:
$CODEX_HOME/skillsifCODEX_HOMEis set~/.codex/skills(default)
Project search paths:
$TOOLKIT_SEARCH_PATHenvironment variable (colon-separated paths)~/Projects(default)
Search depth: 4 levels (finds ~/Projects/*/, ~/Projects/*/*/, and ~/Projects/*/*/*/)
Global skills location: ~/.claude/skills/ (symlinks for Conductor autocomplete)
Workflow
Copy this checklist and track progress:
Update Target Projects Progress:
- [ ] Phase 1: Discover projects with toolkit-version.json
- [ ] Phase 1b: Check Codex CLI skill pack status
- [ ] Phase 1c: Check global skill symlinks (Conductor autocomplete)
- [ ] Phase 1d: Detect orphaned skills (removed from toolkit)
- [ ] Phase 1e: Check workstream scripts status
- [ ] Phase 1f: Check skill resolution mode for each project
- [ ] Phase 2: Detect activity status for each project
- [ ] Phase 3: Check sync status (OUTDATED vs CURRENT)
- [ ] Phase 4: Display status report (including orphans, global status, and resolution)
- [ ] Phase 5: User selection (what to sync)
- [ ] Phase 6a: Sync Codex skill pack (if selected) — includes deletions
- [ ] Phase 6b: Sync global skill symlinks (if selected)
- [ ] Phase 6c: Sync target projects (if selected) — includes deletions
- [ ] Phase 6d: Sync workstream scripts (if selected)
- [ ] Phase 6g: Sync Codex App setup wrapper (if selected)
- [ ] Phase 6e: Adopt global skills (if selected) — migrate local to global
- [ ] Phase 6f: Revert to local skills (if selected) — copy from global back to project
- [ ] Phase 7: Generate summary report
Phase 1: Discover Projects
See PROJECT_SYNC.md for detailed discovery and sync logic.
- Find all
toolkit-version.jsonfiles in search paths - Read each file and verify
toolkit_locationmatches - Extract
toolkit_commitandlast_synctimestamps
Phase 1b: Check Codex CLI Skill Pack
See CODEX_SYNC.md for detailed Codex sync logic.
- Discover skills dynamically from toolkit
- Classify each skill: MISSING, SYMLINK_CURRENT, COPY_OUTDATED, etc.
- Determine overall Codex status
Phase 1c: Check Global Skill Symlinks
See GLOBAL_SYNC.md for detailed global sync logic.
- Scan
~/.claude/skills/for existing entries - Classify each: SYMLINK_CURRENT, MISSING, SYMLINK_OTHER, REAL_DIR
- Detect orphaned symlinks (pointing to deleted toolkit skills)
- Determine overall global status
Phase 1e: Check Workstream Scripts Status
Detect .workstream/ scripts in target projects and compare file hashes with toolkit:
- Check if target has
.workstream/directory - For each script (
lib.sh,setup.sh,dev.sh,verify.sh,README.md):- Compare SHA256 hash with toolkit version
- Classify: MISSING, CURRENT, OUTDATED
- Check
workstream.json.exampleseparately (it's a reference, not a project file) - Track status in
toolkit-version.jsonunder a"workstream"key
Status determination:
MISSING— no.workstream/directory in targetCURRENT— all script hashes match toolkitOUTDATED— one or more scripts differ from toolkit
Phase 1f: Check Skill Resolution Mode
For each target project, determine current skill resolution state:
check_project_resolution() {
local project_path="$1"
local version_file="$project_path/.claude/toolkit-version.json"
local skills_dir="$project_path/.claude/skills"
# Read current resolution from config
local resolution=$(jq -r '.skill_resolution // "unknown"' "$version_file" 2>/dev/null)
local force_local=$(jq -r '.force_local_skills // null' "$version_file" 2>/dev/null)
# Check actual state: are there local skill directories?
local has_local_skills=false
local local_count=0
if [[ -d "$skills_dir" ]]; then
local_count=$(find "$skills_dir" -maxdepth 1 -mindepth 1 -type d 2>/dev/null | wc -l)
if [[ "$local_count" -gt 0 ]]; then
has_local_skills=true
fi
fi
# Check if global symlinks are healthy
local globals_healthy=false
if all_skills_globally_usable 2>/dev/null; then
globals_healthy=true
fi
# Respect force_local_skills override
if [[ "$force_local" == "true" ]]; then
echo "LOCAL_FORCED"
return
fi
# Determine resolution state
if [[ "$has_local_skills" == "true" ]]; then
if [[ "$globals_healthy" == "true" ]]; then
echo "ADOPTABLE" # Can migrate to global
else
echo "LOCAL" # Must stay local (globals not ready)
fi
else
# No local skills
if [[ "$globals_healthy" == "true" ]]; then
echo "GLOBAL" # Resolving via global symlinks
else
echo "MISSING" # Neither local nor global available!
fi
fi
}
| Resolution State | Meaning | Available Actions |
|---|---|---|
GLOBAL | Using global symlinks (healthy) | Revert to local (option 9) |
LOCAL | Local copies, globals not ready | Sync locally |
LOCAL_FORCED | Local copies, force_local_skills: true | Sync locally (override active) |
ADOPTABLE | Local, but global available | Adopt global (option 8) |
MISSING | No local, no healthy global | ⚠️ Skills unavailable — run global sync first |
Phase 1d: Detect Orphaned Skills
Identify skills that exist in targets but have been removed from toolkit:
- Compare installed skills against current toolkit skills
- Mark as ORPHANED if skill directory no longer exists in toolkit
- Check if orphaned skills have local modifications
See CODEX_SYNC.md and PROJECT_SYNC.md for orphan detection logic.
Phase 2-3: Activity and Sync Status
For each project:
- Classify activity: ACTIVE (uncommitted), RECENT (modified <24h), DORMANT
- Check if sync needed by comparing commits
Phase 4: Display Status Report
TOOLKIT SYNC STATUS
===================
Toolkit: /path/to/toolkit
Current: abc1234 (2026-01-23)
GLOBAL SKILLS (Conductor Autocomplete)
───────────────────────────────────────
Location: ~/.claude/skills
Status: CURRENT (30 symlinks active)
CODEX CLI SKILL PACK
────────────────────
Location: ~/.codex/skills
Status: {status summary}
TARGET PROJECTS
───────────────
# Project Sync Status Resolution Adoptable Activity
─────────────────────────────────────────────────────────────────────
1 ~/Projects/app OUTDATED local ✓ (30 dirs) DORMANT
2 ~/Projects/api CURRENT global — RECENT
3 ~/Projects/lib CURRENT local ⚠️ 2 modified ACTIVE
Resolution column values:
global— Skills resolve via~/.claude/skills/symlinkslocal— Skills copied to project's.claude/skills/mixed— Some global, some local
Adoptable column values:
✓ (N dirs)— Can adopt global resolution (N skill directories to remove)⚠️ N modified— Can adopt, but N skills have local modifications—— Already using global resolution (or not applicable)
Phase 5: User Selection
Prompt with options:
- Sync everything (Recommended)
- Global skill symlinks only
- Codex skill pack only
- Target projects only
- Select specific items
- Include ACTIVE projects too
- Skip for now
- Adopt global skills (remove local copies, switch to global resolution)
- Revert to local skills (copy from global back to project)
Option 8 visibility: Only show if at least one project is ADOPTABLE (has local
copies and global symlinks are healthy).
Option 9 visibility: Only show if at least one project uses global resolution.
Phase 6: Execute Sync
6a: Codex Sync — See CODEX_SYNC.md 6b: Global Skills Sync — See GLOBAL_SYNC.md 6c: Project Sync — See PROJECT_SYNC.md
6d: Workstream Scripts Sync — Copy .workstream/*.sh, README.md, and workstream.json.example to target projects:
- For each target project selected for sync:
- Create
.workstream/directory if missing - Copy scripts:
lib.sh,setup.sh,dev.sh,verify.sh - Copy documentation:
README.md,workstream.json.example - Run
chmod +x .workstream/*.sh - Verify with
ls -la .workstream/*.shthat scripts exist and have executable permissions.
- Create
- Compare hashes before copying — skip if CURRENT
- Update
toolkit-version.json"workstream"key with new hashes. Read back the file to confirm valid JSON. - Do NOT copy or overwrite
workstream.json(project-owned config)
6g: Codex App Setup Wrapper Sync — Copy .codex/setup.sh to target projects:
- For each target project selected for sync:
- Create
.codex/directory if missing - Copy
setup.shfrom toolkit.codex/setup.sh - Run
chmod +x .codex/setup.sh - Verify with
ls -la .codex/setup.shthat the file exists and is executable.
- Create
- Compare hashes before copying — skip if CURRENT
- Do NOT overwrite
.codex/environments/or other Codex App config (project-owned)
6e: Adopt Global Skills — Migrate from local to global resolution:
See GLOBAL_SYNC.md for state model and helper definitions.
Pre-flight checks:
- Verify global health:
all_skills_globally_usable()must return true - If unhealthy: abort with message "Global symlinks not healthy. Run sync first (option 1)."
For each selected project:
-
Detect modified local skills — skills where current hash ≠ stored hash:
find_modified_skills() { local project_path="$1" local modified=() for skill in $(ls "$project_path/.claude/skills/" 2>/dev/null); do local stored_hash=$(jq -r ".files[\".claude/skills/$skill/SKILL.md\"].hash // empty" \ "$project_path/.claude/toolkit-version.json") if [[ -n "$stored_hash" ]]; then local current_hash=$(shasum -a 256 "$project_path/.claude/skills/$skill/SKILL.md" | cut -d' ' -f1) if [[ "$current_hash" != "$stored_hash" ]]; then modified+=("$skill") fi fi done echo "${modified[@]}" } -
Show migration preview:
ADOPT GLOBAL SKILLS: ~/Projects/app ──────────────────────────────────── Will remove: 30 skill directories Modified skills: 2 (will be backed up) After migration: Skills resolve via ~/.claude/skills/ ⚠️ This project will no longer contain .claude/skills/. Collaborators without ~/.claude/skills/ will lose access. Proceed? [y/N] -
If user confirms:
- Back up modified skills to
.claude/skills.bak/{skill}/(if any) - Verify with
ls .claude/skills.bak/that backups were created before proceeding with deletion. - Delete local skill directories:
# Note: glob must be OUTSIDE quotes to expand if [[ -d "$project_path/.claude/skills" ]]; then rm -rf "$project_path/.claude/skills/"*/ fi - Verify with
ls "$project_path/.claude/skills/"that skill directories were removed. - Update toolkit-version.json:
- Set
"skill_resolution": "global" - Set each file's
"resolution": "global"
- Set
- Read back
toolkit-version.jsonto confirm valid JSON and thatskill_resolutionis"global". - DO NOT use
git rm— let user review and commit
- Back up modified skills to
-
Report:
✓ Migrated ~/Projects/app to global skill resolution Removed: 30 skill directories Backed up: 2 modified skills → .claude/skills.bak/ Skills now resolve via: ~/.claude/skills/
6f: Revert to Local Skills — Copy from global back to project:
For projects that were migrated to global but need portability:
-
Show revert preview:
REVERT TO LOCAL SKILLS: ~/Projects/app ─────────────────────────────────────── Will copy: 30 skills from ~/.claude/skills/ Target: .claude/skills/ After revert: Skills copied locally for portability Proceed? [y/N] -
If user confirms:
- Create
.claude/skills/directory - For each globally-resolved skill:
- Copy from global symlink target to local
- Verify with
ls .claude/skills/that expected skill directories were copied. - Update toolkit-version.json:
- Set
"skill_resolution": "local" - Set each file's
"resolution": "local" - Update hashes and timestamps
- Set
- Read back
toolkit-version.jsonto confirm valid JSON and thatskill_resolutionis"local".
- Create
-
Report:
✓ Reverted ~/Projects/app to local skill resolution Copied: 30 skills to .claude/skills/ Skills now resolve via: project-local copies
Phase 7: Summary Report
SYNC COMPLETE
=============
Global Skills (Conductor Autocomplete):
Symlinks created: 2
Symlinks removed: 1 (orphaned)
Symlinks repaired: 0
Already current: 28
Codex CLI Skill Pack:
Skills updated: 3
Skills deleted: 1 (orphaned)
Already current: 12
Target Projects:
Projects processed: 4
Synced: 2
Skipped: 1 (active)
Current: 1
Skills deleted: 1 (orphaned)
Resolution Changes:
Adopted global: 1 project (30 local dirs removed)
Reverted local: 0 projects
Modified backed up: 2 skills → .claude/skills.bak/
Deleted Skills (removed from toolkit):
- multi-model-verify
All synced items are now at toolkit commit abc1234
If projects were migrated:
MIGRATION SUMMARY
─────────────────
Projects migrated to global resolution:
✓ ~/Projects/app (30 skills)
✓ ~/Projects/api (30 skills)
These projects now use ~/.claude/skills/ symlinks.
Local skill copies have been removed.
Note: Collaborators need ~/.claude/skills/ symlinks to access skills.
Run this from their toolkit clone: /update-target-projects → option 2
Error Handling
| Situation | Action |
|---|---|
No toolkit-version.json files found in search paths | Report "No toolkit-using projects found in {search paths}" and list the paths searched; suggest running /setup first |
toolkit_location in a project's toolkit-version.json points to a different toolkit | Skip that project with a warning; do not sync skills from a mismatched toolkit |
cp -r or symlink creation fails during sync | Report the specific failure, continue syncing remaining items, include failures in the summary report |
rm -rf fails during global adoption (option 8) | STOP adoption for that project, report permission error, do not update toolkit-version.json to "global" |
gh or git commands fail during discovery | Report the error, skip affected projects, continue with remaining projects |
Edge Cases
See EDGE_CASES.md for handling:
- Codex directory doesn't exist
- No projects found
- Project uses different toolkit
- Git not available
- Sync conflicts
REMINDER: For projects using local resolution, always copy skills to target projects, not just update toolkit-version.json. The version file tracks state, but skills must actually be copied for changes to take effect. Projects using global resolution don't need local copies—they resolve via ~/.claude/skills/ symlinks.