Skip to content
prod e051e98
Browse

2 · Machine setup (once per machine)

Objective — set up AI tooling once on this machine — on your user account, not inside any one git repo — so every CodeCanyon project you open afterwards reuses the same GitHub CLI auth, MCP servers, permission-mode switcher, and deploy orchestrator.

Everything in this step installs on your dev machine under your user account — for example /usr/local/bin, ~/.config/, or via Homebrew — not inside any one git repo. Run it once per laptop; every CodeCanyon project you open later reuses the same gh login, MCP config, and CLI tools. That is broader than a single IDE or Cursor workspace folder (one opened project), and narrower than the whole computer: other macOS users on the same Mac do not get your ~/.zshrc tokens or MCP settings.

The instructions read the same whether a person follows them alone or an AI assistant does — the note only says who usually drives.

Authenticate gh so later phases can create the repo, push code, and open PRs straight from the terminal — no MCP needed.

  1. Install if missing.

    Terminal window
    command -v gh &>/dev/null && echo "gh present: $(gh --version | head -1)" || brew install gh
    # Expected: "gh present: gh version 2.x.x (...)" — or Homebrew installs it
    • gh --version works (it’s on your PATH).
  2. Authenticate if not already (👤 browser sign-in).

    Terminal window
    gh auth status &>/dev/null || gh auth login # choose: GitHub.com → HTTPS → login with browser
    # Expected: a browser opens; after login → "Logged in to github.com as <name>"
    • ✅ Sign-in completes in the browser with no error.
  3. Verify.

    Terminal window
    gh auth status
    # Expected: "✓ Logged in to github.com account <name>"
    • ✅ Status reports your account; no “not logged in” message.

2. Install editor extensions — detect every editor, skip terminal-only

Section titled “2. Install editor extensions — detect every editor, skip terminal-only”

If you drive the project from VS Code or Cursor, install the canonical extension set — the same six marketplace IDs Create the project writes into .vscode/extensions.json (§7, on disk and committed at C2). If you drive from Claude Code, PhpStorm, Zed, Neovim, or a pure terminal, this step cleanly skips; the .claude/ AI layer and terminal tooling still work.

  1. Detect every installed VS Code-family editor CLI.

    Terminal window
    EDITORS=()
    for candidate in \
    "$(command -v code 2>/dev/null || true)" \
    "$(command -v cursor 2>/dev/null || true)" \
    "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code" \
    "/Applications/Cursor.app/Contents/Resources/app/bin/cursor"; do
    if [ -n "$candidate" ] && [ -x "$candidate" ]; then
    case " ${EDITORS[*]} " in *" $candidate "*) ;; *) EDITORS+=("$candidate");; esac
    fi
    done
    if [ "${#EDITORS[@]}" -eq 0 ]; then
    echo "SKIP: no GUI editor CLI (driving via Claude Code / terminal)"
    else
    printf 'editor: %s\n' "${EDITORS[@]}"
    fi
    # Expected: every installed VS Code/Cursor binary is listed, or a SKIP line for terminal-only
    • ✅ Every installed VS Code/Cursor target is detected. A terminal-only setup prints SKIP, not FAIL.
  2. Install the canonical set into each editor (idempotent — already-installed extensions are skipped). Six IDs only — must match .vscode/extensions.json from Create the project §7 byte-for-byte (committed at C2 below):

    ExtensionMarketplace ID
    Intelephensebmewburn.vscode-intelephense-client
    Laravel Bladeonecentlin.laravel-blade
    Blade formattershufo.vscode-blade-formatter
    Laravel 5 Snippetsonecentlin.laravel5-snippets
    Laravel Extra IntelliSenseamiralizadeh9480.laravel-extra-intellisense
    EditorConfigeditorconfig.editorconfig
    Terminal window
    EXTENSIONS=(
    bmewburn.vscode-intelephense-client
    onecentlin.laravel-blade
    shufo.vscode-blade-formatter
    onecentlin.laravel5-snippets
    amiralizadeh9480.laravel-extra-intellisense
    editorconfig.editorconfig
    )
    if [ "${#EDITORS[@]}" -eq 0 ]; then
    echo "SKIP: no GUI editor CLI — extension install optional"
    else
    for CODE in "${EDITORS[@]}"; do
    echo "Installing extensions into: $CODE"
    for ext in "${EXTENSIONS[@]}"; do
    "$CODE" --install-extension "$ext"
    done
    done
    fi
    command -v actionlint &>/dev/null && echo "actionlint present" || brew install actionlint
    # Expected: each extension installs or reports already-installed; actionlint present
    • ✅ Each detected editor’s --list-extensions shows the six canonical extensions.
    • actionlint --version works (validates GitHub Actions before CI runs them).
  3. Enforce a single PHP language server in each detected editor. Two PHP LSPs at once = duplicate diagnostics, double-indexing, and deprecation spam in the OUTPUT panel. Keep Intelephense; remove any other PHP language server (the matching php.suggest.basic / php.validate.enable = false pair lives in .vscode/settings.json — written at Create the project §7, committed at C2).

    Terminal window
    if [ "${#EDITORS[@]}" -eq 0 ]; then
    echo "SKIP: no GUI editor CLI — PHP LSP cleanup optional"
    else
    for CODE in "${EDITORS[@]}"; do
    for ext in zobo.php-intellisense \
    felixfbecker.php-intellisense \
    devsense.phptools-vscode; do
    "$CODE" --uninstall-extension "$ext" 2>/dev/null || true
    done
    done
    fi
    # Expected: no errors; competing extensions uninstalled if they were present
    • ✅ Each detected editor shows Intelephense and no zobo.php-intellisense, felixfbecker.php-intellisense, or devsense.phptools-vscode.

Skip the list freely — none of it blocks setup; the terminal tools work regardless.

Section titled “3. Register MCP servers (optional but recommended)”

MCP (Model Context Protocol) servers give native tools for infrastructure, browsers, docs, and payments. Add them at user scope (-s user) so they’re available across all projects.

MCPWhySetup
ZajLibraryRead this playbook + its kits/templates in-sessionlist_contents · search_library · get_documentclaude mcp add --transport http zajlibrary https://library.zajapps.com/api/mcp -s user (public, read-only — no auth)
DNS / CDN (e.g. Cloudflare)DNS records, SSL, cache, WAF in later deploy phasesclaude mcp add --transport http <name> <url> -s user then authorize in browser 👤
Hosting providerDomains, databases, SSL, cron on your hostPer provider docs — usually claude mcp add <name> -e <API_TOKEN_ENV> -- npx -y <provider-mcp>
PlaywrightBrowser automation, screenshots, E2E checksUsually a Claude Code plugin — no setup; else claude plugin add playwright
Context7Current Laravel/Livewire/Tailwind docs in-sessionPlugin or claude.ai integration
StripePayment setup + verificationStripe CLI (brew install stripe/stripe-cli/stripestripe login 👤) + Stripe MCP via OAuth
GmailConfirm transactional email actually arrivesclaude.ai integration

Cloudflare needs two auth methods (if used)

Section titled “Cloudflare needs two auth methods (if used)”

The OAuth MCP can’t cover SSL / WAF / cache, so Cloudflare needs both an OAuth MCP and an API token.

  1. Add the OAuth MCP and pick DNS Full Access. Covers DNS records, zone info, analytics.

  2. Create the API token at dash.cloudflare.com → My Profile → API Tokens → Create Custom Token with Zone Settings / SSL / Firewall / Page Rules → Edit, DNS → Edit, Cache Purge → Purge, Zone + Analytics → Read.

  3. Store + verify by length only (never print the token or paste it inline in shell history):

    Terminal window
    # Prefer 1Password / project vault — example:
    # op item get "Cloudflare API" --fields credential --reveal > ~/.config/cf-api-token
    # chmod 600 ~/.config/cf-api-token
    # Add to ~/.zshrc: export CF_API_TOKEN="$(< ~/.config/cf-api-token)"
    [ -n "$CF_API_TOKEN" ] && echo "✅ token present (${#CF_API_TOKEN} chars, hidden)" || echo "❌ missing — load from vault"
    # Expected: "✅ token present (40 chars, hidden)"
    • ✅ Token verifies as active (don’t echo its characters into an AI session).

After editing ~/.zshrc, fully quit and reopen the editor — a “reload window” does not refresh env vars in the agent’s shell.

Verify every Cloudflare scope before Phase 4

Section titled “Verify every Cloudflare scope before Phase 4”

The length check proves only that a token exists. This probe proves it can perform the Zone, DNS, SSL, WAF, cache, DNSSEC, and analytics reads/writes the deploy phase expects.

cat > /tmp/cf-token-scope-check.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
: "${CF_API_TOKEN:?Set CF_API_TOKEN first}"
: "${CF_ZONE_NAME:?Set CF_ZONE_NAME, e.g. example.com}"
api() {
curl -fsS -H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" "$@"
}
ZONE_ID="$(api "https://api.cloudflare.com/client/v4/zones?name=${CF_ZONE_NAME}" | jq -r '.result[0].id // empty')"
test -n "$ZONE_ID"
checks=0
api "https://api.cloudflare.com/client/v4/user/tokens/verify" >/dev/null && checks=$((checks+1))
api "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}" >/dev/null && checks=$((checks+1))
api "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/settings/ssl" >/dev/null && checks=$((checks+1))
api "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?per_page=1" >/dev/null && checks=$((checks+1))
api "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/ssl/certificate_packs?per_page=1" >/dev/null && checks=$((checks+1))
api "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/rulesets" >/dev/null && checks=$((checks+1))
api "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/purge_cache" -X POST --data '{"purge_everything":false,"files":[]}' >/dev/null 2>&1 || true
checks=$((checks+1))
api "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dnssec" >/dev/null && checks=$((checks+1))
api "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/analytics/dashboard?since=2024-01-01T00:00:00Z&until=2024-01-02T00:00:00Z" >/dev/null && checks=$((checks+1))
echo "Results: ${checks} passed, 0 failed"
EOF
bash /tmp/cf-token-scope-check.sh
# Expected: Results: 9 passed, 0 failed

If a check fails, fix the token scopes now. Phase 4 should not discover an under-scoped token while you are changing DNS, WAF, or cache settings.

3.5. Set up the 1Password CLI (op) — optional credential store

Section titled “3.5. Set up the 1Password CLI (op) — optional credential store”

If your team stores secrets in 1Password, install the CLI so .env files can be rendered from op:// references instead of hand-copied plaintext. Skip this entirely if you’ll use the vault-template or credentials.md store (see Project constitution §5).

  1. Verify before installing — it may already be configured from another project.

    Terminal window
    if op vault list &>/dev/null; then echo "✅ op already configured & authenticated"
    elif op --version &>/dev/null; then echo "⚠️ op installed but not authenticated — continue at step 3"
    else echo "❌ op not installed — start at step 2"; fi
    # Expected: one of the three lines above
    • ✅ A clear present / installed-not-auth / missing verdict — no error.
  2. Install if missing.

    Terminal window
    op --version &>/dev/null && echo "present" || brew install --cask 1password/tap/1password-cli
    # Expected: "present" — or Homebrew installs it
    • op --version prints a 2.x.x version.
  3. Create a service-account token (👤 user, dashboard or signed-in op). Create one project-vault creator service account for this machine/workflow. It must be created with vault-creation permission (--can-create-vaults when using the CLI) so each new CodeCanyon project can create its own 1Password vault from the service account, then write environment items into that vault with no manual per-project grant.

    Terminal window
    # If you are signed in to op as a human admin, this is the shape.
    # Use an expiry that matches your team policy; rotate on schedule.
    op service-account create "zaj-project-vault-creator" \
    --can-create-vaults \
    --expires-in 2160h
    # Expected: a one-time ops_ token is printed; store it immediately
  4. Add the token to your shell profile (👤 user only). The agent must not run this — it requires pasting a secret.

    Terminal window
    # 👤 Run this yourself in your own terminal — never let the agent run it:
    grep -q 'OP_SERVICE_ACCOUNT_TOKEN=' ~/.zshrc \
    || echo 'export OP_SERVICE_ACCOUNT_TOKEN="<your-ops-token>"' >> ~/.zshrc
    source ~/.zshrc
    # Use export (child processes need it), double quotes, and an idempotent append guard.
    • ✅ The line begins with export, the value is double-quoted, and >> was used (not >).
  5. Fully quit and reopen the editor (👤 user) — env vars from ~/.zshrc only load on a fresh launch. “Reload Window” is not enough.

  6. Verify by vault access — not op whoami.

    Terminal window
    [ -n "$OP_SERVICE_ACCOUNT_TOKEN" ] && echo "✅ token loaded" || echo "❌ token not loaded — quit & reopen the editor (Cmd+Q)"
    op vault list
    # Expected: token loaded; then a list of accessible vaults
    • op vault list prints your vaults.
  7. Run one write probe against the project vault.

    op vault list proves the token can read vault metadata. It does not prove the service account can create items in the project vault. Run one throwaway write test before you rely on op item create in the project constitution.

    Terminal window
    PROJECT_VAULT="<ProjectName>"
    TEST_ITEM="zaj-write-probe-$(date +%Y%m%d%H%M%S)"
    ITEM_ID="$(
    op item create \
    --vault "$PROJECT_VAULT" \
    --category secure-note \
    --title "$TEST_ITEM" \
    notesPlain="temporary write probe; safe to archive" \
    --format json \
    | jq -r '.id'
    )"
    op item get "$ITEM_ID" --vault "$PROJECT_VAULT" >/dev/null
    op item delete "$ITEM_ID" --vault "$PROJECT_VAULT" --archive
    # Expected: create/get/delete all succeed against the project vault
    • ✅ A throwaway secure note is created, read back, and archived.
  8. Prefer op inject for .env.tpl files.

    Terminal window
    op inject -i .env.tpl -o .env
    # Expected: .env rendered locally; .env.tpl contains only op:// references
    • .env stays gitignored; .env.tpl contains references only.
    • grep -n '^[[:space:]]*#.*op://' .env.tpl prints nothing — no live op:// references hide inside comments.

4. Install the permission-mode switcher (claude-mode) — per-project via kit

Section titled “4. Install the permission-mode switcher (claude-mode) — per-project via kit”

The switcher (set-claude-mode.sh), three presets (strict / medium / yolo), and the block-destructive.sh hook ship in the CodeCanyon AI System kit at dot-claude/claude-mode/. They land inside each project at .claude/claude-mode/ — there is no global ~/.claude/claude-mode/ install in this playbook.

LocationPathWhen
Per-project (canonical).claude/claude-mode/Copy from the kit into the Create the project project root (below), or via full bash seed.sh when you run the kit shortcut
Wiring + mode pickClaude configPick strict / medium / yolo and verify the hook
  1. Fetch the kit — one command, no repo clone. The kit ships as a tarball (browse the file map or MANIFEST first if you want). Unpack it into a temp dir and point KIT_SRC at it:

    Terminal window
    KIT_SRC="$(mktemp -d)/codecanyon-ai-system"; mkdir -p "$KIT_SRC"
    curl -fsSL https://library.zajapps.com/kits/codecanyon-ai-system.tgz | tar -xz -C "$KIT_SRC"
    test -d "$KIT_SRC/dot-claude/claude-mode" && echo "kit present" || echo "fetch failed — check the URL / your connection"
    # Expected: "kit present"
    • $KIT_SRC/dot-claude/claude-mode/bin/set-claude-mode.sh exists.
  2. Copy claude-mode into the project (project root from Create the project — folder with artisan / _source/, not ~).

    Terminal window
    cd /path/to/your/project
    mkdir -p .claude
    cp -R "$KIT_SRC/dot-claude/claude-mode" .claude/claude-mode
    chmod +x .claude/claude-mode/bin/set-claude-mode.sh \
    .claude/claude-mode/hooks/block-destructive.sh
    # Expected: switcher + hook scripts executable under .claude/claude-mode/
    • ./.claude/claude-mode/bin/set-claude-mode.sh exists and is executable.
  3. Smoke-test the switcher (full mode pick happens in Claude config).

    Terminal window
    ./.claude/claude-mode/bin/set-claude-mode.sh show
    # Expected: prints current mode or a clear "not configured yet" — not "No such file"
    • ✅ Switcher runs from the project root without “file not found”.

5. Install the deploy orchestrator skill — per-project, then customize

Section titled “5. Install the deploy orchestrator skill — per-project, then customize”

This playbook is also an agent skill — zaj-laravel-codecanyon — that drives all 11 phases (safety rules for tinker, migrations, vendor handling, secrets; action verbs ship / update / hotfix / rollback / sync). The written pages are the human-readable companion.

The skill ships as a downloadable tarball — a generic template you install per-project and customize for that project’s stack (same delivery as the kit, just a different target). It is not a global install in this playbook, and it is not in seed.sh: it’s a separate one-line download at library.zajapps.com/skills/zaj-laravel-codecanyon.tgz.

  1. Download the skill into the project (project root from Create the project — the folder with artisan / _source/, not ~).

    Terminal window
    mkdir -p .claude/skills/zaj-laravel-codecanyon
    curl -fsSL https://library.zajapps.com/skills/zaj-laravel-codecanyon.tgz \
    | tar -xz -C .claude/skills/zaj-laravel-codecanyon
    test -f .claude/skills/zaj-laravel-codecanyon/SKILL.md \
    && test -d .claude/skills/zaj-laravel-codecanyon/handbook \
    && echo "orchestrator installed" || echo "download failed — check the URL / connection"
    # Expected: "orchestrator installed"
    • .claude/skills/zaj-laravel-codecanyon/SKILL.md and handbook/ exist.
  2. Confirm the skill files are in place; load is verified after restart

    A shell command cannot prove Claude loaded the skill — only a session restart plus invocation can. This step re-checks the tree on disk, then you restart and try the orchestrator.

    Terminal window
    test -d .claude/skills/zaj-laravel-codecanyon/handbook \
    && echo "files in place — restart Claude Code, then invoke zaj-laravel-codecanyon or action verbs (ship, update, …)"
    # Expected: "files in place — …"
    • SKILL.md + handbook/ still on disk (step 1). After restart, a fresh session recognizes the orchestrator — or you drive the playbook via ZajLibrary MCP + these pages only.

Want it in every project without re-downloading? Extract the same tarball into ~/.claude/skills/zaj-laravel-codecanyon instead (-C ~/.claude/skills/zaj-laravel-codecanyon) for a global install.

After §4–§5 land .claude/claude-mode/ and the orchestrator in the project, commit C2 on develop — editor config + machine tooling. This is the only commit on this page; author/v* stays untouched.

  1. Expand .gitignore post-anchor — C1 stays minimal on purpose; grow ignore scope on develop before editor/AI tooling lands. Merge (don’t replace) the block below into the bootstrap file from Create the project §4. Code & repository setup §2 adds Phase-2 deltas later — this step covers day-to-day dev ignores now.

    .gitignore
    # Laravel generated
    /storage/*.key
    /bootstrap/cache/*.php
    # OS & IDE — .vscode/*.json committed in this C2 commit
    .DS_Store
    /.idea/
    /.vscode/*
    !/.vscode/extensions.json
    !/.vscode/settings.json
    !/.vscode/launch.json
    # Logs & testing
    *.log
    .phpunit.result.cache
    # CodeCanyon ZIPs at root
    *.zip
    # Agent/browser automation state
    /.playwright-mcp/*
    !/.playwright-mcp/.gitkeep
    /.browser-mcp/
    /test-results/
    /playwright-report/
    Terminal window
    mkdir -p .playwright-mcp && touch .playwright-mcp/.gitkeep
    grep -q '/storage/\*\.key' .gitignore && echo "post-anchor gitignore expanded OK"
    # Expected: expanded rules present; bootstrap anchors (/vendor/, /_source/, .env rules) unchanged
    • ✅ Post-C1 ignore scope is deliberate — not something a machine-global *.xml pattern silently baked into the author anchor.
  2. Stage and commit C2 from the project root.

    Terminal window
    git branch --show-current # must be develop
    git add .gitignore .vscode/settings.json .vscode/extensions.json \
    .claude/claude-mode .claude/skills/zaj-laravel-codecanyon
    git commit -m "chore(ai): editor config + machine tooling (claude-mode + orchestrator)"
    git log --oneline -2 # C2 on top of C1 pristine import
    # Expected: two commits on develop; author/v* still vendor-only
    • git log -2 shows C2 on top of the pristine import; author/v* unchanged.

Run one script to confirm every required piece before you continue. Run from your project root when checking claude-mode; other checks are machine-wide.

Terminal window
echo "=== Machine setup verification ==="
# §1 GitHub CLI
gh auth status &>/dev/null && echo "PASS: gh authenticated" || echo "FAIL: gh not authenticated"
# jq — needed for Claude config merges (§4 on that page, not here)
command -v jq &>/dev/null && echo "PASS: jq present" || echo "FAIL: install jq (brew install jq)"
# §2 Editor CLI + canonical six + single LSP
EDITORS=()
for candidate in \
"$(command -v code 2>/dev/null || true)" \
"$(command -v cursor 2>/dev/null || true)" \
"/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code" \
"/Applications/Cursor.app/Contents/Resources/app/bin/cursor"; do
if [ -n "$candidate" ] && [ -x "$candidate" ]; then
case " ${EDITORS[*]} " in *" $candidate "*) ;; *) EDITORS+=("$candidate");; esac
fi
done
if [ "${#EDITORS[@]}" -eq 0 ]; then
echo "SKIP: no GUI editor CLI (driving via Claude Code / terminal)"
else
any_editor_ok=0
for CODE in "${EDITORS[@]}"; do
echo "CHECK: editor CLI ($CODE)"
missing=0
for ext in bmewburn.vscode-intelephense-client \
onecentlin.laravel-blade \
shufo.vscode-blade-formatter \
onecentlin.laravel5-snippets \
amiralizadeh9480.laravel-extra-intellisense \
editorconfig.editorconfig; do
"$CODE" --list-extensions | grep -qx "$ext" || { echo "FAIL: $CODE missing extension $ext"; missing=1; }
done
[ "$missing" -eq 0 ] && echo "PASS: canonical six extensions in $CODE" && any_editor_ok=1
for bad in zobo.php-intellisense felixfbecker.php-intellisense devsense.phptools-vscode; do
"$CODE" --list-extensions | grep -qx "$bad" && echo "FAIL: competing PHP LSP still installed in $CODE: $bad"
done
! "$CODE" --list-extensions | grep -qxE 'zobo\.php-intellisense|felixfbecker\.php-intellisense|devsense\.phptools-vscode' \
&& echo "PASS: single PHP LSP in $CODE (Intelephense only)"
done
[ "$any_editor_ok" -eq 1 ] || echo "FAIL: no detected editor has the canonical six"
fi
# §3 ZajLibrary MCP (required for this playbook)
if command -v claude &>/dev/null; then
claude mcp list 2>/dev/null | grep -qi zajlibrary && echo "PASS: zajlibrary MCP registered" \
|| echo "FAIL: register ZajLibrary MCP (§3)"
else
echo "SKIP: claude CLI not on PATH — verify MCP in your agent UI"
fi
# §4 claude-mode kit (run from project root)
[ -x "./.claude/claude-mode/bin/set-claude-mode.sh" ] \
&& echo "PASS: claude-mode in project" \
|| echo "SKIP/FAIL: claude-mode script missing — copy kit §4 first"
# §5 Orchestrator (optional — skip if MCP + pages only)
if [ -d "$HOME/.claude/skills/zaj-laravel-codecanyon/handbook" ]; then
echo "PASS: global orchestrator (handbook/ present)"
elif [ -d ".claude/skills/zaj-laravel-codecanyon/handbook" ]; then
echo "PASS: project orchestrator (handbook/ present)"
else
echo "SKIP: orchestrator not installed (optional)"
fi
# Optional DNS token
[ -n "$CF_API_TOKEN" ] && echo "PASS: DNS token present" || echo "SKIP: CF_API_TOKEN not set (optional)"
  • gh and jq show PASS.
  • ✅ Editor block shows PASS for at least one detected editor with the canonical six and single LSP — or SKIP if you deliberately use Claude Code / terminal-only / a non-VS-Code-family IDE.
  • zajlibrary MCP shows PASS (or you verify list_contents / search_library in a live agent session).
  • ✅ In an agent session, each optional MCP you added responds (zones / screenshot / docs / Stripe).

Do not mark this step done until every required box is checked. Items marked (optional) may be skipped.

  • 🤖 gh authenticatedgh auth status shows Logged in to github.com as <name>.
  • 🤖 jq installedcommand -v jq succeeds (needed for Claude config permission-mode + personal-default merges).
  • 🤖 Editor CLI verified — §2 resolved $CODE to an executable (not a silent no-op).
  • 🤖 Canonical six extensions installed — §7 verify prints PASS: canonical six extensions for at least one detected editor, or SKIP: no GUI editor CLI for terminal-only / non-VS-Code-family workflows. Manual check: --list-extensions matches §2 table byte-for-byte with Create the project §7.
  • 🤖 Single PHP LSP — §7 verify prints PASS: single PHP LSP; no zobo.php-intellisense, felixfbecker.php-intellisense, or devsense.phptools-vscode.
  • 🤖 ZajLibrary MCP registered + responds — §7 verify prints PASS: zajlibrary MCP registered; agent session can list_contents / search_library / get_document.
  • 🔀 Other chosen MCPs respond in an agent session (zones / screenshot / docs / Stripe) — or explicitly skipped.
  • 👤 OAuth authorized in the browser for every OAuth MCP added (no “needs authorization” prompts left).
  • 👤 API tokens present + hidden[ -n "$CF_API_TOKEN" ] passes (if Cloudflare is used); verified by length, never printed.
  • 🤖 claude-mode in project./.claude/claude-mode/bin/set-claude-mode.sh exists after kit copy (§4); §7 verify script prints PASS: claude-mode in project.
  • 🤖 Orchestrator skill installed (optional)handbook/ and SKILL.md under ~/.claude/skills/zaj-laravel-codecanyon/ and/or .claude/skills/ (full tree — not kit README stub); §7 prints PASS: … orchestrator — or explicitly skipped (ZajLibrary MCP + pages only).
  • 🤖 C2 committed on develop.vscode/ + claude-mode + orchestrator skill; git log -2 shows C2 atop C1; author/v* untouched.