setup
Initialize a new project with the AI Coding Toolkit. Use when setting up toolkit skills in a new or existing project.
SKILL.md
| Name | setup |
| Description | Initialize a new project with the AI Coding Toolkit. Use when setting up toolkit skills in a new or existing project. |
name: setup description: Initialize a new project with the AI Coding Toolkit. Use when setting up toolkit skills in a new or existing project. argument-hint: [target-directory] allowed-tools: Bash, Read, Write, AskUserQuestion toolkit-only: true
Initialize a new project at $1 with the AI Coding Toolkit.
Steps
- Directory guard (must run from toolkit repo)
- Confirm
.toolkit-markerexists in the current working directory - If it is missing, STOP and tell the user to
cdinto theai_coding_project_basetoolkit repo and re-run/setup $1
- Confirm
0.5. Idempotency Check
Check if target already has toolkit installed:
if [[ -f "$1/.claude/toolkit-version.json" ]]; then
EXISTING_COMMIT=$(jq -r '.toolkit_commit' "$1/.claude/toolkit-version.json")
CURRENT_COMMIT=$(git rev-parse HEAD)
fi
Decision logic:
- If
toolkit-version.jsondoesn't exist → proceed with full setup (existing flow) - If exists and
toolkit_commit= current HEAD → report "Already up to date" and skip to Step 7 (success report) - If exists and
toolkit_commit≠ current HEAD → proceed with incremental update (Step 3a)
Store the result as SETUP_MODE:
SETUP_MODE=full— new installationSETUP_MODE=current— already up to dateSETUP_MODE=incremental— updating existing installation
-
Validate target directory
- If
$1is empty, ask the user for the target directory path - Check if the directory exists; if not, offer to create it
- If
-
Ask project type
- Greenfield: Starting a new project from scratch
- Feature: Adding a feature to an existing project
2a. For Feature type: Ask feature name and create directory
- Prompt: "What should this feature be called? (used as folder name, e.g., 'analytics-dashboard')"
- Validate: lowercase, hyphens and underscores allowed, no spaces or special characters
- Create $1/features/ directory if it doesn't exist
- Create $1/features/<feature-name>/ directory
- Store the feature path as FEATURE_PATH = $1/features/<feature-name>
-
Copy skills to target (with global resolution check)
Before copying each skill, check if it's globally available. See GLOBAL_SYNC.md for helper definitions.
Pre-copy checks:
# Source the global sync helpers GLOBAL_SKILLS_DIR="$HOME/.claude/skills" TOOLKIT_ROOT="$(pwd)" # Check if global directory exists and has symlinks GLOBAL_AVAILABLE=false if [[ -d "$GLOBAL_SKILLS_DIR" ]]; then # Count symlinks pointing to this toolkit SYMLINK_COUNT=$(find "$GLOBAL_SKILLS_DIR" -maxdepth 1 -type l 2>/dev/null | wc -l) if [[ "$SYMLINK_COUNT" -gt 0 ]]; then GLOBAL_AVAILABLE=true fi fiCopy logic with global resolution:
GLOBAL_COUNT=0 LOCAL_COUNT=0 for skill_dir in .claude/skills/*/; do skill_name="$(basename "$skill_dir")" # Check for toolkit-only flag in YAML frontmatter (between --- markers) if sed -n '/^---$/,/^---$/p' "$skill_dir/SKILL.md" 2>/dev/null | grep -q '^toolkit-only: true'; then continue # Skip toolkit-only skills fi # Check if this skill is globally usable if [[ "$GLOBAL_AVAILABLE" == "true" ]]; then global_path="$GLOBAL_SKILLS_DIR/$skill_name" if [[ -L "$global_path" && -e "$global_path" ]]; then # Verify it points to this toolkit resolved=$(realpath "$global_path" 2>/dev/null) expected=$(realpath "$skill_dir" 2>/dev/null) if [[ "$resolved" == "$expected" ]]; then echo " $skill_name — globally available" ((GLOBAL_COUNT++)) continue # Skip copy, will resolve via global fi fi fi # Copy locally cp -r "$skill_dir" "$1/.claude/skills/" echo " $skill_name — copied locally" ((LOCAL_COUNT++)) doneSummary output:
- If all skills are global:
"All skills resolved via ~/.claude/skills/ — no local copies needed" - If mixed:
"Skills: {GLOBAL_COUNT} global, {LOCAL_COUNT} local" - If all local:
"Copied {LOCAL_COUNT} skills to project"
Copy verification config (if missing):
.claude/verification-config.json→ target's.claude/verification-config.json
Verify result:
# For local-only or mixed: verify local copies exist if [[ "$LOCAL_COUNT" -gt 0 ]]; then actual_count=$(ls -d "$1/.claude/skills/"*/ 2>/dev/null | wc -l) if [[ "$actual_count" -eq 0 ]]; then # STOP and report copy failure fi fiAlso verify configuration file:
test -f "$1/.claude/verification-config.json" && echo "Config: OK" || echo "Config: MISSING (non-critical)"Verify skill copy results: After the copy loop completes, run
ls "$1/.claude/skills/"and confirm the expected skill directories are present. If any expected local copies are missing, STOP and report the failure before continuing. - If all skills are global:
3b. Copy workstream scripts to target
Copy .workstream/ scripts from the toolkit to the target project:
mkdir -p "$1/.workstream"
for file in lib.sh setup.sh dev.sh verify.sh README.md workstream.json.example; do
if [ -f ".workstream/$file" ]; then
cp ".workstream/$file" "$1/.workstream/$file"
fi
done
chmod +x "$1/.workstream/"*.sh 2>/dev/null || true
Do NOT copy workstream.json — this is project-owned and created by the user.
Verify copies:
ls -la "$1/.workstream/" 2>/dev/null
Confirm setup.sh, dev.sh, verify.sh, and lib.sh exist and are executable.
Verify with ls -la that permissions include +x on all .sh files. If any script is missing or not executable, report the discrepancy.
3c. Copy Codex App templates to target
Copy .codex/ templates from the toolkit to the target project:
mkdir -p "$1/.codex"
cp ".codex/setup.sh" "$1/.codex/setup.sh"
cp ".codex/AGENTS.md" "$1/.codex/AGENTS.md"
chmod +x "$1/.codex/setup.sh"
These are recommended defaults for Codex App integration. Users configure the setup script in Codex App Settings (Cmd+,) → Local Environments.
Verify Codex App copies:
- Verify with
ls -la "$1/.codex/setup.sh"that the file exists and is executable. - Verify with
ls "$1/.codex/AGENTS.md"that the file was copied.
3a. Incremental Sync (When SETUP_MODE=incremental)
Skip Step 3 entirely and use this incremental approach instead.
Check resolution mode from existing config:
FORCE_LOCAL=$(jq -r '.force_local_skills // empty' "$1/.claude/toolkit-version.json")
CURRENT_RESOLUTION=$(jq -r '.skill_resolution // "local"' "$1/.claude/toolkit-version.json")
Important: For existing projects with local copies, continue syncing locally to preserve shadowing behavior. Do NOT automatically switch to global resolution.
Load the stored file hashes from $1/.claude/toolkit-version.json:
STORED_HASHES=$(jq '.files' "$1/.claude/toolkit-version.json")
For each skill in the copy list (excluding toolkit-only skills — check SKILL.md frontmatter for toolkit-only: true):
-
Calculate toolkit file hash:
TOOLKIT_HASH=$(shasum -a 256 "$TOOLKIT_FILE" | cut -d' ' -f1) -
Get stored hash from toolkit-version.json (hash at last sync)
-
Calculate target file hash (if exists):
TARGET_HASH=$(shasum -a 256 "$TARGET_FILE" | cut -d' ' -f1)
Classification and Action:
| Condition | Classification | Action |
|---|---|---|
| Already using global resolution | GLOBAL_USABLE | Skip (resolves via global) |
| Target doesn't exist | NEW | Copy from toolkit |
| Target hash = Toolkit hash | CURRENT | Skip (already up to date) |
| Target hash = Stored hash | CLEAN_UPDATE | Copy from toolkit (no local changes) |
| Target hash ≠ Stored hash | LOCAL_MODIFIED | Skip with warning |
Track counts for each classification and report summary:
INCREMENTAL SYNC
================
Global resolution: {count} skills (via ~/.claude/skills)
New files: {count} copied
Updated files: {count} copied
Current files: {count} skipped (already up to date)
Modified files: {count} skipped (local changes preserved)
If any files are LOCAL_MODIFIED, list them:
WARNING: These files have local modifications and were NOT updated:
- .claude/skills/phase-start/SKILL.md
- .claude/skills/fresh-start/SKILL.md
To update these files, either:
- Run /sync for interactive conflict resolution
- Manually backup and delete them, then re-run /setup
-
Create or Update toolkit-version.json
For full setup (SETUP_MODE=full):
Create
.claude/toolkit-version.jsonin the target to enable future syncs. Determine the resolution mode based on how skills were installed:{ "schema_version": "1.1", "toolkit_location": "{absolute path to this toolkit}", "toolkit_commit": "{current git HEAD commit hash}", "toolkit_commit_date": "{commit date in ISO format}", "last_sync": "{current ISO timestamp}", "force_local_skills": null, "skill_resolution": "{global|local|mixed}", "files": { ".claude/skills/fresh-start/SKILL.md": { "hash": "{sha256 hash of file}", "synced_at": "{ISO timestamp}", "resolution": "{global|local}" } // ... entry for each skill } }Resolution determination:
- If
GLOBAL_COUNT > 0andLOCAL_COUNT == 0:"skill_resolution": "global" - If
GLOBAL_COUNT == 0andLOCAL_COUNT > 0:"skill_resolution": "local" - If both > 0:
"skill_resolution": "mixed"
Per-file resolution:
- Skills that were skipped (globally available):
"resolution": "global" - Skills that were copied:
"resolution": "local"
For incremental update (SETUP_MODE=incremental):
Update the existing
toolkit-version.json:- Update
toolkit_committo current HEAD - Update
toolkit_commit_dateto current commit date - Update
last_syncto current timestamp - Preserve
force_local_skillssetting - For each file that was copied (NEW or CLEAN_UPDATE):
- Update the file's
hash,synced_at, andresolution
- Update the file's
- Keep existing entries for files that were skipped (CURRENT or LOCAL_MODIFIED)
- Recalculate
skill_resolutionbased on all files
For already current (SETUP_MODE=current):
Skip this step entirely.
Get toolkit info:
TOOLKIT_PATH=$(pwd) COMMIT_HASH=$(git rev-parse HEAD) COMMIT_DATE=$(git log -1 --format=%cI HEAD)Calculate file hashes:
shasum -a 256 "$file" | cut -d' ' -f1Include entries for ALL files in non-toolkit-only skill directories:
# Hash every .md file in every skill directory (skip toolkit-only) for skill_dir in .claude/skills/*/; do # Skip toolkit-only skills (parse YAML frontmatter between --- markers) if sed -n '/^---$/,/^---$/p' "$skill_dir/SKILL.md" 2>/dev/null | grep -q '^toolkit-only: true'; then continue fi for file in "$skill_dir"*.md; do [[ -f "$file" ]] || continue hash=$(shasum -a 256 "$file" | cut -d' ' -f1) # Add entry for "$file" with hash and timestamp done doneThis ensures skills with supporting files (e.g.,
audit-skills/CRITERIA.md,audit-skills/SCORING.md) are tracked for conflict detection.Skills with
toolkit-only: truein frontmatter are NOT copied or tracked. These run only from the toolkit directory (e.g., setup, update-target-projects).Verify toolkit-version.json: Read back the file with
cat "$1/.claude/toolkit-version.json" | python3 -m json.tool(orjq .) to confirm it contains valid JSON and thetoolkit_commitfield matches the expected value. - If
-
Create CLAUDE.md if it doesn't exist
Create a minimal CLAUDE.md that references AGENTS.md:
@AGENTS.mdVerify CLAUDE.md: Read back
$1/CLAUDE.mdto confirm it was written correctly and contains the@AGENTS.mdreference. -
Codex CLI Detection (Optional)
Check if OpenAI Codex CLI is installed:
command -v codex >/dev/null 2>&1If Codex is detected:
- Use AskUserQuestion to prompt:
Question: "Codex CLI detected. Install toolkit skills for Codex?" Options: - "Yes, install" — Install skills via symlink (auto-updates with toolkit) - "No, skip" — Don't install Codex skills
If user selects "Yes, install":
- Run from this toolkit directory:
./scripts/install-codex-skill-pack.sh --method symlink - Verify with
ls -la ~/.codex/skills/that symlinks were created successfully. - Report the installation result
If Codex is not detected:
- Skip silently (don't mention Codex to users who don't have it)
Note: Using symlinks means Codex skills auto-update when user runs
git pullon the toolkit. - Use AskUserQuestion to prompt:
6a. Codex MCP Configuration (if Codex detected and skills installed)
After installing Codex skills, offer to configure essential MCPs:
- Use AskUserQuestion to prompt:
Question: "Configure essential MCP servers for Codex? (Playwright for browser verification)" Options: - "Yes, configure" — Add Playwright MCP to ~/.codex/config.toml - "No, skip" — Skip MCP configuration
If user selects "Yes, configure":
- Run from this toolkit directory:
./scripts/configure-codex-mcp.sh - Verify with
cat ~/.codex/config.tomlthat the MCP configuration was written correctly. - Report the configuration result
Why this matters: Both Claude Code and Codex CLI support the same MCP protocol. This ensures Codex has access to browser automation for verification workflows, matching Claude Code's capabilities when using the Playwright MCP.
-
Report success and next steps
For SETUP_MODE=current (already up to date):
ALREADY UP TO DATE ================== Target: $1 Toolkit commit: {COMMIT_HASH} ({COMMIT_DATE}) No changes needed — toolkit files are current.For SETUP_MODE=incremental (updated existing):
TOOLKIT UPDATED =============== Target: $1 Previous commit: {OLD_COMMIT_HASH} Current commit: {COMMIT_HASH} {Summary from Step 3a showing files synced/skipped} All toolkit skills are now up to date.For SETUP_MODE=full, Greenfield:
TOOLKIT INITIALIZED =================== Target: $1 Skill resolution: {mode} ({details}) Next steps (run from your project directory): 1. cd $1 2. /product-spec 3. /technical-spec 4. /generate-plan 5. /fresh-start 6. /configure-verification 7. /phase-prep 1 8. /phase-start 1Skill resolution line examples:
Skill resolution: global (30 skills via ~/.claude/skills symlinks)Skill resolution: local (30 skills copied to project)Skill resolution: mixed (25 global, 5 local)
For SETUP_MODE=full, Feature:
TOOLKIT INITIALIZED =================== Target: $1 Feature directory: FEATURE_PATH Next steps (run from your project directory): 1. cd $1 2. /feature-spec <feature-name> 3. /feature-technical-spec <feature-name> 4. /feature-plan <feature-name> 5. /fresh-start 6. /configure-verification 7. /phase-prep 1 8. /phase-start 1 After phase completion, merge AGENTS_ADDITIONS.md into $1/AGENTS.md
Important
- This skill must be run from the ai_coding_project_base toolkit directory
- All other skills (
/product-spec,/technical-spec,/generate-plan,/feature-spec,/feature-technical-spec,/feature-plan, and execution skills) run from the target project directory - Only
/setupand/update-target-projectsrun from the toolkit - Use
cp -rfor directory copies to preserve structure - Do not overwrite existing files without asking
Error Handling
| Situation | Action |
|---|---|
Target directory does not exist and mkdir -p fails | Report permission error, suggest creating manually, exit without partial state |
cp -r fails when copying skills to target | STOP immediately, report which skills failed to copy, do not write toolkit-version.json |
toolkit-version.json write fails or produces invalid JSON | Complete file copies (primary goal), warn that incremental syncs will not work, suggest checking .claude/ directory permissions |
| Codex CLI skill installation fails | Do NOT fail the entire setup; report the error and continue with remaining steps |
Global symlink check fails (broken symlinks in ~/.claude/skills/) | Fall back to local copy for affected skills, report which symlinks are broken |
When Setup Cannot Complete
If LOCAL_MODIFIED files conflict during incremental sync:
- List all conflicting files with their local vs toolkit versions
- Ask user: "Keep local changes, overwrite with toolkit, or diff each file?"
- If "Keep local": Skip those files, complete rest of sync, warn about version mismatch
- If "Overwrite": Back up local files to
.claude/backup/before overwriting - If "Diff each": Show side-by-side diff, let user choose per file
If target directory doesn't exist and can't be created:
- Report: "Cannot create directory: {path}"
- Check parent directory permissions
- Suggest: Create manually with
mkdir -p {path} - Exit cleanly without partial state
If Codex CLI skill installation fails:
- Do NOT fail the entire setup
- Report: "Codex skill installation failed: {error}"
- Continue with rest of setup
- Note at end: "Codex skills not installed. Run
./scripts/install-codex-skill-pack.shmanually."
If toolkit-version.json cannot be written:
- Report: "Cannot write toolkit-version.json"
- Complete the file copies (primary goal)
- Warn: "Future incremental syncs will not work until version file is created"
- Suggest: Check .claude/ directory permissions