Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0654aa3
feat: [US-001] - Create typer CLI scaffold with subcommands
Feb 23, 2026
08601ea
feat: [US-002] - Implement project rename step
Feb 23, 2026
5d75446
feat: [US-003] - Implement dependency setup step
Feb 23, 2026
c8decd7
feat: [US-004] - Implement environment variable configuration step
Feb 23, 2026
99e6286
feat: [US-005] - Implement pre-commit hooks activation step
Feb 23, 2026
1657fa1
feat: [US-006] - Refactor banner and logo scripts to accept parameters
Feb 24, 2026
87b6e94
feat: [US-007] - Implement media generation step in CLI
Feb 24, 2026
24bd3e5
feat: [US-008] - Implement full onboarding flow orchestrator
Feb 24, 2026
18f58a1
feat: [US-009] - Remove old Makefile targets and update documentation
Feb 24, 2026
a1bb0da
⚙️ Add make ci pre-commit requirement to CLAUDE.md
Feb 24, 2026
2ebbb41
⚙️ Remove individual onboarding step commands from docs
Feb 24, 2026
b6d4380
⚙️ Remove make banner from README quick start
Feb 24, 2026
5d882af
✨ Move inline imports to top of file in onboard.py
Feb 24, 2026
ddcd3ad
✨ Move remaining inline imports to top of file in onboard.py
Feb 24, 2026
87015d2
🐛 Fix lint CI: replace removed make setup with uv sync + install_tools
Feb 24, 2026
e58c79e
🐛 Replace em dashes with hyphens to pass AI writing check
Feb 24, 2026
3ba47c8
🐛 Fix hooks step: replace .githooks with pre-commit install
Feb 24, 2026
e0ff60f
🐛 Add pre-commit as dev dependency so hooks step works
Feb 24, 2026
77a5398
🐛 Fix media generation crash when generating both banner and logo
Feb 24, 2026
e2b021e
Update pyproject.toml
Miyamura80 Feb 24, 2026
d61f870
🐛 Fix project metadata and type errors
Feb 24, 2026
9dc3161
🐛 Defer Gemini client imports to fix CLI startup
Feb 24, 2026
ee29587
🐛 Revert README and pyproject.toml to template placeholders
Feb 24, 2026
f26e942
✨ Add explanatory comment for deferred imports
Feb 24, 2026
a4b8c64
✨ Remove Ralph agent artifacts
Feb 24, 2026
d14657b
✨ Remove remaining Ralph artifacts
Feb 24, 2026
31bf67e
✨ Restore Ralph automation scripts
Feb 24, 2026
c51732a
🐛 Fix exit code handling in orchestrator
Feb 24, 2026
2aa1add
🐛 Fix _write_env_file data loss issue
Feb 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/linter_require_ruff.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Add uv to path
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Setup
run: make setup
run: uv sync && make install_tools
- name: Run ruff
run: make ruff
- name: Run complexity check
Expand Down
8 changes: 4 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ Super-opinionated Python stack for fast development. Python >= 3.12 required. Us
## Common Commands

```bash
# Setup & Run
make init name=... description=... # Initialize project name and description
make setup # Create/update .venv and sync dependencies
make all # Run main.py with setup
# Onboarding & Setup
make onboard # Interactive onboarding CLI (rename, deps, env, hooks, media)
make all # Sync deps and run main.py

# Testing
make test # Run pytest on tests/
Expand Down Expand Up @@ -138,6 +137,7 @@ Structure as: `init()` → `continue(id)` → `cleanup(id)`
- **Protected Branch**: `main` is protected. Do not push directly to `main`. Use PRs.
- **Merge Strategy**: Squash and merge.
- **Never force push**: Do not use `git push --force` or `--force-with-lease`. If you hit a git issue, stop and ask the user for guidance.
- **Pre-commit CI gate**: Always run `make ci` before committing any changes. Ensure it passes with zero errors. Do not commit if `make ci` fails - fix all issues first, then commit.

## Deprecated

Expand Down
40 changes: 5 additions & 35 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,9 @@ help: ## Show this help message
########################################################

### Initialization
.PHONY: init banner logo
init: ## Initialize project (usage: make init name=my-project description="my description")
@if [ -z "$(name)" ] || [ -z "$(description)" ]; then \
echo "$(RED)Error: Both 'name' and 'description' parameters are required$(RESET)"; \
echo "Usage: make init name=<project_name> description=<project_description>"; \
exit 1; \
fi
@echo "$(YELLOW)🚀 Initializing project $(name)...$(RESET)"
@sed -i.bak "s/name = \"python-template\"/name = \"$(name)\"/" pyproject.toml && rm pyproject.toml.bak
@sed -i.bak "s/description = \"Add your description here\"/description = \"$(description)\"/" pyproject.toml && rm pyproject.toml.bak
@sed -i.bak "s/# Python-Template/# $(name)/" README.md && rm README.md.bak
@sed -i.bak "s/<b>Opinionated Python project stack. 🔋 Batteries included. <\/b>/<b>$(description)<\/b>/" README.md && rm README.md.bak
@echo "$(GREEN)✅ Updated project name and description.$(RESET)"
.PHONY: onboard banner logo
onboard: check_uv ## Run interactive onboarding CLI
@$(PYTHON) onboard.py

banner: check_uv ## Generate project banner image
@echo "$(YELLOW)🔍Generating banner...$(RESET)"
Expand Down Expand Up @@ -84,31 +74,10 @@ check_jq:
jq --version; \
fi

########################################################
# Setup githooks for linting
########################################################
setup_githooks:
@echo "$(YELLOW)🔨Setting up githooks on post-commit...$(RESET)"
chmod +x .githooks/post-commit
git config core.hooksPath .githooks


########################################################
# Python dependency-related
########################################################

### Setup & Dependencies
setup: check_uv ## Create venv and sync dependencies
@echo "$(YELLOW)🔎Looking for .venv...$(RESET)"
@if [ ! -d ".venv" ]; then \
echo "$(YELLOW)VS Code is not detected. Creating a new one...$(RESET)"; \
uv venv; \
else \
echo "$(GREEN)✅.venv is detected.$(RESET)"; \
fi
@echo "$(YELLOW)🔄Updating python dependencies...$(RESET)"
@uv sync

view_python_venv_size:
@echo "$(YELLOW)🔍Checking python venv size...$(RESET)"
@PYTHON_VERSION=$$(cat .python-version | cut -d. -f1,2) && \
Expand All @@ -126,7 +95,8 @@ view_python_venv_size_by_libraries:
########################################################

### Running
all: setup setup_githooks ## Setup and run main application
all: check_uv ## Sync dependencies and run main application
@uv sync
@echo "$(GREEN)🏁Running main application...$(RESET)"
@$(PYTHON) main.py
@echo "$(GREEN)✅ Main application run completed.$(RESET)"
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ Opinionated Python stack for fast development. The `saas` branch extends `main`

## Quick Start

- `make init name=my-project description="My project description"` - initialize project
- `make all` - runs `main.py`
- `make onboard` - interactive onboarding CLI (rename, deps, env, hooks, media)
- `make all` - sync deps and run `main.py`
- `make fmt` - runs `ruff format` + JSON formatting
- `make banner` - create a new banner that makes the README nice 😊
- `make test` - runs all tests in `tests/`
- `make ci` - runs all CI checks (ruff, vulture, ty, etc.)




## Configuration

```python
Expand Down
18 changes: 12 additions & 6 deletions init/generate_banner.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ class BannerDescription(dspy.Signature):
"""Generate a creative description of a person/animal/object holding a banner. Go for a japanese style, creative and fun, but make sense."""

title: str = dspy.InputField()
suggestion: str = dspy.InputField(
desc="Optional suggestion to guide the banner description generation"
theme: str = dspy.InputField(
desc="Optional theme/style suggestion to guide the banner description generation"
)
banner_description: str = dspy.OutputField(
desc="A creative description of a person/animal/object holding a banner with the given title. Do not mention any colors"
Expand All @@ -26,7 +26,13 @@ class BannerDescription(dspy.Signature):
client = genai.Client(api_key=global_config.GEMINI_API_KEY)


async def generate_banner(title: str, suggestion: str | None = None) -> Image.Image:
async def generate_banner(title: str, theme: str | None = None) -> Image.Image:
"""Generate a banner image for the project.

Args:
title: The project title to display on the banner.
theme: Optional theme/style suggestion to guide image generation.
"""
# First, use LLM to generate a creative banner description
inf_module = DSPYInference(
pred_signature=BannerDescription,
Expand All @@ -35,7 +41,7 @@ async def generate_banner(title: str, suggestion: str | None = None) -> Image.Im

result = await inf_module.run(
title=title,
suggestion=suggestion or "",
theme=theme or "",
)

print(result.banner_description)
Expand Down Expand Up @@ -72,5 +78,5 @@ async def generate_banner(title: str, suggestion: str | None = None) -> Image.Im

if __name__ == "__main__":
title = "Python-Template"
suggestion = "use a snake in the image"
asyncio.run(generate_banner(title, suggestion))
theme = "use a snake in the image"
asyncio.run(generate_banner(title, theme))
14 changes: 7 additions & 7 deletions init/generate_logo.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ class WordmarkDescription(dspy.Signature):
"""Generate a creative description for a horizontal wordmark logo with text. The wordmark should be clean, modern, and professional."""

project_name: str = dspy.InputField()
suggestion: str = dspy.InputField(
desc="Optional suggestion to guide the wordmark description generation"
theme: str = dspy.InputField(
desc="Optional theme/style suggestion to guide the wordmark description generation"
)
wordmark_description: str = dspy.OutputField(
desc="A creative description for a horizontal wordmark logo that includes the project name as text. Focus on typography, icon placement, and professional branding. The wordmark should be wide and horizontal."
Expand Down Expand Up @@ -93,7 +93,7 @@ def invert_colors(img: Image.Image) -> Image.Image:


async def generate_logo(
project_name: str, suggestion: str | None = None, output_dir: Path | None = None
project_name: str, theme: str | None = None, output_dir: Path | None = None
) -> dict[str, Image.Image]:
"""Generate logo assets using AI-powered pipeline with consistent branding:
1. Generate light mode wordmark with greenscreen
Expand All @@ -107,7 +107,7 @@ async def generate_logo(

Args:
project_name: Name of the project
suggestion: Optional suggestion to guide the logo generation
theme: Optional theme/style suggestion to guide the logo generation
output_dir: Output directory for the generated images. Defaults to docs/public/

Returns:
Expand All @@ -128,7 +128,7 @@ async def generate_logo(
wordmark_inf = DSPYInference(pred_signature=WordmarkDescription, observe=False)
wordmark_result = await wordmark_inf.run(
project_name=project_name,
suggestion=suggestion or "",
theme=theme or "",
)

print(f"Wordmark description: {wordmark_result.wordmark_description}")
Expand Down Expand Up @@ -264,5 +264,5 @@ async def generate_logo(

if __name__ == "__main__":
project_name = "Python-Template"
suggestion = "incorporate python snake and modern tech aesthetics, simple and clean"
asyncio.run(generate_logo(project_name, suggestion))
theme = "incorporate python snake and modern tech aesthetics, simple and clean"
asyncio.run(generate_logo(project_name, theme))
Loading