Initializing Project
Scaffold a new project repository optimized for agentic development from a problem description — or just set up ops tooling (git, precommits, gitignore, licensing, etc.) for an existing or empty project.
Quick Start
When invoked, follow the workflow below sequentially. Use
at each decision point to gather user preferences. Do NOT skip steps or assume defaults without asking.
Workflow
Step 0: Detect Environment
Before anything else, check the current directory's state:
- Run
git rev-parse --is-inside-work-tree
to see if the CWD is already inside a git repository (even if it has zero commits or is otherwise empty).
- Run to check if the directory has any files/folders at all.
- If it IS a git repo, note this — we will NOT run later. Also run
git symbolic-ref --short HEAD
to detect the current default branch name and store it as .
- If it is NOT a git repo, note this — we may need to initialize one later. will be determined in Step 8.
Tell the user what you detected:
- Whether the current directory is a git repo
- Whether it's empty or has existing files
Then ask explicitly:
Where do you want to set up the project?
- Here — use the current directory ()
- New subdirectory — create a new folder inside the current directory
If the user picks "New subdirectory", ask for the folder name, create it, and
into it.
All subsequent operations MUST happen in the chosen directory — never in a parent or sibling directory.
Step 1: Understand the Problem
Read the user's problem description. If none was provided, ask:
What problem are you solving? Describe what you want to build in 1-2 sentences.
Summarize back your understanding before proceeding.
Step 1.5: Scaffolding Mode
Ask the user what level of scaffolding they want:
What would you like to set up?
- Full project — scaffold code, tooling, and ops (runtime, package manager, formatter, linter, CI, license, precommits, CLAUDE.md)
- Ops only — just set up ops tooling (git, .gitignore, license, CI, precommits, CLAUDE.md) without creating project code or installing a runtime/package manager
If the user picks Ops only, skip Steps 2–5 entirely and jump straight to Step 6 (CI/CD). The ops-only path still walks through CI, licensing, git setup, gitignore, precommits, and CLAUDE.md.
If the user picks Full project, continue with Step 2.
Step 2: Project Name
Suggest 2-3 kebab-case project names derived from the problem description. Ask the user to pick one or provide their own.
Naming rules:
- Lowercase, kebab-case ()
- Short (1-3 words)
- Descriptive of the solution, not the problem
Step 3: Runtime & Language
Ask the user which runtime/language to use. Present options based on what fits the problem:
| Option | When to suggest |
|---|
| TypeScript (Bun) | Web apps, APIs, CLI tools, full-stack; fast runtime with built-in bundler/test runner |
| TypeScript (Node.js) | Web apps, APIs, CLI tools, full-stack; broader ecosystem compatibility |
| Python | Data, ML/AI, scripting, automation |
| Rust | Performance-critical, systems, CLI tools |
| Go | Infrastructure, networking, microservices |
Suggest the best fit as the first option with "(Recommended)" appended.
Step 4: Package Manager & Project Init
Based on the chosen runtime, initialize the project:
TypeScript (Bun) (Recommended for TypeScript):
- Run
- Create with strict mode
TypeScript (Node.js):
- Ask: npm, yarn, or pnpm? (Recommend pnpm)
- Run the appropriate init command
- Create with strict mode
Python:
- Ask: uv, poetry, or pip? (Recommend uv)
- Run the appropriate init command
- Set Python version (ask or default to 3.12+)
Rust:
- Run
- Create to pin the toolchain and ensure all contributors have formatting/linting/editor components:
toml
[toolchain]
channel = "stable"
components = ["rustfmt", "clippy", "rust-analyzer"]
Go:
- Ask for module path (suggest
github.com/{user}/{project}
)
- Run
Step 5: Code Formatting & Linting
Ask the user which formatter and linter to use. Present options based on the chosen runtime. The user may select separate tools for formatting and linting, or a unified tool that handles both.
TypeScript / JavaScript:
| Option | Type | Description |
|---|
| Biome (Recommended) | Formatter + Linter | Fast, unified tool, minimal config |
| ESLint + Prettier | Linter + Formatter | Most popular, huge plugin ecosystem |
| ESLint (flat config) | Linter only | If user wants linting without a formatter |
| oxlint | Linter | Extremely fast, Rust-based, drop-in ESLint alternative |
Python:
| Option | Type | Description |
|---|
| Ruff (Recommended) | Formatter + Linter | Extremely fast, replaces Black + Flake8 + isort |
| Black + Flake8 | Formatter + Linter | Established, widely adopted |
| Black + Ruff | Formatter + Linter | Black formatting with Ruff linting |
Rust:
| Option | Type | Description |
|---|
| rustfmt + Clippy (Recommended) | Formatter + Linter | Standard Rust toolchain, no extra install |
Go:
| Option | Type | Description |
|---|
| gofmt + go vet (Recommended) | Formatter + Linter | Built into Go toolchain |
| gofmt + golangci-lint | Formatter + Linter | More comprehensive linting rules |
After selection:
- Install the chosen tools as dev dependencies
- Create the appropriate config file(s) (e.g., , , , )
- Add , , and scripts to the project's task runner (e.g., scripts, , )
Step 6: CI/CD
Ask the user what CI/CD they want. Options:
| Option | Description |
|---|
| GitHub Actions (Recommended) | Standard for GitHub repos |
| None | Skip CI/CD for now |
| Other | Let user specify |
If GitHub Actions is selected, create
with:
- Format check step (e.g., , , )
- Lint step (using the linter chosen in Step 5)
- Test step (appropriate test runner)
- Triggered on push to and pull requests
Note: The workflow file is created locally. The user must push the repository to GitHub and verify the workflow runs. Any required secrets (e.g.,
, deployment keys) must be configured in the repository's
Settings → Secrets and variables → Actions.
Step 7: Licensing
Ask the user which license to use. Present the common options prominently:
| Option | SPDX ID | Category | When to suggest |
|---|
| MIT | | Permissive | Most common open-source license |
| Apache 2.0 | | Permissive | Open source with patent protection |
| GPL 3.0 | | Copyleft | Requires derivative works stay open |
| Dual License | (see below) | Permissive | Two licenses (e.g., MIT + Apache-2.0, Rust standard) |
| Proprietary | — | — | Private/commercial projects |
| None | — | — | Skip for now |
| Other | (see below) | — | Pick from expanded list |
<details>
<summary>Expanded license list (click to show)</summary>
Permissive:
·
·
·
·
·
·
·
·
·
·
·
Copyleft:
·
·
·
·
·
·
·
·
·
</details>
Fetching License Text
Fetch the license text using
from this skill's vendored license templates:
https://raw.githubusercontent.com/Nathan13888/nice-skills/master/data/licenses/{SPDX-ID}
After reading, replace placeholder fields with actual values:
- or → current year
- or → user's name from (ask if not set)
Single License
- Fetch the license text from the URL above
- Replace placeholders
- Write to
Dual License
When the user selects Dual License:
- Ask which two licenses to combine (recommend MIT + Apache-2.0, the Rust ecosystem standard)
- Fetch both license texts in parallel via
- Replace placeholders in both
- Create and (pattern: )
- Create a root file explaining the dual licensing:
This project is licensed under either of
* Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
* MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Step 8: Git Setup
Use the git repo status detected in Step 0 — do NOT re-run the check.
If no repo was detected in Step 0:
- Ask the user what the default branch name should be (suggest , but accept any name such as ). Store the answer as .
- Run
git init -b {DEFAULT_BRANCH}
to initialize with that branch name.
- Create (see below)
- Create initial commit:
chore: initialize project
If a repo already exists (detected in Step 0):
- Ask the user if they want a created or updated
- If in Ops only mode and no runtime was chosen, ask the user which template(s) to use (or offer to skip)
- Ask the user if they want an initial commit with the scaffolded files
Fetching Templates
Fetch the primary
template for the chosen runtime using
:
| Runtime | Template | URL |
|---|
| TypeScript (Bun/Node) | | https://raw.githubusercontent.com/github/gitignore/b4105e73e493bb7a20b5d7ea35efd5780ca44938/Node.gitignore
|
| Python | | https://raw.githubusercontent.com/github/gitignore/b4105e73e493bb7a20b5d7ea35efd5780ca44938/Python.gitignore
|
| Rust | | https://raw.githubusercontent.com/github/gitignore/b4105e73e493bb7a20b5d7ea35efd5780ca44938/Rust.gitignore
|
| Go | | https://raw.githubusercontent.com/github/gitignore/b4105e73e493bb7a20b5d7ea35efd5780ca44938/Go.gitignore
|
After fetching the primary template, ask the user if they want additional global ignores appended:
| Option | Template Name |
|---|
| macOS | |
| Linux | |
| Windows | |
| VSCode | |
| JetBrains | |
| Vim | |
| None | (skip) |
Global URL pattern:
https://raw.githubusercontent.com/github/gitignore/b4105e73e493bb7a20b5d7ea35efd5780ca44938/Global/{Name}.gitignore
Combine templates into a single
with section headers:
gitignore
# === Node ===
{fetched Node.gitignore content}
# === macOS ===
{fetched macOS.gitignore content}
Step 9: Git Hooks
Ask the user if they want git hooks to enforce code quality. Options:
| Option | Description |
|---|
| Yes, with Lefthook (Recommended) | Universal git hooks manager; works with any language/runtime |
| Yes, with native hooks | Language-specific setup (husky, pre-commit framework, .git/hooks) |
| No | Skip git hooks |
The hooks follow this convention:
| Hook | Action |
|---|
| Auto-fix formatting and linting on staged files |
| Check formatting and linting (no fix) + run tests |
The rationale:
fixes what it can so the developer isn't blocked;
is a final gate that catches anything unfixable and runs the full test suite before code reaches the remote.
Lefthook (universal, any runtime)
Lefthook is a fast, language-agnostic git hooks manager that works for any runtime.
- Install lefthook (pick the method appropriate for the project):
- npm/bun:
npm install --save-dev lefthook
/
- Homebrew:
- Go:
go install github.com/evilmartians/lefthook@latest
- Or download a binary release from GitHub
- Create at the project root. Substitute the actual commands for the chosen runtime and formatter/linter:
yaml
pre-commit:
commands:
format-fix:
run: {format fix command} # e.g. biome format --write, ruff format, cargo fmt
lint-fix:
run: {lint fix command} # e.g. biome lint --fix, ruff check --fix, cargo clippy --fix
pre-push:
commands:
format-check:
run: {format check command} # e.g. biome format --check, ruff format --check, cargo fmt --check
lint-check:
run: {lint check command} # e.g. biome lint, ruff check, cargo clippy -- -D warnings
test:
run: {test command} # e.g. bun test, pytest, cargo test, go test ./...
- Run to activate the hooks.
Native hooks (language-specific)
If the user prefers native hooks instead:
TypeScript (Bun/Node.js):
- Install and
- Configure in to run the formatter/linter fix commands on staged files (auto-fix on commit)
- Initialize husky with:
- hook: runs (auto-fixes staged files)
- hook: runs format check, lint check, and tests
Python:
- Install framework
- Create with hooks that fix (e.g., , )
- Run
pre-commit install --hook-type pre-commit --hook-type pre-push
- Add a stage entry (or a separate script) that runs format check, lint check, and
Rust:
- Create : runs (fix) and
- Create : runs ,
cargo clippy -- -D warnings
, and
- Make both scripts executable ()
Go:
- Create : runs (fix) and applies if available
- Create : runs (check), , and
- Make both scripts executable ()
Step 10: CLAUDE.md
Ask the user if they want an agent context file created for the project. Options:
| Option | Description |
|---|
| Yes, as | Gives Claude context about the project for agentic development |
| **Yes, as + symlink ** (recommended) | Creates as the canonical file and symlinks (preferred for multi-agent/tool setups) |
| No | Skip |
If the user picks
+ symlink, create the file as
and then run:
bash
ln -s AGENTS.md CLAUDE.md
Regardless of which option is chosen, the file content is identical — use the template below, filling in project-specific details:
markdown
# {Project Name}
{One-line problem description}
## Tech Stack
- **Runtime:** {runtime}
- **Language:** {language}
- **Package Manager:** {package manager}
- **Formatter:** {formatter}
- **Linter:** {linter}
## Project Structure
{tree of created files/dirs}
## Development
### Setup
```bash
{install command}
Run
Test
Format
Lint
Lint Fix
Conventions
- {Language-specific conventions, e.g., "Use strict TypeScript - no types"}
- Write tests for all new functionality
- Use conventional commits (type: description)
- Keep functions small and focused
Architecture
{Brief description of intended architecture based on the problem}
### Step 11: Summary
Print a summary of everything that was created. Adapt the summary to the chosen mode:
**Full project mode:**
Project initialized: {name}
Location: {path}
Runtime: {runtime}
Package Manager: {pkg manager}
Formatter: {formatter}
Linter: {linter}
License: {license(s)}
CI/CD: {ci/cd}
Pre-commit: {yes/no}
Files created:
{list of files — if AGENTS.md + symlink was chosen, show both AGENTS.md and CLAUDE.md → AGENTS.md}
Next steps:
- {install command}
- Push to GitHub and verify GitHub Actions workflows run correctly
- Configure any required secrets in Settings → Secrets and variables → Actions
- Start building!
Ops tooling initialized
Location: {path}
License: {license(s)}
CI/CD: {ci/cd}
Pre-commit: {yes/no}
Files created:
{list of files — if AGENTS.md + symlink was chosen, show both AGENTS.md and CLAUDE.md → AGENTS.md}
Next steps:
- Push to GitHub and verify GitHub Actions workflows run correctly
- Configure any required secrets in Settings → Secrets and variables → Actions
- Start building!
> **Reminder:** GitHub Actions workflows only run once the repository is pushed to GitHub. If you haven't created the remote repository yet, do that first (`gh repo create` or via the GitHub UI), then push with `git push -u origin {DEFAULT_BRANCH}`.
If the project was created in the current directory, do NOT include a `cd` step — the user is already there.
## Guidelines
- Always ask before creating files — never assume preferences
- Use `AskUserQuestion` with concrete options, not open-ended prompts
- If a tool is not installed (e.g., `bun`, `uv`), offer to install it or suggest an alternative
- **All files MUST be created in the chosen project directory (CWD or the user's subdirectory choice from Step 0) — never in a parent, sibling, or unrelated directory**
- Check if the target directory already exists before creating anything
- Keep the initial project minimal — don't over-scaffold
- Respect the user's choice to skip code scaffolding — ops-only mode is a first-class path, not a fallback
- The CLAUDE.md should be practical and specific, not boilerplate
- Detect git user.name and user.email from git config for license attribution
- If the user provides a GitHub username, use it for module paths and license
- Use `WebFetch` with prompt "Return the full file content exactly as-is" to get raw template text without summarization
- If `WebFetch` fails for any URL, fall back to generating content from memory and inform the user
- For dual-license, fetch both license texts in parallel to minimize latency