Scaffolder for agentic-development infrastructure inside any project
Project description
project-init
Scaffolder for agentic-development infrastructure. One command drops a .claude/ 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, enforced agent infrastructure (CI, a git-lifecycle DAG guard, memory, curated MCPs) — not a hand-maintained .claude/ per project.
uvx project-init . # scaffold into the current directory
→ How it compares to other scaffolders and Claude Code plugins: docs/positioning.md.
What it gives you
Inside any target project:
<your-project>/
├── AGENTS.md # canonical agent instructions; points into .claude/
├── CLAUDE.md # thin redirect to AGENTS.md (+ Claude-only compact instructions)
└── .claude/
├── 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:
- One folder,
.claude/, for everything agentic. Project root stays clean. - Memory is à-la-carte — a superset ladder (ADR-024): flat agent-memory files (
--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-freecorepreset). When present, the vault and the agent index are separated on disk. - The GitHub lifecycle is à-la-carte — the issue → branch → PR → review → merge automation (DAG guard hooks, lifecycle scripts, board/validation workflows, issue/PR templates, lifecycle skills) ships by default but is declinable (
--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). - Low-token code map — Python projects ship
.claude/scripts/gen_code_map.py, a deterministic AST generator that writes.claude/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 withjust code-map(#496). - Deterministic-first — hooks and scripts are bash/python. LLM calls only where generative.
- Claude-first, portable core — built and tested for Claude Code; other agents get instructions, not enforcement. See Agent support tiers.
bunanduvonly — nonpm/npx/pip/venvanywhere in scaffolded projects.
Install (one-time)
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.
Pin a specific version, or opt into the unreleased development head:
PROJECT_INIT_REF=v0.5.1 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 (any pinned tag):
uv tool install git+https://github.com/VytCepas/project-init@v0.5.1
Distribution rationale: ADR-008 (git channel), ADR-011 (PyPI via trusted publishing).
Platform requirements
macOS, Linux, and WSL work out of the box. The scaffolded hooks and lifecycle
scripts are bash (a single bash-3.2 portability floor, epic #359) — so on native Windows
(non-WSL) you need Git for Windows (it ships
bash/sh + coreutils), and you should run from a Git Bash shell. Claude
Code then runs hooks through Git Bash automatically; the wired hooks also pin
"shell": "bash" to make that explicit. Without Git for Windows, Claude Code
falls back to PowerShell, which can't run a bash hook — so the enforcement
hooks won't fire. PowerShell-only is not a supported target; there are no
.ps1 equivalents by design. (WSL remains the smoothest Windows path.)
Agent support tiers
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 — read directly from .claude/ |
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 .claude/scripts/install_hooks.sh has run (server-side actions need branch protection) |
Everything, including Ollama-based agents |
Surface support matrix
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 |
.claude/settings.json (honored) |
root .mcp.json |
yes |
| VS Code Copilot | CLAUDE.md/AGENTS.md |
.claude/skills |
Claude hooks (matchers ignored) | .vscode/mcp.json (servers) |
yes |
| Cursor | AGENTS.md |
.claude/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 |
AGENTS.md is the portability backbone (every surface reads it); CLAUDE.md
rides alongside for Claude + VS Code. The generated .claude/CAPABILITIES.md
lists exactly what a given scaffold exposes, on any surface.
Local vs. cloud: where enforcement actually runs (ADR-007)
The execution model — not the surface name — decides what binds:
- Local-execution surfaces (Claude Desktop-local, VS Code, Codex IDE, Cursor, Antigravity, Gemini Code Assist): bash hooks + git hooks + MCP stdio servers all run on your machine, so the enforcement layer is live (subject to the per-surface fidelity above — some drop hook matchers).
- Cloud-sandbox surfaces (Claude web, Codex cloud, Jules): only
repo-committed config runs; user-level
~/.claudeis 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:
- Agent hook enforcement (including the Codex CLI) is best-effort, not a guarantee. Generated hooks are
fail-open, some surfaces ignore matchers, and some (e.g. codex 0.138.0) may not
fire project-scoped hooks without an enable step; an agent reading
AGENTS.mdis 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). - Automated testing covers the Claude Code artifacts + the rendered per-surface files. The suite validates settings/skills/hooks/MCP and the generated surface configs; no GUI agent is driven live in CI.
Use
Option 1: Inside a Claude Code session (interactive)
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. It asks for project name, language, delivery model, memory stack, and MCPs — then scaffolds .claude/ for you.
Option 2: From a shell (non-interactive, for CI / scripts)
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 wizard asks (interactive mode only):
- Project name / description
- Language (Python/Node/Go/Rust/none) — drives
lint_command,format_command,test_command - Delivery model (
--delivery library|service|prototype) — how the project ships, driving its env/CI/release bundle (ADR-015).serviceadds the container parity bundle (Dockerfile +compose.yaml+ devcontainer +just up/build) and unlocks the deploy overlay;libraryadds a tag-triggered release workflow (publish disabled until you wire the registry);prototype(default) adds nothing env-specific.servicerequires a language. - Deploy overlay (
--deploy none|cloud-run|fly|k8s|registry|custom) — opt-in, service only. Container targets scaffold a build-once-by-digestdeploy.yml(GitHub Environments: staging auto-deploys, production is gated) + a declarativedeploy/environments.yaml, plussetup_env_protection.sh(server-side prod gate, tiered by profile) andwhats_deployed.sh.none(default) = your platform (Vercel/Render/Fly/…) owns deploy. - Infrastructure-as-Code (
--iac none|opentofu) — opt-in OpenTofu/HCL skeleton underinfra/+ a plan-on-PR workflow (apply is manual / environment-gated, never apply-on-merge). Emits structure only — no resources or credentials. - Multi-model switching (
--multi-model) — opt-in overlay (ADR-016) that scaffolds a claude-code-router config + asetup_models.shinstaller, so you can run DeepSeek/Kimi/Ollama through the Claude Code harness with live/modelswitching and background cost-routing — your hooks, CI gates, and standards stay identical (they run below the model). OpenAI/Codex is better in its native--agentsharness. CCR is pinned, machine-level, and the scaffolder never runs it (ADR-001). Clean by default. - AI governance (
--governance) — opt-in overlay (ADR-018) that ships governance-as-code for projects that build or operate an AI system: a policy layer (AI usage policy, approved-tools / data-handling / code-provenance docs, NIST RMF crosswalk), a system card template carrying a flat-scalar governance manifest, a two-file AIBOM (generated MCP + detected-CCR-route inventory, plus a user-owned declarations file), and a presence-triggered CI gate that validates every real system card (required fields, allowed values, theprohibited+allowed:trueillegal combo, declarations completeness,last_reviewedstaleness) — failing the build, not producing a PDF. Adopts NIST AI RMF / ISO 42001 / EU AI Act / OWASP conventions (referenced, not re-authored). A freshly scaffolded project ships only an example/template, so the gate passes until a team deliberately writes a card. Most projects are not AI products — strictly opt-in, off by default. Thegovernedpreset enables it. - Observability (
--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 backend (
--memory none|auto|obsidian|obsidian-graphify|obsidian-graphify-rag) — a superset ladder (ADR-024): none (vault-free; thecorepreset), auto (flat agent-memory files in.claude/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-runsetup_rag.shstub + therag_endpointdescriptor, 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). - GitHub lifecycle (
--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, thecreate_issue/start_task/github_workflowskills, and — in plugin mode — theproject-init-lifecycleplugin. none declines it for a forge-agnostic or minimalist scaffold (thecorepreset'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). - Core MCPs (Context7)
- Database MCP — none / Postgres / SQLite
- Browser automation — Playwright (yes/no)
- Owner/team (
--owner) — default CODEOWNERS owner, SECURITY contact, and LICENSE copyright holder (e.g.@org/team) - License (
--license mit|apache-2.0|proprietary|none) — renders a LICENSE with the current year and the owner (or project name);noneskips the file - No-plugin fallback (
--no-plugin) — copies the shared hooks/skills into.claude/and wires them insettings.jsoninstead of relying on theproject-init-workflowplugin (offline / no-trust environments) - Devcontainer (
--devcontainer) — renders.devcontainer/for Codespaces, fresh clones, and remote agent containers (see below) - Agents & surfaces (
--agents claude,codex,ollama,cursor,antigravity,vscode,amp,junie) — which agents/editors the project supports; defaultclaude. Amp and JetBrains Junie get a skills layer plus generated MCP config (.amp/settings.jsonkeyamp.mcpServers;.junie/mcp/mcp.json). Selecting thecontext7-httpMCP 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 are instructions-level only. (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.tomlwhen 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 - Toolchain pinning (
--mise) — rendersmise.tomlpinning runtime/tool versions. Ownership rule: mise owns versions only; uv/bun own dependencies, just owns commands,.envowns environment - Docs tooling (
--no-docs) — by default a python project getsmkdocs.ymland a node project getstypedoc.json(local-preview configs — there is no publish workflow; ADR-022/PI-343).--no-docsdeclines them; the wizard asks per language (#477) - Renovate (
--no-renovate) —renovate.json(the Renovate dependency-update bot config) ships by default;--no-renovatedeclines it if you use a different update mechanism (#477, ADR-022) - Editor config (
--vscode) — renders.vscode/extensions.json+ a minimalsettings.json(format-on-save wired to the preset formatter); nothing personal, and the.gitignoreshares only these two files
Every preset also scaffolds the env/secret pattern: .env.example
documents the variables and their loading order, .env is gitignored, and
.claude/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
.claude/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.
Your answers are recorded in .claude/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.
Remote and web agent sessions
Scaffolded projects bootstrap themselves in ephemeral environments (Claude Code on the web, CI agents, fresh clones):
- A SessionStart hook (
.claude/hooks/session_setup.sh) syncs dependencies when a session opens in a cold environment —just setupwhen available, falling back touv 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. - The opt-in
--devcontainerflag renders a minimal.devcontainer/(Ubuntu base image; post-create installsjustplus the language toolchain and reuses the same bootstrap) — one consistent environment for new colleagues, Codespaces, and agent containers.
Example command
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.
Update
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.)
Upgrading a scaffolded project
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 |
| removed | no longer rendered by current templates | nothing (reported only; upgrade never deletes) |
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).
.claude/memory/ and .claude/vault/ are never compared or touched, and
.claude/config.yaml keeps your hand-edited fields (project_key, board
number) — only its project_init_version and the scaffold record are
refreshed.
How it works: scaffolding records the preset, template variables, and a
content-hash manifest in a scaffold: block at the end of
.claude/config.yaml, plus the rendered text of each managed (UTF-8) file in a
.claude/.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.
Adding or removing a concern later
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
--applyit only reports what would change. -
--applyis git-guarded — it refuses a dirty work tree (so the change lands as one revertible diff);--allow-dirtyoverrides. -
removenever 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 memoryunwires the tier but keeps.claude/memory/and.claude/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)
--purgeand--exportare mutually exclusive;--purgeprints what it will delete and (like all--applyruns) 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.
Uninstall
rm -rf ~/.local/share/project-init ~/.claude/commands/project-init.md
Troubleshooting
/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 working from Git Bash on Windows
Edit and commit from inside WSL (wsl then cd ~/projects/...). Editing WSL files from Git Bash on Windows mangles executable bits and line endings.
Unknown preset 'foo'
Run project-init --help 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.
Positioning in the ecosystem
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:
- What this scaffolder owns: project infrastructure files (CI workflows,
.gitignore, GitHub issue/PR templates and board automation), preset composition with deterministic, tested rendering, and the integrated GitHub lifecycle (DAG-enforced issue → branch → PR → review → merge). No community plugin or scaffolder covers these. - Knowledge-graph memory: the community has consolidated around
Graphify for codebase knowledge
graphs. The
obsidian-graphifypreset wires it in (ADR-009). - Distributing
.claude/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 theproject-init-workflowplugin — the project-agnostic skills and guard hooks, auto-update included. Scaffolds are plugin-first (ADR-010 cutover):settings.jsonenables the plugin, and a hook or skill fix shipped in the plugin reaches every project without re-scaffolding. The--no-pluginflag restores file copies + local wiring for offline or no-marketplace-trust environments; the scaffolder keeps owning project files either way. AGENTS.mdvsCLAUDE.md: Claude Code still reads onlyCLAUDE.md(anthropics/claude-code#34235), while most other tools read theAGENTS.mdstandard — which is why this repo and scaffolded projects keep both:AGENTS.mdis the canonical source of truth andCLAUDE.mdredirects to it — Claude Code still readsCLAUDE.mdonly because of the issue above (the #136 inversion shipped).
Further reading
- Using project-init in Your Project — full workflow, day-to-day usage, customization, and troubleshooting
- Template System — how layers and variables work
- Contributing — how to contribute to project-init itself
Layout of this repo
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
Status
Actively developed and published to PyPI (current release: v0.6.0). Contributions welcome — track and propose work in GitHub Issues, and use GitHub Discussions for questions, ideas, and feedback. Forks and pull requests are encouraged.
License
Apache-2.0 — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file project_init-0.6.0.tar.gz.
File metadata
- Download URL: project_init-0.6.0.tar.gz
- Upload date:
- Size: 793.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3dbb0b950bfe3596251af0cd5237bea348ba6e83c18401bd96509afd77103d4c
|
|
| MD5 |
ada28752127cef40b4d54555f8ff1dd4
|
|
| BLAKE2b-256 |
bdc0395bbaa3e477c576f719d3a8eaead64ae87d4641341ad51cae6747164950
|
Provenance
The following attestation bundles were made for project_init-0.6.0.tar.gz:
Publisher:
release.yml on VytCepas/project-init
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
project_init-0.6.0.tar.gz -
Subject digest:
3dbb0b950bfe3596251af0cd5237bea348ba6e83c18401bd96509afd77103d4c - Sigstore transparency entry: 2048537112
- Sigstore integration time:
-
Permalink:
VytCepas/project-init@94b2b0c3488783912707e4f4dd7a9a40da5339ed -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/VytCepas
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@94b2b0c3488783912707e4f4dd7a9a40da5339ed -
Trigger Event:
push
-
Statement type:
File details
Details for the file project_init-0.6.0-py3-none-any.whl.
File metadata
- Download URL: project_init-0.6.0-py3-none-any.whl
- Upload date:
- Size: 462.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
464c9a1e1cdcd246536803bdf0e90544c048fbc86483e11e10c6a30497a348e0
|
|
| MD5 |
26da0dcca8ff8fdef80ba20d980c77f1
|
|
| BLAKE2b-256 |
d124d5e73401fafbf9ab9cfe8b54c6bd28dcb642874622f10e5b88f013412e40
|
Provenance
The following attestation bundles were made for project_init-0.6.0-py3-none-any.whl:
Publisher:
release.yml on VytCepas/project-init
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
project_init-0.6.0-py3-none-any.whl -
Subject digest:
464c9a1e1cdcd246536803bdf0e90544c048fbc86483e11e10c6a30497a348e0 - Sigstore transparency entry: 2048537139
- Sigstore integration time:
-
Permalink:
VytCepas/project-init@94b2b0c3488783912707e4f4dd7a9a40da5339ed -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/VytCepas
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@94b2b0c3488783912707e4f4dd7a9a40da5339ed -
Trigger Event:
push
-
Statement type: