plugins/coordinator/skills/project-onboarding/SKILL.md
Use when starting in a new project repo, when /update-docs reports tracker_missing, or on first coordinator-plugin run.
npx skillsauth add oduffy-delphi/coordinator-claude project-onboardingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
/update-docs reports tracker_missing — the project lacks coordination infrastructure~/.claude)Before scaffolding, check what already exists. Never overwrite existing files.
Check for each of these and record status (exists / missing / incomplete):
├── CLAUDE.md — project conventions
├── docs/README.md — documentation index (wikis, research, specs, reference)
├── docs/project-tracker.md — workstream tracking
├── docs/wiki/ — wiki guides (LAZY — created by coordinator:distill on first guide extraction)
├── docs/wiki/DIRECTORY_GUIDE.md — guide index with decision record mapping
├── docs/plans/ — implementation plans (LAZY — created when first plan is copied from ~/.claude/plans/)
├── docs/research/ — research outputs (LAZY — created by deep-research:research on first run)
├── tasks/lessons.md — engineering patterns (LAZY — created by coordinator:workstream-complete on first lesson)
├── archive/completed/ — completion archive (LAZY — created by coordinator:workstream-complete on first completion)
├── tasks/handoffs/ — session continuity (LAZY — created by coordinator:handoff on first handoff)
├── CONTEXT.md — domain glossary (LAZY — never scaffold; produced when first term is resolved)
├── DIRECTORY.md — source index
└── .gitignore — check for .claude/settings.local.json entry
If docs/project-tracker.md already exists: This skill becomes a health check — verify the format matches the standard template, flag deviations, and skip to Phase 4 (REPORT).
Global detection: Check if ~/.claude/CLAUDE.md exists. If yes, the generated CLAUDE.md will include an "extends global" reference. If not, the template is fully self-contained — no dependency on global config.
Repo classification (PM ask): Check if .gitignore excludes session infrastructure directories (tasks/, archive/, tasks/handoffs/). Capture this as a hint string — do not make a decision from it:
_(detected: 2+ of 3 session dirs gitignored — looks like a distribution repo)__(detected: standard working-tree layout)_Always ask the PM:
Is this repo:
- (a) a working repo — for active development, with session artifacts tracked
- (b) a published artifact / template — distributed for downstream consumers; no session infrastructure
- (c) both — a working repo that publishes itself as the artifact
(detected: {hint})
Branch on the PM's answer:
"You answered (b) — distribution repo. Onboarding infrastructure doesn't belong here. Track work on this repo from your parent project's tracker instead."
"This repo is published as its own working artifact — consumers see the full directory shape including
tasks/andarchive/."
Report what exists and what needs to be created before proceeding.
Project type short-circuit: Check if coordinator.local.md exists at the repo root:
test -f coordinator.local.md && echo "exists" || echo "missing"
If it exists, read it and capture project_type and project_subtypes (if present). Emit a one-line confirmation:
Project type: {type}{ +subtypes: [{subtypes}] if any}. From coordinator.local.md — skipping Phase 2 question 2.
If coordinator.local.md's project_type differs from the detected_type derived from the marker scan, append this one-line challenge immediately after the confirmation (PM remains authoritative — this is informational only, not a re-ask):
coordinator.local.mdsays{type}but detected stack is mostly{detected_type}— keeping the file value (PM authoritative). If wrong, editcoordinator.local.mdand re-run.
If coordinator.local.md is missing, proceed to Phase 2 question 2 (cold-ask) as normal.
Also check for legacy values in the file: if project_type is unreal, meta, or bare web, emit a one-line warning with the migration hint (e.g. unreal → project_type: game-dev + project_subtypes: [unreal]). Do not auto-rewrite.
Runtime marker scan: Run bash "$HOME/.claude/plugins/coordinator/bin/detect-project-runtime.sh" and capture the output. Show to PM in Phase 2 above question 2 as _(detected stack: <one-line summary>)_. PM's answer is authoritative; detection is sanity-check only. Output is advisory stdout — no skill/agent/hook reads it programmatically (adding a consumer requires a separate plan per archive/specs/2026-05-06-detect-project-runtime.md).
Derived type from markers: Once the marker scan returns, derive a detected_type (and detected_subtypes if applicable) using these rules, in priority order:
*.uplugin or *.uproject present → detected_type: game-dev, detected_subtypes: [unreal]package.json + any of next.config.js, vite.config.*, nuxt.config.*, svelte.config.*, remix.config.* present → detected_type: web-devrequirements.txt or pyproject.toml present (and no UE markers) → detected_type: data-scienceCargo.toml, go.mod, or none of the above → detected_type: generalCapture these as part of the Phase 1 profile. If coordinator.local.md already exists and its project_type differs from detected_type, emit a one-line challenge inline in the Phase 1 report (see Project type short-circuit block above for the exact wording).
Skip when Phase 1 found a genuinely empty repo (no README, no CONTRIBUTING, no top-level manifest).
Substrate-first onboarding. Read the project's accumulated institutional memory before asking the PM cold: README.md, CLAUDE.md, tasks/lessons.md, tasks/improvement-queue.md if present (1.5a); most-recent 5 handoffs for stack/tooling clues if tasks/handoffs/ exists (1.5b); sibling CLAUDE.md files for stack-shared conventions via ~/.claude/tasks/repo-registry.md stack_tags (1.5c). Output: a 5–10 line substrate snapshot. Cold-ask is the fallback when substrate is empty.
Roadmap orientation (run immediately after the substrate snapshot): Query the completed archive for recent roadmap items — especially valuable when joining cold.
"$HOME/.claude/plugins/coordinator/bin/query-records.sh" --type completion --since "90d" --where "nature=roadmap" \
--sort "-loe.tshirt" --limit 10 --format markdown-list
Render under #### Recent roadmap (last 90d, top-10 by size) in the Phase 4 REPORT (count-always per docs/wiki/orientation-surfacing-doctrine.md; (none) is expected on new repos). Otherwise:
README.md / README.rst / README.txt if present.CONTRIBUTING.md if present.package.json, pyproject.toml, Cargo.toml, go.mod, *.uplugin, *.uproject, etc. — whichever exist.git log --oneline -20.Draft proposals from what you read:
Project name — from README H1 or repo directory name.
Project type + subtypes — from manifest signals + README role description, reconciled with Phase 1 runtime-marker output. If proposal differs from detected_type, surface both with proposal winning and emit:
Detected stack suggests
{detected_type}. README/manifests suggest{proposed_type}. Going with{proposed_type}— confirm or override.
Initial workstreams (1-3) — derived from README "what this does" + recent commit subjects + any "Roadmap" / "TODO" / "Status" sections. If the repo names sibling repos (path on disk, GitHub URL, or "split" / "addon" / "upstream" / "downstream" language), capture each as peer_repo_candidates.
Present proposals to the PM for ratification:
Before I scaffold, here's what I found:
Project name: {proposed} Project type: {proposed}{, subtypes: [...] if any} Workstreams (proposed):
- {WS1} — {2-3 deliverables}
- {WS2} — {...}
Sibling repos referenced: {list with file:line citations from README/CONTRIBUTING}
Ratify, correct, or say "go cold" to skip this and ask from scratch.
On ratification: skip Phase 2's name + workstreams questions; only ask if PM corrected something or said "go cold."
On peer-repo presence: ask once whether to dispatch parallel Explore scouts (recommended). If yes, dispatch each with: "Read README, CONTRIBUTING, and recent commits. Identify shared schemas, integration contracts, and shipped vs in-flight work relevant to {this repo's name}. Reply with file:line citations." Wait for results before drafting tracker workstreams.
Skip questions Phase 1.5 already ratified. Phase 1.5 may have already pinned project name and/or workstreams; only ask the questions whose answers are still missing. If coordinator.local.md was found in Phase 1, skip question 2 — project type already pinned. Ask:
1. Project name — short name (e.g., "Geneva MVP", "DroneSim") 2. Initial workstreams (1-3) — name, 2-3 deliverables, optional deps/blockers. Say "stubs" for placeholders.
If coordinator.local.md was NOT found (cold-ask path), present all three:
1. Project name — short name (e.g., "Geneva MVP", "DroneSim") (detected stack: <one-line summary>) 2. Project type:
game-dev— Game development (adds the Game Dev Reviewer reviewer, game-dev domain agents)web-dev— Web frameworks (adds the Front-End Reviewer for front-end review, the UX Reviewer for UX)data-science— Notebooks, pipelines (adds the Data Science Reviewer reviewer)general— Standard conventions only 3. Initial workstreams (1-3) — name, 2-3 deliverables, optional deps/blockers. Say "stubs" for placeholders.
Wait for PM response before proceeding.
Create only what's missing. Use the templates in this skill's templates/ directory as the base.
Only scaffold files that have meaningful day-1 content. A placeholder header trains agents to ignore the directory; empty scaffolding has zero signal value. Create files and directories only when there is a real artifact to write.
Audit verdict — Phase 3 scaffold items:
| Item | Verdict | Reasoning |
|------|---------|-----------|
| CLAUDE.md | EAGER | Project conventions apply immediately; filled in Phase 2 |
| docs/project-tracker.md | EAGER | Workstreams established in Phase 2; real content on day 1 |
| docs/README.md | EAGER | Structural index with project name, pointers to plans/research/wikis |
| .gitignore entry | EAGER | Prevents accidental credential commits from first commit onwards |
| Post-commit hook | EAGER | Auto-push crash insurance is needed from the very first commit |
| cross-repo/ dir | EAGER (contract-bearing) | Inbound cross-repo memo channel — sibling EMs address this repo's cross-repo/ by name; must exist before any memo arrives. Scaffolded with README.md (real content, not .gitkeep) by scaffold-canonical-structure.sh. Schema: cross-repo-memo. Source of truth: canonical-structure.yaml; plan: docs/plans/2026-05-23-cross-repo-single-surface-and-canonical-scaffold.md § Lazy-vs-eager reconciliation. |
| tasks/lessons.md | LAZY | Header + comment only; no lessons exist until first session runs |
| tasks/handoffs/ dir | LAZY | No handoffs until first session ends via /handoff |
| tasks/handoff-tracker.md | LAZY (render) | Per-repo handoff tracker. Never scaffold manually — lazily created on first render by bin/render-handoff-tracker.js. Edit-resistance: two layers (agent hook + editor guard, both wired automatically). → docs/wiki/handoff-tracker-system.md § Edit-Resistance |
| archive/completed/ dir | LAZY | No completed work until first work item ships |
| docs/wiki/ dir | LAZY | Wiki guides come from /distill after artifacts accumulate |
| docs/plans/ dir | LAZY | Plans come from plan mode; none exist on day 1 |
| docs/research/ dir | LAZY | Research outputs come from /deep-research pipelines |
| tasks/review-trail/ dir | LAZY | Review records written by /workstream-complete and /handoff |
LAZY items are NOT created here. Each has a designated "create on first use" owner noted in its section below.
Use templates/CLAUDE.md.template via render-template.sh. Construct three substitution values before calling the helper:
GLOBAL_EXTENDS_LINE — Extends global \~/.claude/CLAUDE.md`.if that file exists; else""`.PROJECT_TYPE_BLOCK — concatenated per-type convention section bodies (one per selected type, blank line between). Full block bodies for game-dev, web-dev, data-science, and multi-type rules: → docs/wiki/project-onboarding-claude-md-render.md. general type: empty string.Use absolute $HOME-anchored paths. Leave <!-- Fill in --> comments as-is.
Use templates/tracker.md.template:
[PROJECT_NAME], [DATE] (today), [YEAR], [MONTH][WORKSTREAMS] with formatted workstream blocks from PM input:For each workstream the PM provided:
### N. [Workstream Name]
**Status:** Ready
**Specs:** <!-- link when spec is written -->
- [ ] [Deliverable 1]
- [ ] [Deliverable 2]
- [ ] [Deliverable 3]
If PM said "stubs": create one placeholder workstream:
### 1. [Define workstreams]
**Status:** Ready
- [ ] _PM: Define initial workstreams and deliverables_
Do NOT create this file during onboarding — no meaningful day-1 content. Created by coordinator:workstream-complete on first lesson capture.
Create docs/README.md — the documentation index maintained by /update-docs. Structure:
# [Project Name] — Documentation Index
Central entry point for all project documentation. Maintained by `/update-docs`.
---
## Wikis and Guides
→ **[`docs/wiki/DIRECTORY_GUIDE.md`](guides/DIRECTORY_GUIDE.md)** — full guide index
_No guides yet. Created by `/distill` as knowledge accumulates._
---
## Plans
→ [`docs/plans/`](plans/) — plans start in `~/.claude/plans/`, copied here on approval.
---
## Research
→ [`docs/research/`](research/) — `/deep-research` outputs; key findings extracted by `/distill`.
---
## Reference Documentation
| Doc | Purpose |
|-----|---------|
| [project-tracker.md](project-tracker.md) | Active workstreams and priorities |
---
*Last updated: [DATE]. Maintained by `/update-docs`.*
Replace [Project Name] and [DATE] with the appropriate values.
Only create directories with real day-1 content or referenced by files being written in this phase:
mkdir -p docs # for project-tracker.md (3b) and README.md (3d)
mkdir -p tasks # for feature work; lessons.md is lazy (see 3c)
Scaffold contract-bearing directories by invoking scaffold-canonical-structure.sh. This is idempotent — safe to re-run; never clobbers existing content:
# Resolve scaffold script from the coordinator plugin location, not cwd.
_scaffold_script="$HOME/.claude/plugins/coordinator/bin/scaffold-canonical-structure.sh"
# Pass --root explicitly so the scaffold targets the project repo, not the coordinator plugin root.
bash "$_scaffold_script" --root "$(pwd)"
The script reads canonical-structure.yaml and creates every creation: eager directory entry with a README.md (not a .gitkeep). Currently that means cross-repo/ with its schema-documenting README — the file an inbound sender's EM looks for before writing a memo.
Do NOT pre-create the LAZY directories above (tasks/handoffs/, archive/completed/, docs/wiki/, docs/plans/, docs/research/, tasks/review-trail/) with .gitkeep files — they are created by the skill that first writes to them (see table above). Contract-bearing dirs (cross-repo/) are scaffolded with READMEs by scaffold-canonical-structure.sh.
Ensure .gitignore contains the canonical block (per docs/wiki/gitignore-policy.md):
# Machine-specific Claude settings (do not commit)
.claude/settings.local.json
# Scratch — transient agent output, investigation notes, workstream byproduct.
# `scratch/` matches at any depth (top-level scratch/, tasks/scratch/, etc.)
scratch/
tasks/_*.log
Procedure:
.gitignore doesn't exist: Create it with the canonical block above..gitignore exists but is missing any of the three rules: Append only the missing rules under a single comment header (# Coordinator universal — scratch + machine-local settings).Warning checks:
.gitignore ignores all of .claude/ (.claude/ or .claude/*), warn: only .claude/settings.local.json needs ignoring.scratch/ or tasks/_*.log, surface count and offer git rm --cached -r cleanup (confirm with PM first — don't auto-untrack).Check for .git/hooks/post-commit. If absent, install one that delegates to the canonical helper (SSH remotes on Windows → PowerShell; HTTPS → git directly):
cat > .git/hooks/post-commit <<'HOOK'
#!/bin/bash
# Auto-push to remote on work/* or feature/* branches — crash insurance.
# Delegates to coordinator-auto-push helper.
exec "$HOME/.claude/plugins/coordinator/bin/coordinator-auto-push"
HOOK
chmod +x .git/hooks/post-commit
If the repo already has a post-commit hook (e.g. Git LFS prefix), preserve the existing block(s) and append the helper invocation backgrounded:
# === Auto-push (crash insurance) ===
( "$HOME/.claude/plugins/coordinator/bin/coordinator-auto-push" ) &
exit 0
Skip if a custom auto-push hook already exists and the PM has signed off on it.
Then harden this repo's git config against two concurrent-EM Git-for-Windows failure modes (see docs/wiki/concurrent-em-hazards.md § H21–H22): gc.autoDetach false so git's auto-maintenance runs synchronously instead of detaching into a background process that can orphan the index lock, and core.checkStat minimal so the index comparison ignores the NTFS-unstable ctime/ino/dev fields that cause a phantom-dirty tree under concurrent index rewrites:
"$HOME/.claude/plugins/coordinator/bin/coordinator-configure-git"
Idempotent — safe to re-run; a no-op if already hardened.
Mark the generated handoff tracker renders read-only in VS Code (and forks that
honor files.readonlyInclude) so a human does not accidentally hand-edit a file
the renderer overwrites. This is the editor-side complement to the agent-side
guard (the block-tracker-edit.sh PreToolUse hook, which ships with the plugin
and needs no per-project setup). Idempotent — merges two globs into
.vscode/settings.json without clobbering existing settings:
bash "$HOME/.claude/plugins/coordinator/bin/ensure-vscode-readonly.sh" --root "$(pwd)"
The helper skips loudly if jq is absent or .vscode/settings.json is JSONC
(comments/trailing commas) — in that case the report should note the two keys to
add by hand (files.readonlyInclude → "**/tasks/handoff-tracker.md": true,
"**/tasks/doe-handoff-tracker.md": true). Offer-shaped, not a hard lock: a user
can still override per-file via VS Code's "Set Active Editor Writeable".
Do NOT create this file directly — requires source file analysis handled by /update-docs Phase 2. Note in the report that the PM should run /update-docs.
Record which COORDINATOR_SCHEMA_VERSION this project was onboarded against. Idempotent —
safe to re-run; overwrites only when the schema version has been bumped since the last stamp.
Skip for distribution repos (answer (b) from Phase 1). Apply for working repos ((a) and (c)).
Resolve CLAUDE_PLUGIN_ROOT as the coordinator plugin root (e.g. ~/.claude/plugins/coordinator-claude/coordinator):
source "${CLAUDE_PLUGIN_ROOT}/lib/coordinator-currency.sh"
coordinator_currency_write "$(pwd)" "${CLAUDE_PLUGIN_ROOT}"
If the write succeeds: add docs/coordinator-currency.yaml to the Created list (or Already Existed if idempotent no-op). If it fails with a clear error, add a Needs Attention warning — the stamp is non-fatal for onboarding but required for the drift probe.
If Phase 1.5 dispatched peer-repo scouts, ensure the tracker's workstream blocks include file:line citations from the scout reports.
Present what was done:
## Onboarding Complete — [Project Name]
### Created
- [list each file/directory created]
### Already Existed (untouched)
- [list each file that was skipped]
### Needs Attention
- [any warnings — .gitignore issues, incomplete CLAUDE.md sections to fill in]
### Recent Roadmap (last 90d, top-10 by size)
_(Results from Phase 1.5 roadmap orientation query — one bullet per row. Render "(none)" when the query returns zero rows. Heading always present — count-always per orientation-surfacing-doctrine.)_
### Next Steps
0. **Your `~/.claude` is the surface you evolve** — it is a git-tracked repo that IS your live coordinator install. Customize it (CLAUDE.md, lessons, wiki), commit, and push. Never edit the upstream `coordinator-claude` source clone; changes there are overwritten on the next publish/refresh.
1. **Fill in CLAUDE.md** — the `<!-- Fill in -->` sections need project-specific details
2. **Run `/update-docs`** — generates DIRECTORY.md source index, refreshes docs/README.md, and creates orientation cache
3. **Run `/workstream-start`** — verifies everything is wired up correctly
4. **Introspect coordinator / plugin bindings** — run the envelope-branch check below to verify the coordinator sees this project correctly.
```sh
# Compact JSON output — pipe through python -m json.tool if you want pretty-print.
# No --json flag needed — default output is compact JSON.
python3 -m coordinator_whoami.project_rag # POSIX / macOS
py -3 -m coordinator_whoami.project_rag # Windows Git Bash / PowerShell
Parse binding.kind and binding.target from the JSON envelope (cross-plugin-whoami-contract.md §Operator wiring):
binding.kind == "bound" AND binding.target matches cwd: emit Coordinator binding healthy: project-rag is bound to <binding.target>.binding.kind == "bound" AND binding.target does NOT match cwd: emit a mismatch block:
Binding mismatch:
envelope binding.target : <binding.target>
expected (cwd) : <cwd>
Run /project-rag:setup to re-register this project root.
binding.kind == "unbound": emit:
project-rag is not bound to this project. Run /project-rag:setup to register this project root.ModuleNotFoundError) OR the command exits non-zero: emit:
coordinator_whoami is not installed. Run /coordinator:setup to install the introspection package.Full probe suite: docs/wiki/coordinator-doctor.md.
5. If machine-local get repos.* fails — the machine-local registry is not yet bootstrapped for this project. See coordinator-doctor.md probes P-1 through P-4 to bootstrap the registry.
The documentation index is live at docs/README.md. Subdirectories are created lazily as artifacts accumulate:
docs/wiki/ — created by /distill when first guide is extracteddocs/plans/ — created when first plan is written in plan modedocs/research/ — created by /deep-research on first run/update-docs maintains docs/README.md; /distill creates wiki guides from session artifacts
## Coordinator Conventions — Discovery Summary
When a new project is onboarded, surface these convention introductions so the EM has them at hand from day one. These are one-line pointers; the canonical docs hold the full mechanics.
- **Acceptance oracle (outer-loop):** Non-trivial reviewed plans declare bindable acceptance criteria gated at `/merging-to-main`. See `docs/wiki/writing-plans.md` § Acceptance Oracle.
## Onboarding Bug Fixes — Three-Layer Rule
Any onboarding bug fix that doesn't ship all three layers will recur:
**Layer 1 — Prevention:** Fix the install/setup script so future runs don't hit the failure.
**Layer 2 — Reactive repair:** A targeted recovery path for users who already hit the failure and won't re-run the full installer. Valid shapes: a `doctor`-style script (`--fix` flag), or an idempotent slash command safe to re-run against broken state. What matters is the ability to recover without a clean-slate install.
**Layer 3 — Searchable docs:** A row in the troubleshooting table keyed on the **literal error text** the user would see.
```markdown
| Error | Cause | Fix |
|-------|-------|-----|
| `ModuleNotFoundError: No module named 'coordinator_whoami'` | coordinator-whoami package was not installed | Run `/coordinator:setup` to install the introspection package |
Layer 2 recovery: doctor probe P-5 in coordinator-doctor.md.
When onboarding flags a new failure: Verify all three layers exist before closing — missing layers are part of the same fix, not a follow-up task.
/update-docs handles ongoing tracker maintenance. Tracker format matches the tracker-maintenance skill for consistency.tasks/handoffs/ (git-tracked); settings.local.json in .gitignore.~/.claude/CLAUDE.md exists.tools
Orient session — preflight, load context, choose work
documentation
Wrap up finished work — capture lessons, update docs
testing
Use before commit, /merge-to-main, /workday-complete, or to validate repo state. Resolves and runs the project's configured fast-test command.
development
Root-cause discipline for ONE identified bug, test failure, or unexpected behavior — pin the premise, reproduce, trace to source, fix at source, verify. For a single known issue, not a codebase sweep.