AI-friendly Python project template.
This repository is a reusable template for small-to-medium Python applications developed with:
- Python 3.12+
- VS Code / WSL
unittest- optional Docker Compose
- GitHub Actions CI
- Codex CLI friendly workflows
- clear documentation for humans and AI agents
The goal of this template is to provide a clean, predictable starting point for Python projects.
It favors:
- small, reviewable changes
- simple architecture
- deterministic tests
- minimal dependencies
- explicit scripts
- documentation that stays close to the code
- AI-friendly repository conventions
This repository is intended to be used as a GitHub Template repository.
For the full workflow, including:
- preparing this repository as a template
- using
Use this template - creating a new repository from the template
- cloning the new repository
- running
scripts/init_from_template.sh - importing the template into an existing local directory
- understanding when Git creates a new directory
Full instructions: docs/template-usage.md
Minimal flow:
gh repo create sagivba/my-new-project --template sagivba/python-ai-friendly-template --private --clone
cd my-new-project
scripts/init_from_template.sh my-new-projectDo not run the initialization script from src/. Run it from the project root.
Before making changes, read these files:
AGENTS.md
.github/CONTRIBUTING.md
Use:
AGENTS.mdfor AI agents, Codex CLI, ChatGPT, and other AI-assisted coding workflows..github/CONTRIBUTING.mdfor human contribution rules, review expectations, testing policy, dependency policy, and documentation expectations.
These two files are part of the template contract. Keep them aligned with the repository structure, commands, and workflow.
This repository is intended to be marked as a GitHub Template repository.
After creating a new repository from this template, run:
scripts/init_from_template.sh my-new-projectOr, if you want to choose the Python package name explicitly:
scripts/init_from_template.sh "My New Project" --package my_new_projectThe initialization script updates:
- project name
- Python package directory under
src/ - imports and package references
README.mdpyproject.toml.env.example- Docker-related project naming references where possible
The script creates this marker file:
.template-initialized
This prevents accidental repeated initialization. A second run will fail unless --force is used.
Use --force only when you intentionally want to re-run initialization:
scripts/init_from_template.sh my-new-project --forcemy-python-project-template/
├── .github/
│ ├── workflows/
│ │ └── ci.yml
│ └── CONTRIBUTING.md
├── .vscode/
│ ├── settings.json
│ ├── launch.json
│ └── tasks.json
├── docs/
│ ├── architecture.md
│ ├── codex-workflow.md
│ └── dev-python.md
├── scripts/
│ ├── init_from_template.sh
│ ├── test.sh
│ ├── lint.sh
│ └── clean.sh
├── src/
│ └── my_python_project_template/
│ ├── __init__.py
│ ├── app.py
│ ├── config.py
│ ├── routes/
│ ├── services/
│ ├── model/
│ └── utils/
├── tests/
├── templates/
├── static/
├── .env.example
├── .gitignore
├── AGENTS.md
├── Dockerfile
├── docker-compose.yml
├── docker-compose.dev.yml
├── docker-compose.qa.yml
├── Makefile
├── README.md
├── TODO.md
├── requirements.in
├── requirements.txt
└── pyproject.toml
The template uses a simple layered structure:
routes -> services -> model
|
utils
Responsibilities:
app.py: application factory and wiringconfig.py: configuration loadingroutes/: HTTP request/response boundaryservices/: application and business logicmodel/: domain models, data structures, model-facing codeutils/: small generic helpers onlytests/:unittesttest coverage
Do not put business logic directly inside route handlers.
For more detail, read:
docs/architecture.md
python -m venv .venv
source .venv/bin/activateFor Conda:
conda create -n my-python-project-template python=3.12 -y
conda activate my-python-project-templatepython -m pip install --upgrade pip
python -m pip install -r requirements.txtcp .env.example .envThe important value is:
PYTHONPATH=src
scripts/test.sh quickor:
scripts/test.sh fullPYTHONPATH=src flask --app my_python_project_template.app:create_app run --debugOpen:
http://127.0.0.1:5000
Health endpoint:
http://127.0.0.1:5000/api/health
Expected response:
{
"status": "ok"
}This project supports running tests either locally or inside Docker.
Use local tests when working in WSL with a dedicated Python environment such as venv or Conda.
scripts/test.sh quick
scripts/test.sh fullEquivalent direct command:
PYTHONPATH=src python -m unittest discover -s tests -p "test_*.py" -vUse Docker Dev tests when you want to run the test suite inside the Dev Docker Compose environment.
scripts/test.sh quick docker-dev
scripts/test.sh full docker-devUse Docker QA tests when validating the project in a QA-like Docker Compose environment before merging.
scripts/test.sh quick docker-qa
scripts/test.sh full docker-qascripts/test.sh [quick|full] [local|docker-dev|docker-qa]Defaults:
scripts/test.shis equivalent to:
scripts/test.sh quick localThe Docker test targets use project-name based Compose names.
You can override them with environment variables:
PROJECT_NAME=my_python_project_template scripts/test.sh full docker-dev
DEV_COMPOSE_PROJECT=my_python_project_template_dev scripts/test.sh full docker-dev
QA_COMPOSE_PROJECT=my_python_project_template_qa scripts/test.sh full docker-qaDocker support is optional. The primary local development flow is WSL + VS Code + a dedicated Python environment.
docker compose -p my_python_project_template_dev -f docker-compose.yml -f docker-compose.dev.yml up -d --builddocker compose -p my_python_project_template_qa -f docker-compose.yml -f docker-compose.qa.yml up -d --builddocker compose -p my_python_project_template_dev -f docker-compose.yml -f docker-compose.dev.yml downdocker compose -p my_python_project_template_qa -f docker-compose.yml -f docker-compose.qa.yml downdocker compose -p my_python_project_template_dev -f docker-compose.yml -f docker-compose.dev.yml logs -f appRun lint checks:
scripts/lint.shFormat code:
python -m ruff format src tests
python -m ruff check --fix src testsThis repository uses unittest.
Do not introduce pytest unless the project explicitly decides to migrate.
Expected test command:
PYTHONPATH=src python -m unittest discover -s tests -p "test_*.py" -vPreferred project command:
scripts/test.sh full localTesting rules are also documented in:
AGENTS.md
.github/CONTRIBUTING.md
Open the repository from WSL:
code .The template includes:
.vscode/settings.json.vscode/launch.json.vscode/tasks.json
These files configure:
- unittest discovery
- Flask launch profile
- test tasks
- lint task
- Docker Dev/QA tasks
For more detail, read:
docs/dev-python.md
The workflow is located at:
.github/workflows/ci.yml
The CI workflow runs:
- dependency installation
- Ruff lint check
- Ruff format check
- unittest discovery
Read this file before making automated changes:
AGENTS.md
AGENTS.md defines:
- architecture boundaries
- AI/Codex working rules
- branch naming conventions
- local and Docker test targets
- lint expectations
- dependency rules
- documentation rules
- review checklist
Recommended Codex CLI branch prefix:
codex-cli/<short-task-name>
Examples:
codex-cli/add-health-endpoint
codex-cli/fix-docker-test-target
codex-cli/improve-config-loading
For more detail, read:
docs/codex-workflow.md
Read this file before opening or reviewing pull requests:
.github/CONTRIBUTING.md
CONTRIBUTING.md defines:
- working principles
- architecture expectations
- environment rules
- testing rules
- dependency rules
- secrets and configuration policy
- CI rules
- documentation rules
- pull request guidance
- preferred change style
- AI-assisted contribution rules
git clone <new-repo-url>
cd <new-repo>
scripts/init_from_template.sh my-new-project
cp .env.example .env
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
scripts/test.sh full local
scripts/lint.sh
git status
git add .
git commit -m "Initialize project from template"Optional Docker validation:
PROJECT_NAME=my_new_project scripts/test.sh full docker-dev
PROJECT_NAME=my_new_project scripts/test.sh full docker-qaAGENTS.md: instructions for AI agents and Codex-style workflows.github/CONTRIBUTING.md: human contribution rules and review expectationsdocs/dev-python.md: local Python development guidedocs/architecture.md: architecture boundariesdocs/codex-workflow.md: Codex workflow guidancescripts/init_from_template.sh: one-time initialization script after creating a new repository from the templatescripts/test.sh: canonical local and Docker test runnerscripts/lint.sh: canonical lint runner.github/workflows/ci.yml: CI definition