You add projd infrastructure to an existing, working project. You copy skills, hooks, and scripts from the template, merge configuration files non-destructively, and leave the project ready for /projd-plan.
BOILERPLATE_REMOTE_URL: {{BOILERPLATE_REMOTE_URL}} BOILERPLATE_LOCAL_PATH: {{BOILERPLATE_LOCAL_PATH}}
Arguments
$ARGUMENTS
Instructions
Pre-flight: gather context and check for updates
Run these commands to gather context before proceeding:
bash "$HOME/.claude/skills/.projd-updater.sh"-- check for skill updatespwd-- confirm current directorygh auth status-- check GitHub CLI authenticationls -la CLAUDE.md .projd/agent.json lefthook.yml .claude/settings.json-- check for existing filesls -d .projd .projd/progress .projd/scripts .claude/hooks .claude/skills-- check for existing projd directories
If the updater output contains PROJD_UPDATED, stop immediately and tell the user:
Skills were updated to the latest version. Please re-run
/projd-adopt.
Do not proceed with any other steps.
0. Placeholder guard
Check the BOILERPLATE_REMOTE_URL value above. If it still contains {{ (the placeholder was not replaced by the install script), stop immediately and tell the user:
This skill has not been installed properly. Run
./scripts/install-skill.shfrom the projd repo to install it.
Do not proceed.
1. Validate context
Run these checks. Stop on any failure.
- Git repo: Run
git rev-parse --is-inside-work-tree. If not a git repo, stop and suggestgit init. - Not already projd: Check for
.projd/directory. If it exists, stop and tell the user to use./.projd/scripts/upgrade.shinstead. - Not already adopted: Check for
.claude/CLAUDE.md. If it exists and contains## Agent Controls, stop -- projd is already adopted. Also check ifCLAUDE.mdcontains<!-- projd:begin -->(legacy sentinel format) -- if found, stop and suggest running./.projd/scripts/upgrade.shto migrate.
Remember the gh auth status result from the Context section above for later steps.
2. Interview
Step 2a -- Experience level:
Use AskUserQuestion with a single question:
- Experience (header: "Mode"): "How do you want to work?" Options:
Developer -- I make the decisions,Vibes -- Claude picks everything.
Remember the choice for all subsequent steps.
Step 2b -- Developer path (if "Developer" was chosen):
First, auto-detect languages by checking for these files in the project:
| File | Language |
|---|---|
go.mod |
Go |
package.json |
TypeScript |
requirements.txt or pyproject.toml or setup.py |
Python |
Package.swift |
Swift |
build.gradle or build.gradle.kts |
Kotlin |
Cargo.toml |
Rust |
Gemfile |
Ruby |
Then use a single AskUserQuestion call with these questions:
- Language (header: "Language", multiSelect: true): Options:
Go,TypeScript,Python,None -- skip language hooks. Pre-select detected languages by listing them first with "(detected)" in the label. The user picks "Other" to type a different language. - Branch prefix (header: "Prefix"): "Branch prefix for agent work?" Options:
agent/ (Recommended),feature/,claude/. The user picks "Other" to type their own. - Push policy (header: "Push"): "Push policy?" Options:
Feature branches only (Recommended),All branches,No pushing -- local only. - Mode (header: "Mode"): "How should projd files be managed?" Options:
Team -- committed to git (Recommended),Solo -- gitignored, only you see them.
Step 2c -- Vibes path (if "Vibes" was chosen):
Auto-detect language from project files (same detection as 2b). Use defaults:
- Branch prefix:
agent/ - Push policy:
feature(ifghis authenticated),false(if not) - Auto-review:
true(ifghis authenticated),false(if not) - Mode:
solo
Show a one-line summary of choices and ask the user to confirm before proceeding.
3. Clone template to temp dir
Try the remote URL first. If it fails, fall back to the local path:
TEMP_DIR=$(mktemp -d)
git clone --depth 1 <BOILERPLATE_REMOTE_URL> "$TEMP_DIR" 2>/dev/null
If the remote clone fails, try the local fallback (if BOILERPLATE_LOCAL_PATH is set and not the placeholder):
git clone <BOILERPLATE_LOCAL_PATH> "$TEMP_DIR"
If both fail, report and stop.
4. Check for file conflicts
These are the template-managed files that will be copied:
.claude/CLAUDE.md
.claude/hooks/check-git-policy.sh
.claude/hooks/check-path-guard.sh
.claude/skills/projd-start/SKILL.md
.claude/skills/projd-end/SKILL.md
.claude/skills/projd-plan/SKILL.md
.claude/skills/projd-hands-on/SKILL.md
.claude/skills/projd-hands-off/SKILL.md
.projd/scripts/init.sh
.projd/scripts/monitor.sh
.projd/scripts/skill-context.sh
.projd/scripts/smoke.sh
.projd/scripts/status.sh
.projd/scripts/statusline.sh
.projd/scripts/validate.sh
.projd/scripts/upgrade.sh
.projd/scripts/activate-langs.sh
.projd/agent.json
lefthook.yml
For each file, check if it already exists in the project. If any conflicts are found, list them and use AskUserQuestion:
- Conflicts (header: "Conflicts"): "These files already exist: . How to proceed?" Options:
Back up to *.pre-projd and overwrite,Skip conflicting files,Abort.
If "Abort", clean up the temp dir and stop.
If no conflicts, skip the question and proceed.
5. Copy infrastructure files
For each template file listed in step 4:
- Create parent directories as needed (
mkdir -p) - If the file conflicts and the user chose "Back up", rename the existing file to
<filename>.pre-projd - If the file conflicts and the user chose "Skip", skip it
- Otherwise, copy the file from the temp clone
After copying, set executable permissions:
chmod +x .projd/scripts/*.sh .claude/hooks/*.sh
6. Activate language blocks
If the user selected languages that have built-in template support (typescript, go, python, swift, kotlin), run the activation script on each file that has language blocks:
./.projd/scripts/activate-langs.sh .projd/scripts/smoke.sh <lang1> <lang2> ...
./.projd/scripts/activate-langs.sh .projd/scripts/init.sh <lang1> <lang2> ...
./.projd/scripts/activate-langs.sh lefthook.yml <lang1> <lang2> ...
If any selected languages do NOT have built-in template blocks (not in: typescript, go, python, swift, kotlin), manually add equivalent content following the same approach as projd-create step 6b:
lefthook.yml -- add a pre-commit command block under pre-commit.commands:
<tool-name>:
glob: "**/*.<ext>"
run: <lint/format command> {staged_files}
.projd/scripts/smoke.sh -- add run_check lines after # --- Local checks ---:
run_check "<name>" <command>
.projd/scripts/init.sh -- add dependency install lines after # --- Dependencies ---:
if [ -f <manifest-file> ]; then
<install command>
echo "[ok] <Language> dependencies installed"
fi
If the user chose "None -- skip language hooks", skip this entire step.
7. Merge Claude Code settings
Determine the target settings file based on the mode chosen in step 2:
- Team mode:
.claude/settings.json - Solo mode:
.claude/settings.local.json
Read the target file if it exists. If it does not exist, start with an empty {}.
Base mode (Developer):
Merge these entries:
Add to
permissions.allow(deduplicate -- do not add entries that already exist):"Bash(./.projd/scripts/skill-context.sh:*)", "Bash(git *)"Set
statusLine(if the key does not already exist):"statusLine": { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.projd/scripts/statusline.sh" }If a
statusLinealready exists, use AskUserQuestion to ask:- StatusLine (header: "StatusLine"): "A status line is already configured. Replace with projd's?" Options:
Yes -- use projd status line,No -- keep existing.
- StatusLine (header: "StatusLine"): "A status line is already configured. Replace with projd's?" Options:
Add to
hooks.PreToolUse(only if no existing hook already referencescheck-git-policy.sh):{ "matcher": "Bash", "hooks": [ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-git-policy.sh", "timeout": 10 } ] }
Vibes mode:
Replace permissions.allow with the expanded list:
[
"Bash(./.projd/scripts/*)",
"Bash(git *)",
"Bash(grep *)",
"Bash(rg *)",
"Bash(find *)",
"Bash(ls *)",
"Bash(cat *)",
"Bash(head *)",
"Bash(tail *)",
"Bash(wc *)",
"Bash(sort *)",
"Bash(mkdir *)",
"Bash(cp *)",
"Bash(mv *)",
"Bash(rm *)",
"Bash(chmod *)",
"Bash(touch *)",
"Bash(which *)",
"Bash(echo *)",
"Bash(printf *)",
"Bash(test *)",
"Bash(diff *)",
"Bash(curl *)",
"Bash(jq *)",
"Bash(gh *)",
"Bash(npm *)",
"Bash(npx *)",
"Bash(node *)",
"Bash(go *)",
"Bash(python *)",
"Bash(python3 *)",
"Bash(pip *)",
"Bash(pip3 *)",
"Bash(cargo *)",
"Bash(make *)",
"Bash(docker *)",
"Edit",
"Read",
"Write",
"Glob",
"Grep",
"WebFetch",
"WebSearch",
"Agent"
]
If the existing file had additional permissions.allow entries not in the list above, preserve them (union).
Set statusLine (same as base mode, with the same conflict handling).
Set hooks.PreToolUse to include both hooks with the path guard:
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-git-policy.sh",
"timeout": 10
},
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-path-guard.sh",
"timeout": 10
}
]
},
{
"matcher": "Read|Write|Edit",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-path-guard.sh",
"timeout": 10
}
]
}
]
}
If existing hooks.PreToolUse entries exist that are NOT projd hooks, preserve them (append projd entries to the array).
Write the merged result back to the target settings file (.claude/settings.json for team mode, .claude/settings.local.json for solo mode).
8. Create .projd/agent.json
Build .projd/agent.json from interview answers:
{
"git": {
"branch_prefix": "<from interview>",
"protected_branches": ["main", "master"],
"allow_push": "<from interview: 'feature' | true | false>",
"allow_force_push": false,
"auto_commit": true
},
"dispatch": {
"max_agents": 20,
"auto_review": <true if vibes with gh auth, false otherwise>
}
}
Map push policy answers:
- "Feature branches only" ->
"feature" - "All branches" ->
true - "No pushing -- local only" ->
false
If .projd/agent.json already exists, read it and warn the user: "A .projd/agent.json already exists. It will be overwritten with your new settings." Then write the new file. The old values are not merged -- the user just configured fresh values in the interview.
9. Write .claude/CLAUDE.md
Copy .claude/CLAUDE.md from the temp clone directory to the project. This file contains the projd workflow instructions (Agent Controls, Session Conventions, etc.) and is auto-loaded by Claude Code alongside the root CLAUDE.md.
cp "$TEMP_DIR/.claude/CLAUDE.md" .claude/CLAUDE.md
Do NOT modify the user's existing root CLAUDE.md. The projd workflow now lives in .claude/CLAUDE.md as a separate file.
Important: Read .claude/CLAUDE.md from the temp clone (not the root CLAUDE.md) to get the canonical projd sections.
10. Create directories, metadata, and mode
mkdir -p .projd/progress
Write the mode:
echo "<mode>" > .projd/mode
If solo mode, append projd entries to .gitignore:
# projd infrastructure (solo mode)
.projd/
.claude/CLAUDE.md
.claude/hooks/
.claude/skills/
lefthook.yml
Generate .projd/manifest with SHA256 checksums of all copied template files:
: > .projd/manifest
for tf in <each template file>; do
if [ -f "$tf" ]; then
cs=$(shasum -a 256 "$tf" | awk '{print $1}')
printf '%s\t%s\n' "$tf" "$cs" >> .projd/manifest
fi
done
Write .projd/source with the BOILERPLATE_REMOTE_URL.
11. Bootstrap and validate
Run the initialization script to install Lefthook and set up the development environment:
./.projd/scripts/init.sh
Then run validation (allow it to fail -- warnings about missing features in .projd/progress/ are expected):
./.projd/scripts/validate.sh || true
Report any warnings or failures to the user.
12. Clean up and report
Remove the temp clone directory:
rm -rf "$TEMP_DIR"
Print a summary:
projd infrastructure added.
Installed:
Skills: projd-start, projd-end, projd-plan, projd-hands-on, projd-hands-off
Hooks: check-git-policy.sh [+ check-path-guard.sh if vibes]
Scripts: init, smoke, validate, status, statusline, upgrade, skill-context, monitor, activate-langs
Config: .projd/agent.json, lefthook.yml, settings (merged into <settings file>)
.claude/CLAUDE.md created (projd workflow instructions)
Mode: <team|solo>
Note: New skills won't appear in autocomplete until you start a new conversation.
Next steps:
1. Review the changes: git diff
2. Commit when ready
3. Exit and re-run claude to pick up the new skills
4. Plan features: /projd-plan <your requirements>
If there were skipped files (from conflict resolution), list them and suggest the user merge manually.
Rules
- Run each step sequentially. Do not skip ahead.
- Stop on fatal errors (steps 0, 1, 3). Non-fatal errors (step 11 validate) are reported but do not block.
- Never modify the user's existing source code, tests, or non-configuration files.
- Never create a commit. The user decides when to commit the infrastructure changes.
- Never use emojis in output or generated content.
- When merging settings, preserve all existing entries. Only add, never remove.
- Write
.claude/CLAUDE.mdas a separate file. Do not modify the user's rootCLAUDE.md.