init
Initializes project AI-agent docs and workspace conventions. Use when generating agent rules docs, adding GitHub templates, or bootstrapping project rules.
SKILL.md.agents-plugin/skills/init/SKILL.md
GitHubClaude CLI Workspace Initialization
Profiles the project, authors the canonical tool-neutral AGENTS.md rules file (with a compatibility @AGENTS.md-importing CLAUDE.md shim and optional Claude-only notes), and optionally emits GitHub issue templates and git convention files — all flag-driven, non-destructive by default.
Current Project Context
- Profile detection (complete
key=valueoutput,project_rootfirst): !~/.agents/skills/init/scripts/profile-project.sh
Context injection is deliberately one scoped helper call: no pwd, ls | head, 2>/dev/null, or other shell pipeline/redirect. Some hosts reject compound pipelines as a whole even when each segment is allowed, and head truncated the profile (dropping keys such as has_releasing_md). Do not widen allowed-tools with find, head, wc, or pwd.
Headless / permissions
allowed-toolsgrants only the scopedscripts/*.shhelpers plus a few simple read/copy commands. Compound shell pipelines (a | b,a && b, redirection tricks) are host-permission behavior: this skill does not control them, and a caller allowlist that permits each segment may still reject the whole pipeline. Never rely on them.- Every step below has a pipeline-free supported path:
profile-project.sh(full profile),count-source-files.sh(capped count),render-template.sh,migrate-rules.sh,rules-report.sh. Run each as one command. - All helpers require Python 3.11+ and fail up front with a readable message (no partial output) on an older
python3.
Arguments
| Flag | Meaning | Example |
|---|---|---|
--dry-run |
Preview every planned file; make no writes | /init --dry-run |
--docs-only |
Skip MCP/agent selection; emit the rules files only | /init --docs-only |
--templates |
Also emit .github/ issue forms, PR template, labels |
/init --templates |
--git |
Also emit .gitignore, .gitmessage, commitlint (JS/TS), and the lefthook bundle |
/init --git |
--vendor-neutral |
Also emit .ai/rules/project.md pointer to AGENTS.md |
/init --vendor-neutral |
--formatters |
Also bootstrap lint/format via formatters (scripts, configs, aliases, docs) |
/init --formatters |
--release-model[=<model>] |
Run release-model without asking when RELEASING.md is missing |
/init --release-model=trunk-only |
--no-release-model |
Never offer release-model |
/init --no-release-model |
--migrate-rules |
Move an existing long CLAUDE.md into AGENTS.md (dry-run diff first) |
/init --migrate-rules |
--allow-non-git |
With --migrate-rules: permit non-git or git-ignored rules files (timestamped backups first) |
/init --migrate-rules --allow-non-git |
--no-claude-md |
Skip the @AGENTS.md CLAUDE.md shim (needs Claude Code 2.1.277+) |
/init --no-claude-md |
--update |
Structured refresh of existing artifacts (merge/migrate, never clobber) | /init --update |
--force |
Overwrite existing files without prompting | /init --force |
--profile=<lang> |
Override detected language (rust, ts-node, python, go, mixed, empty) |
/init --profile=rust |
Flags are composable. See references/flag-reference.md for the full matrix.
Questions: headless (no question tool or chat turn) defaults: class clarify (empty or unknown profile): print the questions and stop; class confirm-destructive (profile confirmation, conflicts, rules migration): behave as --dry-run, skip existing files, print diffs and the rerun, then stop. The release-model offer is skipped unless --release-model is passed. See ~/.agents/ycc-shared/references/question-policy.md.
Task
Execute the following phases in order. Phases are short — do not add narrative prose between steps.
Phase 0 — Parse flags
Extract mode booleans from $ARGUMENTS:
DRY_RUN— true if--dry-runpresentDOCS_ONLY— true if--docs-onlypresentTEMPLATES— true if--templatespresentGIT— true if--gitpresentVENDOR_NEUTRAL— true if--vendor-neutralpresentFORMATTERS— true if--formatterspresentRELEASE_MODEL— true if--release-modelor--release-model=<model>presentRELEASE_MODEL_VALUE—<model>from--release-model=<model>, else empty. Must betrunk-onlyorrelease-branches; any other value is an error before any phase runs.NO_RELEASE_MODEL— true if--no-release-modelpresent. Combining it with--release-modelis an error before any phase runs.ALLOW_NON_GIT— true if--allow-non-gitpresent (only meaningful with--migrate-rules).NO_CLAUDE_MD— true if--no-claude-mdpresent.MIGRATE_RULES— true if--migrate-rulespresent. Runs only the rules migration (Phase 5.7); combine with--dry-runfor the preview without a prompt.UPDATE— true if--updatepresentFORCE— true if--forcepresentPROFILE— value of--profile=<lang>if provided, else empty
Defaults: all booleans off; no profile override. --update and --force are mutually reinforcing: --update controls merge/migrate behavior, --force controls conflict resolution. Without either, existing files are preserved with a diff-and-ask prompt.
Phase 1 — Profile
- Run
~/.agents/skills/init/scripts/profile-project.shonce, with no pipeline,head, or2>/dev/null, and parse the completekey=valueoutput into variables (the Current Project Context above already holds the same output; re-run only after it changes). Seereferences/project-profile-heuristics.mdfor the key list. - If
PROFILEflag is set, overrideprimary_languagewith that value. - If
is_empty=trueORprimary_language=unknown: ask the user conversationally for project name, purpose, and primary language. Setproject_name,project_purpose, andprimary_languagefrom their answers. - If
UPDATE=falseAND at least two ofhas_claude_md,has_agents_md,has_cursor_rules,has_issue_templates,has_gitmessage,has_gitignoreare true: warn the user "Existing doc/workflow files detected — consider re-running with--updatefor structured refresh, or--forceto overwrite. Continuing with default skip-on-conflict behavior." - Surface the resolved profile summary to the user and wait for confirmation before writing anything — except when
DRY_RUN=true, which proceeds directly to preview.
If MIGRATE_RULES=true, jump directly to Phase 5.7 after profiling; skip all other rendering, release-model, and formatter phases. Migration ignores --force.
Phase 2 — Optional deep analysis
Skip this phase when DOCS_ONLY=true.
Otherwise, estimate source file count with the single scoped helper (no pipeline; walk errors stay visible, output is capped at 51 files):
~/.agents/skills/init/scripts/count-source-files.sh --repo .
It prints count=<n>, capped=true|false, cap=50. If capped=true (i.e., >50 files), dispatch subagent_type: "codebase-research-analyst" with a prompt requesting:
- Key architectural patterns and conventions to encode in
AGENTS.md - Critical commands (test, lint, build, deploy) to embed
- Project-specific MUST/MUST NOT rules worth adding
Feed the agent's output into the AGENTS.md rendering in Phase 3 (conventions and commands only; keep the file well under 100 lines).
Phase 3 — Render templates
Load each applicable .tmpl file from ~/.agents/skills/init/templates/. Substitute all {{PLACEHOLDER}} variables using profile values from Phase 1 (and Phase 2 if run). For language-conditional blocks ({{#IF_RUST}}...{{/IF_RUST}} etc.), include only the block matching primary_language. Leave {{#IF_RELEASE_MODEL}}...{{/IF_RELEASE_MODEL}} blocks (in AGENTS.md.tmpl and github/labels.md.tmpl) unresolved — Phase 5 (dry run) or Phase 5.5 resolves them. Render all files in memory — do NOT write yet. scripts/render-template.sh --template <bundled-template> [--profile -] (profile on stdin; needs Bash 3.2+ and Python 3) renders a template without writing (a thin wrapper over scripts/render-template.py). It only reads templates under the skill's own templates/ directory. A command that profile-project.sh reports as unknown renders as # not detected inside fenced shell blocks, and any template that would put it into YAML (run:) or a checklist guards it with IF_*_CMD / IF_NO_*_CMD blocks instead (lefthook pre-push is omitted, with a comment, when no test command is detected). If profile-project.sh warns that jq is missing, say so in the Phase 1 summary: JS/TS commands could not be detected and will render as # not detected. Mixed-language profiles keep the language blocks of every component language in secondary_languages.
Rendering map:
| Condition | Source template | Target path |
|---|---|---|
| Always | AGENTS.md.tmpl |
AGENTS.md (canonical, ≤80 template lines) |
Unless NO_CLAUDE_MD=true (see below) |
CLAUDE.md.tmpl |
CLAUDE.md (@AGENTS.md + short section) |
| Path-scoped rules exist (see below) | cursor-rule.mdc.tmpl |
.cursor/rules/<scope>.mdc |
VENDOR_NEUTRAL=true |
ai-rule.md.tmpl |
.ai/rules/project.md (pointer) |
TEMPLATES=true |
github/bug_report.yml.tmpl |
.github/ISSUE_TEMPLATE/bug_report.yml |
TEMPLATES=true |
github/feature_request.yml.tmpl |
.github/ISSUE_TEMPLATE/feature_request.yml |
TEMPLATES=true |
github/docs_request.yml.tmpl |
.github/ISSUE_TEMPLATE/docs_request.yml |
TEMPLATES=true |
github/config.yml.tmpl |
.github/ISSUE_TEMPLATE/config.yml |
TEMPLATES=true |
github/pull_request_template.md.tmpl |
.github/pull_request_template.md |
TEMPLATES=true |
github/labels.md.tmpl |
.github/labels.md |
TEMPLATES=true |
github/copilot-instructions.md.tmpl |
.github/copilot-instructions.md |
TEMPLATES=true |
github/workflows/pr-title.yml.tmpl |
.github/workflows/pr-title.yml |
TEMPLATES=true |
github/workflows/pr-title-autofix.yml.tmpl |
.github/workflows/pr-title-autofix.yml |
GIT=true |
git/gitignore.tmpl |
.gitignore |
GIT=true |
git/gitmessage.tmpl |
.gitmessage |
GIT=true |
git/lefthook.yml.tmpl |
lefthook.yml |
GIT=true |
git/install-lefthook.sh.tmpl |
scripts/install-lefthook.sh |
GIT=true |
git/lefthook-usage.md.tmpl |
docs/lefthook-usage.md |
GIT=true AND primary_language in {typescript,javascript} |
git/commitlint.config.cjs.tmpl |
commitlint.config.cjs |
Rules-file shape: AGENTS.md is the single canonical rules file (detected commands, project conventions, MUST / MUST NOT, a one-line Conventional Commits rule, links) — no commit-types table, no stack table, no generic SHOULDs. CLAUDE.md is always rendered as the @AGENTS.md shim (plus a short ## Claude-only notes section, ≤15 lines total, when Phase 2 or the user supplied Claude-specific content), because Claude Code reads CLAUDE.md, not AGENTS.md, in versions before 2.1.277; newer versions fall back to AGENTS.md when no CLAUDE.md exists, so omitting the shim is version-dependent. Skip the shim only with --no-claude-md or an explicit user choice, and then state the 2.1.277+ requirement in the Phase 7 report. Emit .cursor/rules/*.mdc only for path-scoped rules (alwaysApply: false, real globs); recent Cursor versions read a root AGENTS.md when available (verify for your version), so never emit an always-apply copy of the project rules; offer --vendor-neutral or a path-scoped rule if the user's Cursor does not. copilot-instructions.md points at AGENTS.md but does not rely on Copilot following the link: it also carries the detected commands and three repo-neutral essentials (no secrets, Conventional Commits, issue link).
Language-block selection: for every template except gitignore.tmpl, include only the block matching primary_language. For gitignore.tmpl, include every block whose language appears in primary_language or secondary_languages (comma-separated) so mixed-stack repos get every applicable section. For gitignore.tmpl, javascript is treated as typescript for {{#IF_TS}} activation; terraform activates {{#IF_TERRAFORM}}.
Fill PROJECT_CONVENTIONS with verified project-specific architecture/naming constraints from existing docs, Phase 2, or the user; if none are known, use "No additional project-specific conventions detected." Never stamp generic language conventions or assumed tools. Use --keep IF_CLAUDE_ONLY --set CLAUDE_ONLY_NOTES=... for the optional Claude-only notes.
See references/template-library.md for placeholder definitions.
Phase 4 — MCP/agent selection
Skip this phase when DOCS_ONLY=true.
Run the catalog generators:
~/.agents/skills/init/scripts/generate-mcp-catalog.sh
~/.agents/skills/init/scripts/generate-agent-catalog.sh
Present all available options as checkboxes organized by category. Pre-check items that align with the detected profile (language, infrastructure, workflow). Let the user freely adjust the selection before proceeding.
Phase 5 — Dry-run check
If DRY_RUN=true:
- Print a listing of every planned file with a preview snippet (first ~15 lines each). Resolve
IF_RELEASE_MODELblocks as kept whenhas_releasing_md=trueorRELEASE_MODEL=true, else drop them. - Print planned rules-file line counts (see Phase 7) so oversize output is visible before any write.
- Show the planned
.mcp.jsoncontent. - List agent files that would be copied.
- Print the release-model step Phase 5.5 would take: "skip (RELEASING.md exists)", "skip (--no-release-model)", "would run
release-model[--model <value> --yes]", or "would offerrelease-model". - STOP — make no writes.
Phase 5.5 — Release model
Decide whether to create RELEASING.md (the project's branching and release rules — see ~/.agents/ycc-shared/references/branching-model.md), then resolve the IF_RELEASE_MODEL blocks.
- Choose the action (first match wins):
has_releasing_md=true→ skip. The project already has a release model; init reads only its presence (/release-model --auditvalidates it).NO_RELEASE_MODEL=true→ skip.RELEASE_MODEL=true→ run without asking.DOCS_ONLY=true(and no--release-model) → skip;--docs-onlystays limited to the rules files.- Otherwise → ask: "This project has no
RELEASING.md. Runrelease-modelto choose a branching and release model (trunk-only or release branches) and write one?" Default: yes. A missingRELEASING.mdnever blocks init — "no" continues normally.
- Run the
release-modelskill when chosen. WithRELEASE_MODEL_VALUEset, pass--model <value> --yes: the model was decided upstream (for example byblueprint), so the proposal is accepted without questions. Otherwise run it without arguments so it can propose a model from the repo's signals and confirm with the user. - Resolve every
IF_RELEASE_MODELblock rendered in Phase 3: keep the block contents whenRELEASING.mdnow exists at the project root, else drop the block. This covers "exists already" and "created in this run", and drops the pointer ifrelease-modelwas declined or failed. - If
release-modelerrors, record the failure for the Phase 7 summary and continue — do not abort init.
Phase 5.7 — Rules migration (when MIGRATE_RULES=true)
Runs instead of Phases 2–6.5 (profile only), for repos that already have a long CLAUDE.md. Never silently rewrites it.
- Run
~/.agents/skills/init/scripts/migrate-rules.sh --repo . --dry-run(a Bash 3.2 entrypoint forscripts/migrate-rules.py, which shares the@AGENTS.mdimport parser in_shared/scripts/rules_pointer.py(viascripts/rules_file_lib.py) with release-model'spointer-targets.sh) and show the full output: the move diff forAGENTS.mdandCLAUDE.md, new line counts, and the content-loss list (the full text of any replaced legacy pointerAGENTS.md, sections skipped as duplicates, and merge conflicts). Nothing is written. - With
DRY_RUN=true, stop here. - Otherwise ask once: "Apply this migration?" The script refuses outside the git root, over uncommitted changes, or for git-ignored/symlinked rules files;
--allow-non-gitis the explicit opt-in for those cases. Every apply first copies both files to a timestamped backup directory (printed in the output) and writes via temp file + atomic rename, restoring from the backup if the pair cannot be completed. Routing is heading-based and shown per section: only exact Claude runtime headings stay inCLAUDE.md; everything else moves toAGENTS.md, and headings that merely mention Claude are routed toAGENTS.mdand listed as ambiguous for review. On yes, run the same command with--yesinstead of--dry-run. On no, stop; nothing changed. - Content moves to
AGENTS.md; only exact Claude runtime headings remain after@AGENTS.md. Nothing is deleted (a replaced legacy pointer's full text is printed), ambiguous headings are reported, and no duplicate H1/headings are created. Report the new line counts per Phase 7.
Phase 6 — Apply
For each rendered file from Phase 3, apply the resolution rule below. Never silently clobber user content.
Target does not exist → write the rendered file.
Existing rules safeguard (before all resolution rules) → never rewrite an existing non-importing CLAUDE.md or a legacy pointer AGENTS.md, even with --force; offer --migrate-rules. Skip rendering new rules files that would conflict with that existing canonical layout.
Target exists AND FORCE=true → overwrite other artifacts and log the path.
Target exists AND UPDATE=true → structured refresh per artifact type:
| Artifact | Update behavior |
|---|---|
AGENTS.md (canonical or custom) |
Parse existing ##-level headings. Append only the template sections that are missing; preserve existing content verbatim. Report the appended section list. |
AGENTS.md (legacy pointer, agents_md_is_pointer=true) |
Offer --migrate-rules (the pointer names CLAUDE.md, so the real rules are there). Without it, leave the file untouched. |
CLAUDE.md (already @AGENTS.md) |
Leave untouched. |
CLAUDE.md (long, no @AGENTS.md) |
Never rewrite. Print the line count and offer --migrate-rules (dry-run diff first). Without it, leave the file and AGENTS.md as they are. |
.cursor/rules/<scope>.mdc |
Overwrite body content; preserve any non-standard frontmatter keys the user added beyond description, globs, alwaysApply. |
.cursor/rules/project.mdc (legacy always-apply copy) |
Leave as is; advise removing it once AGENTS.md is canonical (Cursor reads AGENTS.md when available; verify your version). |
.cursorrules (legacy, has_legacy_cursorrules=true) |
Offer --migrate-rules-style review: show its content, fold project-specific lines into AGENTS.md, and advise deleting .cursorrules (do not delete automatically). |
.ai/rules/project.md |
Overwrite the pointer body. |
.github/ISSUE_TEMPLATE/*.yml |
Per template: if missing → create; if present → show diff and default to skip (issue forms are often customized). --update --force overwrites. |
.github/pull_request_template.md |
Show diff; default skip. --update --force overwrites. |
.github/labels.md |
Always overwrite (reference doc, safe to refresh). |
.github/copilot-instructions.md |
Show diff; default skip (users customise agent-facing rules). --update --force overwrites. |
.github/workflows/pr-title.yml |
Show diff; default skip (users may customise the Conventional Commits type list or branch filters). --update --force overwrites. |
.github/workflows/pr-title-autofix.yml |
Show diff; default skip (users may tune the placeholder regex, the type-normalization pass, or the draft-toggle behaviour). --update --force overwrites. |
.gitignore |
Show diff; default skip (users curate this file heavily). --update --force overwrites. When has_gitignore=true at Phase 1, warn the user the file already exists. |
.gitmessage |
Show diff; default skip. --update --force overwrites (usually safe — it is a reference template). |
commitlint.config.cjs |
If present → show diff and default skip with a warning ("commitlint rules are often project-customized"). --update --force overwrites. |
lefthook.yml |
Show diff; default skip (users often extend the config with project-specific commands). --update --force overwrites. When has_lefthook_config=true at Phase 1, warn the user the file already exists. |
scripts/install-lefthook.sh |
Always overwrite (managed bootstrap tooling; tracks upstream improvements). |
docs/lefthook-usage.md |
Always overwrite (managed reference doc). |
Target exists AND UPDATE=false AND FORCE=false → show a unified diff, then prompt the user with three choices: overwrite, merge (only meaningful for AGENTS.md), or skip. Default choice: skip.
Then apply MCP/agent selections from Phase 4 (skipped when DOCS_ONLY=true):
${HOME}/.claude/mcp-library/generate-mcp-config.sh <selected-mcps>
Create .claude/agents/ if needed; copy selected agent files from ${HOME}/.claude/agents/.
Phase 6.5 — Formatter bootstrap (when FORMATTERS=true)
When FORMATTERS=true, invoke the formatters skill to bootstrap the lint/format environment. Pass through --dry-run and --force; let the skill handle its own flag defaults for everything else (stack detection, sync vs copy, aliases, docs). Do NOT duplicate formatter logic here — the formatters skill owns every decision about scripts, tool configs, aliases, and docs.
If DRY_RUN=true, invoke formatters --dry-run and merge its preview output into the Phase 7 summary. Otherwise invoke formatters normally.
If the formatters skill exits with an error, record the failure in the Phase 7 summary and continue — do not let a formatter error abort the overall init run.
Phase 7 — Summary report
Produce a summary using ~/.agents/skills/init/templates/workspace-report.md as the base. Extend it with these sections appended after the existing MCP/agents tables:
Docs emitted — list each path written, or "skipped: user chose keep". State explicitly when the user opted out of the CLAUDE.md shim (requires Claude Code 2.1.277+ for native AGENTS.md fallback).
Rules files — one line per rules file that exists after the run (AGENTS.md, CLAUDE.md, .github/copilot-instructions.md, .cursor/rules/*.mdc) with its line count, e.g. AGENTS.md: 31 lines. Mark any file over 200 lines ⚠ over 200 lines — long rules files lose adherence; trim or run --migrate-rules. Run ~/.agents/skills/init/scripts/rules-report.sh to produce these lines; do not estimate.
GitHub templates emitted — list each .github/ path written (omit section if TEMPLATES=false).
Git conventions emitted — list each git artifact path written (omit section if GIT=false).
Release model — the Phase 5.5 outcome: RELEASING.md created (with the chosen model), already present, skipped (and why), declined, or failed (with the error).
Next steps — suggest:
git config commit.template .gitmessage(ifGIT=true)- Review the generated
.gitignore— confirm language sections match the stack and add project-specific entries (secrets files, generated assets, local scratch dirs). Rust libraries should un-comment theCargo.lockignore line (ifGIT=true). bash scripts/install-lefthook.shto install thelefthookbinary and activate the hooks defined inlefthook.yml(ifGIT=true). Re-runnable on every checkout; safe to rerun.- For JS/TS projects: run
{{PACKAGE_MANAGER}} install(devDependencies@commitlint/cli+@commitlint/config-conventionalmust be installed for thecommit-msghook to work). - Review
.github/labels.mdand run thegh label createcommands listed there (ifTEMPLATES=true). Under the release-branches model, create onebackport:X.Ylabel per maintenance branch. - Review
RELEASING.mdand commit it with the rest of the init output (if Phase 5.5 created it). If the offer was declined,/release-modelcan create it later. - Review
.github/copilot-instructions.md— it is a short pointer toAGENTS.mdplus the detected commands; keep it that way (ifTEMPLATES=true). - Enable the PR title check as a required status: Settings → Branches → Branch protection rules, add
Validate Conventional Commit PR title(the job name from.github/workflows/pr-title.yml) to the required checks. Without this, the workflow runs but isn't enforced (ifTEMPLATES=true). .github/workflows/pr-title-autofix.ymlruns alongside the validator and (1) strips placeholder prefixes ([WIP],Draft:,Initial plan) from PR titles server-side, then (2) normalizes a leading Conventional Commit type that was written without a colon or with capitalization (e.g.Refactor X→refactor: X,Feat(auth): X→feat(auth): X). Runs because GitHub Copilot's coding-agent token often lackspull_requests:writeand cannot self-correct. Do not add this workflow to required checks — it is an auto-correcting side effect, not a gate (ifTEMPLATES=true).- Open
AGENTS.mdto review and refine the generated project rules (it is the canonical file; add only what is specific to this project). - If
has_legacy_cursorrules=true: fold any project-specific lines of.cursorrulesintoAGENTS.md, then delete it (init never deletes it).
Important Notes
- Default behavior never destroys existing files; always diff-and-ask before overwriting.
--updateenables structured merge/migrate semantics and is the recommended flag when re-runninginitin a project that already has docs/templates.--forceis opt-in and always logs every path it overwrote.--update --forceapplies merge semantics but overwrites on conflict instead of skipping.- No new agents are registered.
codebase-research-analystis called only once, conditionally, for large existing repos (>50 source files) when--docs-onlyis not set. - The MCP and agent selection flow is preserved unchanged behind
--docs-only. - A missing
RELEASING.mdnever blocks init. Phase 5.5 only offersrelease-model;--release-modelruns it and--no-release-modelsilences the offer. - For the full flag matrix with composability examples, see
references/flag-reference.md. - Read
references/conventional-commits.mdonly when the user asks for the full commit-type reference; the generatedAGENTS.mdcarries a one-line rule, not the types table. Readreferences/label-taxonomy.mdwhen rendering.github/labels.md(--templates).