project-init
Scaffolds new projects with git, CI/CD workflows, pre-commit hooks, and build config. Use when starting a new Python, Rust, or TypeScript project from scratch.
Install
npx skills add https://github.com/athola/claude-night-market/tree/master/plugins/attune/skills/project-init
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install athola-claude-night-market@llmmart
git clone https://github.com/athola/claude-night-market.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole athola/claude-night-market collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Project Initialization Skill
Interactive workflow for initializing new software projects with complete development infrastructure.
Use When
- Starting a new Python, Rust, or TypeScript project
- Updating existing project tooling to current standards
- Need to set up git, GitHub workflows, pre-commit hooks, Makefile
- Want consistent project structure across team
- Converting unstructured project to best practices
- Adding missing configurations to established codebases
Workflow
1. Detect or Select Language
Load modules/language-detection.md
- Auto-detect from existing files (pyproject.toml, Cargo.toml, package.json)
- If ambiguous or empty directory, ask user to select
- Validate language is supported (python, rust, typescript)
2. Collect Project Metadata
Load modules/metadata-collection.md
Gather:
- Project name (default: directory name)
- Author name and email
- Project description
- Language-specific settings:
- Python: version (default 3.10)
- Rust: edition (default 2021)
- TypeScript: framework (React, Vue, etc.)
- License type (MIT, Apache, GPL, etc.)
3. Review Existing Files
Check for existing configurations:
ls -la
Verification: Run the command with --help flag to verify availability.
If files exist (Makefile, .gitignore, etc.):
- Show what would be overwritten
- Ask for confirmation or selective overwrite
- Offer merge mode (preserve custom content)
4. Render and Apply Templates
Load modules/template-rendering.md
Run initialization script:
python3 plugins/attune/scripts/attune_init.py \
--lang {{LANGUAGE}} \
--name {{PROJECT_NAME}} \
--author {{AUTHOR}} \
--email {{EMAIL}} \
--python-version {{PYTHON_VERSION}} \
--description {{DESCRIPTION}} \
--path .
Verification: Run the command with --help flag to verify availability.
The script also scaffolds the project decision journal: docs/tradeoffs.md
and docs/lessons-learned.md. These are append-only logs that later workflows
(brainstorm, specify, plan, execute, review) write to as decisions and lessons
arise. Existing journal files are never overwritten. The format follows the
leyline:decision-journal contract; init uses leyline's template when present
and a vendored copy otherwise, so it works with or without leyline installed.
Verification: Confirm docs/tradeoffs.md and docs/lessons-learned.md
exist and each contains an ## Active index and an ## Archive section.
5. Initialize Git (if needed)
# Check if git is initialized
if [ ! -d .git ]; then
git init
echo "Git repository initialized"
fi
Verification: Run git status to confirm working tree state.
6. Verify Setup
Validate setup:
# Check Makefile targets
make help
# List created files
git status
Verification: Run git status to confirm working tree state.
7. Next Steps
Advise user to:
# Install dependencies and hooks
make dev-setup
# Run tests to verify setup
make test
# See all available commands
make help
Verification: Run pytest -v to verify tests pass.
Error Handling
- Language detection fails: Ask user to specify
--lang - Script not found: Guide to plugin installation location
- Permission denied: Suggest
chmod +xon scripts - Git conflicts: Offer to stash or commit existing work
Success Criteria
- All template files created successfully
- No overwrites without user confirmation
- Git repository initialized
make helpshows available targetsmake testruns without errors (even if no tests yet)
Exit Criteria
- Template files for the selected language are created (or, in dry-run, reported) with no unconfirmed overwrites.
-
docs/tradeoffs.mdanddocs/lessons-learned.mdexist, each with an## Active indexand an## Archivesection. - A pre-existing journal file is detected and left unmodified.
- Git is initialized (unless
--no-git) andmake helplists targets. - Running with
--dry-runwrites no files, including the journal.
Examples
Example 1: New Python Project
**Verification:** Run `pytest -v` to verify tests pass.
User: /attune:project-init
Files (claude-night-market)
-
modules
-
language-detection.md 1.5 KB
# Language Detection Module Automatically detect project language or help user choose. ## Detection Strategy ### 1. Check for Language-Specific Files **Python indicators**: - `pyproject.toml` - `setup.py` - `requirements.txt` - `Pipfile` **Rust indicators**: - `Cargo.toml` - `Cargo.lock` **TypeScript indicators**: - `tsconfig.json` - `package.json` with TypeScript dependencies ### 2. Scan Source Files If no config files found, check `src/` directory: ```bash # Count file types find src -name "*.py" | wc -l find src -name "*.rs" | wc -l find src -name "*.ts" -o -name "*.tsx" | wc -l ``` Language with most files wins. ### 3. Ask User If still ambiguous: ``` Unable to auto-detect project language. Please select: 1. Python 2. Rust 3. TypeScript/React Choice [1-3]: ``` ## Implementation Use `project_detector.py`: ```python from project_detector import ProjectDetector detector = ProjectDetector(Path.cwd()) language = detector.detect_language() if not language: # Ask user print("Select language:") print(" 1. Python") print(" 2. Rust") print(" 3. TypeScript") choice = input("Choice [1-3]: ") language = ["python", "rust", "typescript"][int(choice) - 1] ``` ## Output Set language variable for subsequent modules: - `LANGUAGE` = "python" | "rust" | "typescript" ## Edge Cases - **Multiple languages detected**: Ask user which is primary - **No source files**: Default to Python (most common for new projects) - **Mixed JavaScript/TypeScript**: Prefer TypeScript if tsconfig.json exists -
metadata-collection.md 3 KB
# Metadata Collection Module Collect project metadata from user or infer from environment. ## Required Metadata ### Universal (All Languages) 1. **Project Name** - Default: Current directory name - Validation: lowercase, hyphens allowed, no spaces - Example: `my-awesome-project` 2. **Author Name** - Try to infer from git config: `git config user.name` - Fallback: Ask user - Example: `Alex Thola` 3. **Author Email** - Try to infer from git config: `git config user.email` - Fallback: Ask user - Example: `alex@example.com` 4. **Project Description** - Short one-liner - Default: "A new [language] project" - Example: `A CLI tool for managing tasks` 5. **License Type** - Options: MIT, Apache-2.0, GPL-3.0, BSD-3-Clause - Default: MIT - Example: `MIT` ### Language-Specific **Python**: - `python_version`: Default "3.10" - Check installed Python: `python3 --version` - Options: 3.10, 3.11, 3.12, 3.13 **Rust**: - `rust_edition`: Default "2021" - Options: 2015, 2018, 2021, 2024 **TypeScript**: - `framework`: React, Vue, Svelte, None - `package_manager`: npm, pnpm, yarn ## Inference Strategy ```bash # Try git config first AUTHOR=$(git config user.name 2>/dev/null || echo "Your Name") EMAIL=$(git config user.email 2>/dev/null || echo "you@example.com") # Try to detect Python version PYTHON_VERSION=$(python3 --version 2>/dev/null | cut -d' ' -f2 | cut -d'.' -f1,2) ``` ## Interactive Prompts If values can't be inferred: ``` Project Metadata ================ Project name [my-project]: Author name [Your Name]: Alex Thola Author email [you@example.com]: alex@example.com Description: A CLI tool for managing tasks Python version [3.10]: 3.12 License [MIT]: Continue with these settings? [Y/n]: ``` ## Validation - **Project name**: Must be valid Python module name (or Rust crate, npm package) - Convert spaces to hyphens - Lowercase only - No special characters except hyphen/underscore - **Email**: Basic format check (contains @) - **Python version**: Must be supported (>= 3.10) ## Output Variables Store in dictionary for template rendering: ```python metadata = { "PROJECT_NAME": "my-awesome-project", "PROJECT_MODULE": "my_awesome_project", # Python module name "AUTHOR": "Alex Thola", "EMAIL": "alex@example.com", "PYTHON_VERSION": "3.12", "DESCRIPTION": "A CLI tool for managing tasks", "LICENSE": "MIT", "YEAR": "2026", } ``` ## Examples ### Example 1: Fully Inferred ```bash # Git config exists, Python version detected Inferred project metadata: Name: awesome-cli (from directory) Author: Alex Thola (from git config) Email: alex@example.com (from git config) Python: 3.12 (detected) License: MIT (default) Accept these settings? [Y/n]: y ``` ### Example 2: Interactive ```bash # No git config, ask user Project name [awesome-cli]: Author name: Alex Thola Author email: alex@example.com Description: A CLI tool for managing tasks Python version [3.10]: 3.12 License [MIT]: ``` -
template-rendering.md 4.4 KB
# Template Rendering Module Render templates with collected metadata and copy to project. ## Template Variables Available in all templates: ```python { "PROJECT_NAME": "my-awesome-project", # Project name with hyphens "PROJECT_MODULE": "my_awesome_project", # Python module name (underscores) "AUTHOR": "Alex Thola", # Author name "EMAIL": "alex@example.com", # Author email "PYTHON_VERSION": "3.12", # Python version (e.g., "3.12") "PYTHON_VERSION_SHORT": "312", # Short version (e.g., "312") "LICENSE": "MIT", # License type "DESCRIPTION": "A CLI tool", # Short description "YEAR": "2026", # Current year } ``` ## Template Syntax Use simple `{{VARIABLE}}` replacement: ```toml # pyproject.toml.template [project] name = "{{PROJECT_NAME}}" version = "0.1.0" description = "{{PROJECT_DESCRIPTION}}" authors = [ {name = "{{AUTHOR}}", email = "{{EMAIL}}"} ] ``` ## Rendering Process ### 1. Find Templates ```bash TEMPLATE_DIR="plugins/attune/templates/python" find "$TEMPLATE_DIR" -name "*.template" ``` ### 2. Process Each Template ```python from template_engine import TemplateEngine engine = TemplateEngine(variables) for template_path in template_files: # Calculate output path (remove .template extension) output_path = str(template_path).replace(".template", "") # Render template engine.render_file(template_path, output_path) ``` ### 3. Handle Conflicts If output file exists: ``` File exists: pyproject.toml Options: 1. Skip (keep existing) 2. Overwrite (replace with template) 3. Diff (show differences) 4. Merge (combine both) [Not implemented yet] Choice [1-4]: ``` ## Safety Checks ### Before Rendering - ✅ Check output file doesn't exist (unless --force) - ✅ Validate all template variables are provided - ✅ Check write permissions on output directory ### During Rendering - ✅ Create parent directories if needed - ✅ Log each file created - ✅ Track success/failure for each template ### After Rendering - ✅ Verify all expected files created - ✅ Check file permissions are correct - ✅ Run basic validation (e.g., `make help`) ## Error Handling **Template variable missing**: ```python # In template: {{UNKNOWN_VAR}} # Result: Leaves {{UNKNOWN_VAR}} unchanged (visible in output) # Better: Raise error before rendering ``` **Write permission denied**: ```python try: output_path.write_text(rendered) except PermissionError: print(f"✗ Permission denied: {output_path}") print(" Try: chmod +w .") ``` **Directory creation fails**: ```python try: output_path.parent.mkdir(parents=True, exist_ok=True) except OSError as e: print(f"✗ Cannot create directory: {e}") ``` ## Post-Rendering Actions ### Python Projects 1. **Create source structure**: ```python src_dir = Path("src") / metadata["PROJECT_MODULE"] src_dir.mkdir(parents=True, exist_ok=True) (src_dir / "__init__.py").write_text( f'"""{{metadata["PROJECT_MODULE"]}} package."""\n\n__version__ = "0.1.0"\n' ) ``` 2. **Create tests directory**: ```python tests_dir = Path("tests") tests_dir.mkdir(exist_ok=True) (tests_dir / "__init__.py").write_text("") ``` 3. **Initialize README** (if doesn't exist): ```python readme = Path("README.md") if not readme.exists(): readme.write_text(f"# {metadata['PROJECT_NAME']}\n\n...") ``` ## Validation After all templates rendered: ```bash # Check Makefile works make help # Check git status git status # Verify directory structure tree -L 2 ``` ## Success Criteria - ✅ All templates rendered without errors - ✅ No unresolved template variables in output - ✅ All directories created successfully - ✅ File permissions correct (644 for files, 755 for directories) - ✅ `make help` runs successfully ## Examples ### Example 1: Successful Rendering ``` Rendering templates... ✓ .gitignore ✓ pyproject.toml ✓ Makefile ✓ .pre-commit-config.yaml ✓ .github/workflows/test.yml ✓ .github/workflows/lint.yml ✓ .github/workflows/typecheck.yml Creating project structure... ✓ src/my_awesome_project/__init__.py ✓ tests/__init__.py ✓ README.md All templates rendered successfully! ``` ### Example 2: Handling Conflicts ``` Rendering templates... ✓ .gitignore ⊘ pyproject.toml (skipped - file exists) ? Makefile File exists. Overwrite? [y/N]: n ⊘ Makefile (skipped - user declined) ✓ .pre-commit-config.yaml ... ```
-
-
SKILL.md 4.5 KB
--- name: project-init description: Scaffolds new projects with git, CI/CD workflows, pre-commit hooks, and build config. Use when starting a new Python, Rust, or TypeScript project from scratch. alwaysApply: false model: sonnet tools: [] modules: - ./modules/language-detection.md - ./modules/metadata-collection.md - ./modules/template-rendering.md model_hint: standard role: entrypoint --- # Project Initialization Skill Interactive workflow for initializing new software projects with complete development infrastructure. ## Use When - Starting a new Python, Rust, or TypeScript project - Updating existing project tooling to current standards - Need to set up git, GitHub workflows, pre-commit hooks, Makefile - Want consistent project structure across team - Converting unstructured project to best practices - Adding missing configurations to established codebases ## Workflow ### 1. Detect or Select Language Load `modules/language-detection.md` - Auto-detect from existing files (pyproject.toml, Cargo.toml, package.json) - If ambiguous or empty directory, ask user to select - Validate language is supported (python, rust, typescript) ### 2. Collect Project Metadata Load `modules/metadata-collection.md` Gather: - Project name (default: directory name) - Author name and email - Project description - Language-specific settings: - Python: version (default 3.10) - Rust: edition (default 2021) - TypeScript: framework (React, Vue, etc.) - License type (MIT, Apache, GPL, etc.) ### 3. Review Existing Files Check for existing configurations: ```bash ls -la ``` **Verification:** Run the command with `--help` flag to verify availability. If files exist (Makefile, .gitignore, etc.): - Show what would be overwritten - Ask for confirmation or selective overwrite - Offer merge mode (preserve custom content) ### 4. Render and Apply Templates Load `modules/template-rendering.md` Run initialization script: ```bash python3 plugins/attune/scripts/attune_init.py \ --lang {{LANGUAGE}} \ --name {{PROJECT_NAME}} \ --author {{AUTHOR}} \ --email {{EMAIL}} \ --python-version {{PYTHON_VERSION}} \ --description {{DESCRIPTION}} \ --path . ``` **Verification:** Run the command with `--help` flag to verify availability. The script also scaffolds the project decision journal: `docs/tradeoffs.md` and `docs/lessons-learned.md`. These are append-only logs that later workflows (brainstorm, specify, plan, execute, review) write to as decisions and lessons arise. Existing journal files are never overwritten. The format follows the `leyline:decision-journal` contract; init uses leyline's template when present and a vendored copy otherwise, so it works with or without leyline installed. **Verification:** Confirm `docs/tradeoffs.md` and `docs/lessons-learned.md` exist and each contains an `## Active index` and an `## Archive` section. ### 5. Initialize Git (if needed) ```bash # Check if git is initialized if [ ! -d .git ]; then git init echo "Git repository initialized" fi ``` **Verification:** Run `git status` to confirm working tree state. ### 6. Verify Setup Validate setup: ```bash # Check Makefile targets make help # List created files git status ``` **Verification:** Run `git status` to confirm working tree state. ### 7. Next Steps Advise user to: ```bash # Install dependencies and hooks make dev-setup # Run tests to verify setup make test # See all available commands make help ``` **Verification:** Run `pytest -v` to verify tests pass. ## Error Handling - **Language detection fails**: Ask user to specify `--lang` - **Script not found**: Guide to plugin installation location - **Permission denied**: Suggest `chmod +x` on scripts - **Git conflicts**: Offer to stash or commit existing work ## Success Criteria - All template files created successfully - No overwrites without user confirmation - Git repository initialized - `make help` shows available targets - `make test` runs without errors (even if no tests yet) ## Exit Criteria - [ ] Template files for the selected language are created (or, in dry-run, reported) with no unconfirmed overwrites. - [ ] `docs/tradeoffs.md` and `docs/lessons-learned.md` exist, each with an `## Active index` and an `## Archive` section. - [ ] A pre-existing journal file is detected and left unmodified. - [ ] Git is initialized (unless `--no-git`) and `make help` lists targets. - [ ] Running with `--dry-run` writes no files, including the journal. ## Examples ### Example 1: New Python Project ``` **Verification:** Run `pytest -v` to verify tests pass. User: /attune:project-init
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.