Scaffolder for agentic-development infrastructure
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
Scaffolder for agentic-development infrastructure. One command drops a .agents/ folder into any project so Claude Code (and other agents) have memory, docs, hooks, and curated MCPs ready to go.
Who it's for — solo devs and small teams running Claude Code seriously across multiple repos who want consistent agent infrastructure with a real boundary — git hooks and CI that bind every commit, an in-session git-lifecycle DAG guard that steers (advisory; ADR-007), memory, curated MCPs — not a hand-maintained .agents/ per project.查看完整 README ↗Scaffolder for agentic-development infrastructure. One command drops a .agents/ folder into any project so Claude Code (and other agents) have memory, docs, hooks, and curated MCPs ready to go.
Who it's for — solo devs and small teams running Claude Code seriously across multiple repos who want consistent agent infrastructure with a real boundary — git hooks and CI that bind every commit, an in-session git-lifecycle DAG guard that steers (advisory; ADR-007), memory, curated MCPs — not a hand-maintained .agents/ per project.
uvx project-init . # scaffold into the current directory
→ How it compares to other scaffolders and Claude Code plugins: docs/positioning.md.
Inside any target project:
<your-project>/
├── AGENTS.md # canonical agent instructions; points into .agents/
├── CLAUDE.md # thin redirect to AGENTS.md (+ Claude-only compact instructions)
└── .agents/
├── project-init.md # workflow + conventions
├── config.yaml # record of options chosen at init
├── settings.json # Claude Code settings + hooks
├── skills/ agents/ hooks/ scripts/ rules/
├── memory/
│ ├── MEMORY.md # grep-able memory index
└── vault/ # Obsidian vault (humans)
├── decisions/ design/ sessions/ knowledge/
Principles:
.agents/, for everything agentic. Project root stays clean.--memory auto), plus an Obsidian vault for humans (obsidian), plus Graphify for agents (obsidian-graphify), plus an opt-in tier-3 RAG seam for multi-project/monorepo scale (obsidian-graphify-rag — docs + a user-run setup stub, engine not bundled; #495), or none at all (--memory none / the vault-free core preset). When present, the vault and the agent index are separated on disk.--lifecycle none) for a forge-agnostic or minimalist scaffold. The forge-portable quality hooks (commit-msg, gitleaks, lint/format gate, prod-safety) stay either way (ADR-021)..agents/scripts/gen_code_map.py, a deterministic AST generator that writes .agents/docs/CODE_MAP.md (one line per module/class/function, from docstrings). Agents read it before grepping; in practice the map is ~3% of source size. Regenerate with just code-map (#496)./command skills: /diagram (draw and iterate architecture/code/idea diagrams as committed Mermaid source with live previews), /checkpoint (save a session handoff to a gitignored file, /clear, resume from ~500 tokens), /token_efficiency (token-frugal working habits), plus add_hook, add_command, status, review, and friends. Discover them via /help (plugin mode, the default) or .agents/skills/INDEX.md (in --no-plugin scaffolds, where the skill files are copied into the project). In plugin mode /help lists them only once the plugin is installed for the project — enabledPlugins in .claude/settings.json declares it, it does not install it. Install with claude plugin install project-init-workflow@project-init --scope project (and with the lifecycle), or in a session; tells you whether it is installed.Two install paths — pick by how you'll invoke it:
CLI-only, from PyPI (ADR-011). Gives
you the project-init command — no /project-init slash command:
uv tool install project-init # or one-off: uvx project-init .
Full setup, from git — adds the Claude Code slash command:
curl -sSL https://raw.githubusercontent.com/VytCepas/project-init/main/install.sh | bash
This installs uv if missing, clones the repo to ~/.local/share/project-init (override with PROJECT_INIT_HOME=...) pinned to the latest tagged release, and writes a user-level slash command at ~/.claude/commands/project-init.md.
It refuses any ref whose prod_guard.py lacks the symlink refusal (PI-903), which covers every release up to v1.2.2. If the latest release is one of them, the installer stops before checkout and tells you to re-run with PROJECT_INIT_REF=main.
This check is static: it exists to turn away old releases that lack the refusal, not to vet a ref. It does not defend against a ref deliberately crafted to pass it; anyone who can publish such a ref already controls what you install, so pin a ref you trust.
Pin a specific version, or opt into the unreleased development head:
PROJECT_INIT_REF=vX.Y.Z bash -c "$(curl -sSL https://raw.githubusercontent.com/VytCepas/project-init/main/install.sh)"
PROJECT_INIT_REF=main bash -c "$(curl -sSL https://raw.githubusercontent.com/VytCepas/project-init/main/install.sh)"
Direct tool install without the slash command:
uv tool install git+https://github.com/VytCepas/project-init@main
uv tool install bypasses install.sh entirely, so none of the checks above —
including the PI-903 symlink-refusal check — run. Pin a tag only if you have
verified it carries that refusal (v1.3.0 or newer); v1.2.2 and older do not.
Distribution rationale: ADR-008 (git channel), ADR-011 (PyPI via trusted publishing).
macOS and Linux. On Windows, only inside WSL2, working in the WSL
filesystem (~/...), never across /mnt/c/.... A native Windows shell (Git
Bash, MSYS2, Cygwin: uname -s starting with MINGW, MSYS or CYGWIN) is
refused by install.sh, by project-init itself and by the scaffolded
SessionStart hook, each naming WSL2 (#1070, ADR-030).
The scaffolded hooks and lifecycle scripts are bash, with a single bash-3.2
portability floor (epic #359).
This is firstly a Claude Code scaffolder. It aims to be agent-agnostic where that is cheap, but it is not natively so — be explicit about what each agent gets:
| Tier | What you get | Applies to |
|---|---|---|
| Native | Everything: deterministic hooks (lifecycle guard, pre-commit gate), skills invoked as /commands, settings wiring. Claude Code reads its config from .claude/, which the scaffolder projects from the canonical .agents/ tree — only the config surface Claude reads (settings/skills/commands/agents/rules, each rule's globs: rewritten as the paths: Claude Code scopes rules by), rebuilt each scaffold/upgrade so it never drifts, plain files so it restores identically on Linux, macOS and Windows. State (memory, ADRs) lives once in .agents/ | Claude Code (CLI + the Anthropic VS Code extension) |
| Generated per-surface config | One canonical hook/MCP spec rendered to each surface's native files (ADR-017): Codex .codex/, Cursor .cursor/, Antigravity .agents/ (experimental), VS Code .vscode/mcp.json, Amp .amp/settings.json, Junie .junie/mcp/mcp.json. Skills cross-read natively. Agent hooks (incl. the Codex CLI) are best-effort/fail-open | Codex (CLI+IDE), Cursor, Antigravity, VS Code Copilot, Amp, JetBrains Junie |
| Instructions + portable | AGENTS.md is canonical; CLAUDE.md redirects to it; lifecycle scripts (plain bash), memory/vault (markdown), git hooks (commit-msg, pre-push) — agent-independent; git hooks bind once .agents/scripts/install_hooks.sh has run (server-side actions need branch protection) | Everything, including Ollama-based agents |
Which scaffolded config each surface actually reads (full detail + sources:
docs/development/non-cli-surface-matrix.md):
| Surface | Instructions | Skills | Hooks | MCP | Local shell |
|---|---|---|---|---|---|
| Claude Code CLI / VS Code ext | CLAUDE.md | .claude/skills (mirror of .agents/skills) | .claude/settings.json (mirror of .agents/settings.json) | root .mcp.json | yes |
| VS Code Copilot | CLAUDE.md/AGENTS.md | .agents/skills | Claude hooks (matchers ignored) | .vscode/mcp.json (servers) | yes |
| Cursor | AGENTS.md | .agents/skills | .cursor/hooks.json (best-effort) | .cursor/mcp.json | yes |
| Codex (CLI + IDE) | AGENTS.md | .agents/skills | .codex/hooks.json (advisory) | .codex/config.toml | yes |
Antigravity (agy) | AGENTS.md | .agents/skills | .agents/hooks.json (experimental) | .agents/mcp_config.json | yes |
| Amp | AGENTS.md | .agents/skills | — | .amp/settings.json (amp.mcpServers) | yes |
| JetBrains Junie | AGENTS.md | .junie/skills | — | .junie/mcp/mcp.json | yes |
| Ollama-based | AGENTS.md | — | — | — | yes |
↳ via --multi-model | CLAUDE.md | .claude/skills | .claude/settings.json | root .mcp.json | yes |
AGENTS.md is the portability backbone (every surface reads it); CLAUDE.md
rides alongside for Claude + VS Code. The generated .agents/CAPABILITIES.md
lists exactly what a given scaffold exposes, on any surface.
The execution model — not the surface name — decides what binds:
~/.claude is dropped, hooks run
inside the VM, and git goes through a push-restricted proxy — the local
enforcement layer is replaced by the sandbox's.Two honest caveats hold across all of it:
AGENTS.md is
asked to follow the rules. The git hooks + CI checks are the only
enforcement that binds every surface — that is the real boundary (ADR-007).After the git install (install.sh), a /project-init slash command is available in any Claude Code session:
/project-init
This runs the interactive wizard in the current project directory. The default path is six questions (ADR-029): preset, name, description, language, one Customize? gateway, and bootstrap. Every remaining concern (delivery, MCPs, memory ladder, lifecycle, governance, dev extras, …) resolves to its documented default, is annotated with its why/cost in a resolution preview shown before you accept, and is one gateway selection away when you want to shape it — each concern still explains itself before asking (ADR-023).
With the PyPI install, plain project-init . --non-interactive … (or
uvx project-init . …) works anywhere. With the git install:
cd your-project
uvx --from ~/.local/share/project-init project-init . \
--non-interactive \
--preset obsidian-only \
--name my-app \
--description "an app" \
--language python \
--mcps context7
The full profile pays for itself on long-lived repos: the guards, lifecycle enforcement, and quality gates cost a measured token overhead per agent session (extra compliance turns + always-loaded instructions), and that overhead amortizes as sessions get longer and the codebase grows. For scratch projects, prototypes you'll delete, or short one-off tasks, that overhead buys nothing — scaffold light instead:
project-init . --non-interactive --preset core \
--memory none --lifecycle none --no-docs --no-renovate \
--name scratch --description "short-lived" --language python
You can add any declined concern later (see Adding or removing a concern later).
The wizard's concerns (interactive: the identity questions up front, the rest grouped behind the Customize gateway per ADR-029 — a flag always pins its concern and skips the prompt):
Box profile (optional): a machine-local
~/.claude/box-profile.toml(override:PROJECT_INIT_BOX_PROFILE) may seed the defaults for agent surfaces, the MCP selection, and the distribution profile — advisory only, every seed changeable, flags always win, and an absent/invalid file changes nothing. The file's format is a frozen v1 contract owned by whatever ambient agent layer writes it, not by this project;project-initonly reads it, and reads it advisorily.
lint_command, format_command, test_command--delivery library|service|prototype) — how the project ships, driving its env/CI/release bundle (ADR-015). service adds the container parity bundle (Dockerfile + compose.yaml + devcontainer + just up/build) and unlocks the deploy overlay; library adds a tag-triggered release workflow (publish disabled until you wire the registry); prototype (default) adds nothing env-specific. service requires a language.--deploy none|cloud-run|fly|k8s|registry|custom; identity via --deploy-app (default: project slug), --deploy-region (default: us-central1), --deploy-health-url (default: none) — captured interactively in the delivery group, rendered into the descriptor deploy block the orchestrator dispatches on) — opt-in, service only. Container targets scaffold a build-once-by-digest deploy.yml (GitHub Environments: staging auto-deploys, production is gated) + a declarative deploy/environments.yaml, plus setup_env_protection.sh (server-side prod gate, tiered by profile) and whats_deployed.sh. none (default) = your platform (Vercel/Render/Fly/…) owns deploy.--iac none|opentofu) — opt-in OpenTofu/HCL skeleton under infra/ + a plan-on-PR workflow (apply is manual / environment-gated, never apply-on-merge). Emits structure only — no resources or credentials.--multi-model) — opt-in overlay (ADR-016) that scaffolds a claude-code-router config + a setup_models.sh installer, so you can run DeepSeek/Kimi/Ollama through the Claude Code harness with live /model switching and background cost-routing — your hooks, CI gates, and standards stay identical (they run below the model). OpenAI/Codex is better in its native --agents harness. CCR is pinned, machine-level, and the scaffolder never runs it (ADR-001). Clean by default.--governance) — opt-in overlay (ADR-018) that ships for projects that build or operate an AI system: a (AI usage policy, approved-tools / data-handling / code-provenance docs, NIST RMF crosswalk), a template carrying a flat-scalar governance manifest, a two-file (generated MCP + detected-CCR-route inventory, plus a user-owned declarations file), and a that validates every real system card (required fields, allowed values, the + illegal combo, declarations completeness, staleness) — failing the build, not producing a PDF. Adopts NIST AI RMF / ISO 42001 / EU AI Act / OWASP conventions (referenced, not re-authored). The gate never passes on silence: a freshly scaffolded project ships only an example and templates, so CI stays red until the team either writes a real system card or declares, with a reason and a date in , that the repo ships no AI system (both together is a contradiction and fails). Most projects are not AI products — strictly opt-in, off by default. The preset enables it.Every preset also scaffolds the env/secret pattern: .env.example
documents the variables and their loading order, .env is gitignored, and
.agents/docs/guides/secrets.md covers when and how to escalate to an org
secret manager (sops / 1Password CLI / Doppler) — none is installed, that
choice is org-specific.
Every preset also ships governance starters: .github/CODEOWNERS,
CONTRIBUTING.md (setup, just --list command surface, branch/PR
conventions, review flow), and SECURITY.md. After pushing to GitHub, run
.agents/scripts/setup_github.sh --protect inside the project to apply
baseline branch protection (require CI green, require PR review, block
force-push) — unprotected default branches undermine the workflow
enforcement everything else sets up.
Every preset also ships a root PLAN.md that opens with the project's
done-gate: a Done when: line stating the outcome that makes the project
finished, and a probed by: line naming the check that proves it. Both start
as TODOs for you to fill in; "is this finished?" is then answered by running the
probe rather than by ticking a box.
Your answers are recorded in .agents/config.yaml. On the first scaffold into a project that already has files, your existing files are never clobbered: when a generated file (e.g. a hand-written CLAUDE.md) would differ, the new render is written alongside as a <file>.new sibling for you to merge, and the run prints which files were preserved. On a re-run (config already present) it refreshes the files project-init manages and never overwrites your memory/ or vault/ notes — and a managed file you have edited since the last scaffold (detected via the recorded content hashes) is protected the same way: your file stays, the fresh render lands as a <file>.new sibling. With --strict, templates are rendered and validated in a temporary directory first, then the validated scaffold files are merged into the target; strict mode is not a whole-directory replacement.
Scaffolded projects bootstrap themselves in ephemeral environments (Claude Code on the web, CI agents, fresh clones):
.agents/hooks/session_setup.sh) syncs
dependencies when a session opens in a cold environment — just setup
when available, falling back to uv sync / bun install /
go mod download. Warm sessions are a no-op: a content stamp of the
dependency manifests short-circuits before any tool runs, and a failed
bootstrap warns without blocking the session.--devcontainer flag renders a minimal
.devcontainer/ (Ubuntu base image; post-create installs just plus
the language toolchain and reuses the same bootstrap) — one consistent
environment for new colleagues, Codespaces, and agent containers.Scaffold an Obsidian-only Python project with Context7 MCP:
uvx --from ~/.local/share/project-init project-init /path/to/my-project \
--non-interactive \
--preset obsidian-only --name example --description "example python project" \
--language python --mcps context7
The test suite validates this command works correctly — see TestREADMEExampleCommand in tests/test_readme_examples.py.
PyPI install: uv tool upgrade project-init. Git install: re-run the
installer — it moves the clone to the latest tagged release:
curl -sSL https://raw.githubusercontent.com/VytCepas/project-init/main/install.sh | bash
(PROJECT_INIT_REF=main for the development head; releases are cut by
tagging vX.Y.Z, which triggers the release workflow.)
Scaffolded projects are snapshots — as project-init improves, they drift. After updating the tool itself, re-render any project from its recorded config and see what changed:
project-init upgrade /path/to/my-project # drift report only, touches nothing
project-init upgrade /path/to/my-project --apply # apply the changes
project-init upgrade /path/to/my-project --apply -i # decide per file: update / skip / diff
With -i/--interactive, --apply walks each changed/merged/conflicting file
and prompts to update it, skip it, or show its diff — skipped files stay drifted
and are re-offered next upgrade. New-file additions still use the
--accept-new/--decline-new group consent.
Upgrade as a PR. Every scaffold ships a .github/workflows/project-init-upgrade.yml
workflow (manual workflow_dispatch, opt into a cadence by uncommenting the
schedule: block). It runs the upgrade on a fresh branch and opens a pull request with the
drift — Renovate-style, but for the scaffold — so the change never lands on your
default branch unreviewed and .new conflicts show up right in the PR diff. It
installs project-init from your recorded source URL (so forks/GHES hosts work)
and uses the built-in GITHUB_TOKEN; set an UPGRADE_PR_TOKEN secret if you
want CI to run on the upgrade PR.
The report classifies every template-owned file:
| State | Meaning | --apply does |
|---|---|---|
| new | not in your project | creates it |
| changed | drifted, but you never edited it | updates it |
| merged | drifted and locally edited, but the edits don't overlap | 3-way auto-merges both in place — no .new sibling |
| conflict | drifted and locally edited with overlapping changes | keeps your file; writes the conflict-marked merge as a <file>.new sibling — your edit is never overwritten |
| local edits only | locally edited, but the template has not changed it since the recorded base | nothing — listed without a diff |
| removed | no longer rendered by current templates | nothing (reported only; upgrade never deletes) |
For merged and conflicting files the preview diffs the template's own change (recorded base → new render), not your file against the render — so a merge that keeps your lines never shows them as deleted.
A conflict with no merge base. A customised file whose base was never
recorded (or is stale) has nothing to merge against, so every --apply writes
its .new again; the report says so and names the fix. If your local content is
what you want to keep, record the current render as its base — the file itself
is not touched:
project-init upgrade --adopt-base pyproject.toml .gitignore # paths relative to the project
project-init upgrade --apply # no .new; later template changes 3-way merge
Migration notes. Alongside the file drift, upgrade prints the curated changelog/migration notes for the version span it crosses (recorded → target), with any action required step called out prominently — so you know why the files changed, not just which. The notes are packaged and read offline (no changelog fetch).
.agents/memory/ and .agents/vault/ are never compared or touched, and
.agents/config.yaml keeps your hand-edited fields (project_key, board
number) — only its project_init_version and the scaffold record are
refreshed.
.claude/ wiring can break silently — a hook loses its executable bit,
settings.json gets hand-edited into invalid JSON, a referenced script is
deleted, or the git hooks were never installed. doctor runs a fixed checklist
and prints PASS/WARN/FAIL with a fix hint per line, exiting non-zero on
any FAIL:
project-init doctor # check the current directory
project-init doctor /path/to/my-project # or a specific project
It checks that .agents/config.yaml carries a scaffold record, that
.claude/settings.json is valid JSON referencing only scripts that exist and
are executable, that the project-init plugin(s) are declared, installed for this
project and have their cached payload on disk (plugin mode) or the fallback
hooks are present (--no-plugin), that the git hooks are installed
(a warning, not a failure, before git init), and that a Python interpreter is
resolvable for the hooks. Deterministic — no LLM, no network. The plugin check
is the one read outside the project: Claude Code's install registry
(plugins/installed_plugins.json under $CLAUDE_CONFIG_DIR, default ~/.claude),
of which it reports only the project-init entries. Where that registry cannot be
read — a CI machine, another user — it WARNs; it never passes on the declaration alone.
How it works: scaffolding records the preset, template variables, and a
content-hash manifest in a scaffold: block at the end of
.agents/config.yaml, plus the rendered text of each managed (UTF-8) file in a
.agents/.upgrade-base.json sidecar. Upgrade re-renders the same preset at the
current template version into a staging directory and compares hashes, so user
edits are distinguishable from upstream template changes. When both you and the
templates changed a file, the sidecar is the base leg of a 3-way merge (via
git merge-file, with a pure-Python fallback): non-overlapping edits auto-merge,
only true overlaps become a <file>.new conflict. Migration: projects
scaffolded before this record existed are reconstructed from the semantic config
fields; without recorded hashes or a base, every modified file is conservatively
treated as a conflict (.new sibling). Run upgrade --apply once and the record
is written for next time.
Changed your mind about a tier you declined (or want to drop one)? add and
remove toggle a single concern on an already-scaffolded project — no need to
re-run the wizard. They reuse the upgrade engine, so the shared wiring
(settings.json, config.yaml, CI) is re-rendered with the concern flipped.
project-init add governance --target /path/to/proj # dry-run: report only
project-init add governance --target /path/to/proj --apply # land it
project-init add memory obsidian-only --target /path --apply # memory takes a tier
project-init remove lifecycle --target /path/to/proj --apply # drop a concern
Concerns: lifecycle, governance, observability, multi-model, docs,
renovate, and memory <stack> (auto · obsidian-only · obsidian-graphify ·
obsidian-graphify-rag · none).
Dry-run by default — without --apply it only reports what would change.
--apply is git-guarded — it refuses a dirty work tree (so the change lands
as one revertible diff); --allow-dirty overrides.
remove never destroys your edits — it deletes a concern's files only when
they are byte-identical to what it scaffolded; a file you edited is kept and
reported.
Your notes are safe — remove memory unwires the tier but keeps
.agents/memory/ and .agents/vault/ (your accumulated notes) by default. To
also handle that source data, opt in explicitly:
project-init remove memory --target /path --apply --export ~/notes-backup # move it out first
project-init remove memory --target /path --apply --purge # delete it (destructive)
--purge and --export are mutually exclusive; --purge prints what it will
delete and (like all --apply runs) requires a clean tree, so the data is
recoverable from git. The same flags also clean governance user files.
Known limits. multi-model's CCR config lives in your global ~/.config
(outside the project), so --purge does not touch it. A memory tier downgrade
done via add memory <lower-tier> keeps the now-unused higher-tier data in place;
to drop it, remove memory --purge then add memory <tier> again, or delete the
directory yourself.
# PyPI install:
uv tool uninstall project-init
# git install (installer path):
rm -rf ~/.local/share/project-init ~/.claude/commands/project-init.md
/usr/bin/env: 'bash\r': No such file or directory
A shell template arrived with CRLF line endings. The repo enforces LF via .gitattributes; if you cloned through Windows in a way that converted endings, run dos2unix install.sh templates/**/*.sh and re-clone with git clone --config core.autocrlf=false.
uv: command not found after install
The installer adds ~/.local/bin to PATH for the current process only. Add it to your shell profile: export PATH="$HOME/.local/bin:$PATH" in ~/.bashrc / ~/.zshrc.
claude mcp add fails with command not found: bunx
The MCP catalog uses bun instead of npm/npx. Install it once:
curl -fsSL https://bun.sh/install | bash
Hooks silently do nothing on commit
The hooks need python3 on PATH (replaces the previous jq dependency). They auto-detect uv run ruff for uv-managed Python projects and fall back to a system ruff.
WSL: phantom permission/CRLF changes when editing WSL files from the Windows side
Edit and commit from inside WSL (wsl then cd ~/projects/...). Editing WSL files from the Windows side mangles executable bits and line endings.
Unknown preset 'foo'
Run project-init --list-presets and pick from core (vault-free), auto (memory files, no vault), obsidian-only, obsidian-graphify (ADR-009), or governed. Custom presets go in templates/presets/<name>.toml — author one with project-init preset new <name> --extends <base> (#252).
Where project-init sits relative to the (fast-moving) community landscape, so adopters know what this tool owns and where it defers. For the full four-category comparison and the moat, see docs/positioning.md:
.gitignore, GitHub issue/PR templates and board automation),
preset composition with deterministic, tested rendering, and the integrated
GitHub lifecycle (issue → branch → PR → review → merge — steered in-session by
a DAG guard, bound by git hooks + CI). No
community plugin or scaffolder covers these.obsidian-graphify preset wires it in (ADR-009)..agents/ components: the official
Claude Code plugin marketplace
is the standard channel for hooks/skills/agents. This repo doubles as a
marketplace (.claude-plugin/marketplace.json) shipping two plugins:
project-init-workflow — the project-agnostic skills and guard hooks —
and project-init-lifecycle, the GitHub issue→branch→PR→review→merge
automation (#476), enabled only when the lifecycle tier is on. Both
auto-update. Scaffolds are plugin-first (ADR-010
cutover): settings.json enables the plugin, and a hook or skill fix
shipped in the plugin reaches every project without re-scaffolding. The
--no-plugin flag restores file copies + local wiring for offline or
no-marketplace-trust environments; the scaffolder keeps owning project
files either way.AGENTS.md vs CLAUDE.md: Claude Code still reads only CLAUDE.md
(anthropics/claude-code#34235),
while most other tools read the AGENTS.md standard — which is why this
repo and scaffolded projects keep both: AGENTS.md is the canonical source of
truth and CLAUDE.md redirects to it — Claude Code still
reads CLAUDE.md only because of the issue above (the #136 inversion shipped).project-init/
├── pyproject.toml # uv-managed, rich-only runtime dep, ruff-only dev
├── install.sh # bootstrap one-liner
├── src/project_init/ # wizard CLI + scaffold engine (scaffold, concerns, surfaces, mcps, …)
├── templates/
│ ├── base/ # always copied
│ ├── fallback/ # shared hooks/skills — rendered only with --no-plugin (ADR-010)
│ ├── presets/ # toml preset definitions
│ ├── obsidian/ # vault + agent-memory overlay
│ ├── graphify/ # Graphify memory overlay (implies obsidian)
│ ├── rag/ # tier-3 RAG memory overlay
│ ├── lifecycle/ # git lifecycle enforcement (+ lifecycle_fallback for --no-plugin)
│ ├── multi_model/ # CCR model-switching overlay (--multi-model)
│ ├── observability/ # transcript metrics overlay (--observability)
│ ├── governance/ # AI governance overlay (--governance)
│ ├── auto/ # always-on emitted artifacts
│ └── amp/ antigravity/ codex/ junie/ # per-surface wiring overlays (--agents)
└── tests/ # focused pytest modules by behavior area
Actively developed and published to PyPI (current release: v1.0.1). Contributions welcome — track and propose work in GitHub Issues, and use GitHub Discussions for questions, ideas, and feedback. Forks and pull requests are encouraged.
Apache-2.0 — see LICENSE.
project-init-lifecycle@project-init/pluginproject-init doctorbun and uv only — no npm/npx/pip/venv anywhere in scaffolded projects.prohibitedallowed:truelast_reviewed.agents/governance/NO_AI_SYSTEM.mdgoverned--observability) — opt-in overlay (ADR-019) that scaffolds a file-based usage report: a stdlib analyzer over the Claude Code transcript JSONL plus a guarded, stdin-safe hook self-log, rendered to an HTML report with one command. No Docker, no OTEL, no egress — everything stays on disk. Lets you see what your agents actually do (tokens, tool calls, activity) without a telemetry backend. Strictly opt-in, off by default.--memory none|auto|obsidian-only|obsidian-graphify|obsidian-graphify-rag; obsidian is accepted as an alias for obsidian-only) — a superset ladder (ADR-024): none (vault-free; the core preset), auto (flat agent-memory files in .agents/memory/, no vault — pure files, installs nothing), Obsidian-only (auto plus a human markdown vault), Obsidian + Graphify (obsidian plus a derived code knowledge graph; recommended for code-heavy projects), or + RAG (obsidian-graphify-rag, tier 3 — a semantic recall seam: docs + a user-run setup_rag.sh stub + the rag_endpoint descriptor, engine not bundled; worth it only at multi-project/monorepo scale, parked in #495). Each rung adds a retrieval surface without relocating the anchors. The flag overrides the preset's default; the wizard explains each backend and its install cost before asking (#466, #497, ADR-024).--lifecycle github|none) — github (default) ships the issue → branch → PR → review → merge automation: DAG guard hooks, lifecycle scripts (start_issue/finish_pr/…), board/PR-validation workflows, issue/PR templates, the create_issue/start_task/github_workflow skills, and — in plugin mode — the project-init-lifecycle plugin. none declines it for a forge-agnostic or minimalist scaffold (the core preset's audience). The forge-portable quality hooks (commit-msg, gitleaks secret scan, lint/format gate, prod-safety) stay either way. The flag overrides the preset's default; the wizard explains it before asking (#476, ADR-021).psql/sqlite3 access instead--profile individual|standalone|org) — how the project receives project-init updates and how strictly rules are enforced (ADR-013): individual (default — plugin-first, updates tracked from upstream, advisory enforcement), standalone (everything copied into the repo, no plugin dependency, you apply updates), org (your organization's fork is the source of truth, server-side enforcement). Org mode can add --no-egress to omit the external official plugin marketplace from scaffolded settings (#258)--owner) — default CODEOWNERS owner, SECURITY contact, and LICENSE copyright holder (e.g. @org/team)--license mit|apache-2.0|proprietary|none) — renders a LICENSE with the current year and the owner (or project name); none skips the file--no-plugin) — copies the shared hooks/skills into .agents/ and wires them in settings.json instead of relying on the project-init-workflow plugin (offline / no-trust environments)--devcontainer) — renders .devcontainer/ for Codespaces, fresh clones, and remote agent containers (see below)--agents claude,codex,ollama,cursor,antigravity,vscode,amp,junie) — which agents/editors the project supports; default claude. Amp and JetBrains Junie get a skills layer plus generated MCP config (.amp/settings.json key amp.mcpServers; .junie/mcp/mcp.json). Selecting the context7-http MCP emits an HTTP/streamable entry (type: http) — the transport that works on Claude web/mobile/Cowork, where stdio servers are invisible. Codex gets the shared skills at .agents/skills/ plus the command guard wired via .codex/hooks.json (advisory — codex 0.138.0 may not fire project hooks without an enable step); Antigravity (agy, Google's CLI/IDE) gets the shared skills at .agents/skills/, the command guard via .agents/hooks.json (experimental), and project MCP at .agents/mcp_config.json; Ollama-based agents get the portable AGENTS.md contract (plus git-level enforcement) as a standalone surface — Ollama is a model server with no universal client-side hook/skill/MCP config to wire. To run other models with the full hooks/skills/MCP harness, use --multi-model (CCR), which routes them through the Claude Code harness so your standards run below the model — whether local (Ollama-served, e.g. qwen3-coder) or cloud (DeepSeek, Kimi). Model tool-calling quality varies, so pick one suited to agentic use. (Gemini CLI was removed in PI-386 — Google sunset its free/Pro/Ultra tiers on 2026-06-18; Antigravity, which reads the same .agents/ tree, is the Google target.) Other GUI surfaces get generated per-surface config from one canonical source (ADR-017): Cursor → .cursor/hooks.json + .cursor/mcp.json, VS Code → .vscode/mcp.json; selecting any MCP also emits a root .mcp.json (Claude's shareable project scope) and .codex/config.toml when Codex is on. Skills are read natively by all of these. Agent hooks (incl. the Codex CLI) are best-effort/fail-open (their exact blocking I/O wasn't live-verified — e.g. codex 0.138.0 may not fire project hooks without an enable step); git hooks + CI remain the only enforcement that binds every surface. Only the Claude path is functionally CI-tested — overlays are contract-tested on the rendered files--mise) — renders mise.toml pinning runtime/tool versions. Ownership rule: mise owns versions only; uv/bun own dependencies, just owns commands, .env owns environment--no-docs) — by default a python project gets mkdocs.yml and a node project gets typedoc.json (local-preview configs — there is no publish workflow; ADR-022/PI-343). --no-docs declines them; the wizard asks per language (#477)--no-renovate) — renovate.json (the Renovate dependency-update bot config) ships by default; --no-renovate declines it if you use a different update mechanism (#477, ADR-022)--vscode) — renders .vscode/extensions.json + a minimal settings.json (format-on-save wired to the preset formatter); nothing personal, and the .gitignore shares only these two files