Skip to main content

scaffld

Python License: MIT

Scaffold a new, fully-wired Python project in seconds — with a friendly terminal UI.

scaffld generates a clean project skeleton (src layout, tests, typed code, CI, pre-commit, license, and an optional virtualenv) from extensible templates. No cookiecutter YAML to memorize, no {% raw %} gymnastics to keep GitHub Actions files intact — just answer a few prompts and start writing code.

pip install scaffld
scaffld new

Features

  • Interactive TUI built with Rich — pick a template from a table, confirm a summary, watch the file tree appear.
  • Batteries included — every project ships with pyproject.toml, a src/ layout, pytest tests that pass out of the box, a GitHub Actions matrix CI, a .pre-commit-config.yaml, a real LICENSE, and a sensible .gitignore.
  • Three built-in templates — python-lib, python-cli, and python-api (FastAPI).
  • GitHub-Actions-safe templating — a tiny custom engine leaves ${{ ... }} expressions untouched, so your workflow files render correctly with zero escaping.
  • Extensible — drop your own template folder in ~/.scaffld/templates and it shows up instantly. Templates are just a template.toml plus a files/ tree.
  • Scriptable — --no-input makes scaffld behave in CI and Makefiles.
  • Zero-config virtualenv — optionally creates .venv for the new project.

Install

pip install scaffld
# or, from a clone:
pip install -e ".[dev]"

Installing from the repository needs git on your machine; scaffld is not on PyPI yet, so pip install scaffld will not find it.

Requires Python 3.9+. Runtime dependencies: typer and rich (plus tomli on 3.9/3.10).

Usage

List the available templates:

$ scaffld list
                              Available templates
┏━━━┳━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ # ┃ Template   ┃ Kind    ┃ Description                                       ┃
┡━━━╇━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 1 │ python-api │ api     │ FastAPI service with a health route, typed        │
│   │            │         │ handlers, and CI.                                 │
│ 2 │ python-cli │ cli     │ Zero-dependency argparse CLI with a               │
│   │            │         │ console-script entry point.                       │
│ 3 │ python-lib │ library │ Importable Python library: src/ layout, typed     │
│   │            │         │ API, tests, and CI.                               │
└───┴────────────┴─────────┴───────────────────────────────────────────────────┘

Create a project. Run scaffld new with no arguments for the full interactive flow, or pass flags to skip the prompts:

$ scaffld new "Weather Bot" -t python-cli -a "Ada Lovelace" -d "A tiny weather CLI." --no-input --no-venv
weather-bot/
├── .github/
│   └── workflows/
│       └── ci.yml
├── .gitignore
├── .pre-commit-config.yaml
├── LICENSE
├── README.md
├── pyproject.toml
├── src/
│   └── weather_bot/
│       ├── __init__.py
│       └── cli.py
└── tests/
    └── test_cli.py
╭──────────────────────────────────── Done ────────────────────────────────────╮
│ Created 9 files in /tmp/weather-bot                                          │
╰──────────────────────────────────────────────────────────────────────────────╯

Next steps:
  cd weather-bot
  pip install -e ".[dev]"
  pytest

scaffld show python-lib prints the file tree a template would generate, without writing anything to disk.

The generated project is real and works immediately:

$ cd weather-bot && pip install -e ".[dev]" && pytest -q
...                                                                        [100%]
3 passed in 0.01s

$ weather-bot Fernando
Hello, Fernando!

Useful flags

Flag Meaning
-t, --type Template to use (scaffld list).
-a, --author Author name (defaults to SCAFFLD_AUTHOR, then git config user.name, then $USER).
--email Author email (defaults to SCAFFLD_EMAIL, then git config user.email).
-d, --description One-line project description.
-l, --license MIT, BSD-3-Clause, ISC, or none.
-o, --output Directory to create the project in (defaults to the current directory).
--python Minimum Python version for the generated project (3.N or 3.N.P).
--venv / --no-venv Create a .venv in the new project. On by default.
--no-input Never prompt — fail if a required value is missing (great for CI).
--force Write into a non-empty directory.

scaffld -V (or --version) prints the version and exits.

How it works

A template is just a directory:

my-template/
├── template.toml        # name, kind, description
└── files/               # the tree that gets rendered
    ├── pyproject.toml
    ├── src/{{ package_name }}/__init__.py
    └── ...

Both file contents and path segments are rendered, so a directory literally named {{ package_name }} becomes weather_bot/ on disk.

The rendering engine is deliberately small and has one property that matters for real projects: unknown {{ ... }} expressions are left untouched. That means a GitHub Actions file can contain ${{ matrix.python-version }} right next to a scaffld variable like {{ project_name }}, and only the latter is substituted — no escaping required. It also supports filters ({{ project_name | snake }}) and nestable conditionals ({% if has_license %}...{% endif %}).

Derived variables are computed once and kept consistent: give it "Weather Bot" and you get package_name = weather_bot, project_slug = weather-bot, a filled-in license, the year, and more. Names are transliterated to ASCII first, so "Café Búho" yields cafe_buho rather than a shredded caf_b_ho, and a name that collides with a Python keyword gets a trailing underscore (class → class_) so the package stays importable.

Custom templates

Point scaffld at your own templates by dropping them in ~/.scaffld/templates/ (or any directory listed in the SCAFFLD_TEMPLATES environment variable). A user template that shares a name with a built-in one shadows it, so you can override the defaults. Available variables include project_name, package_name, project_slug, author, author_email, description, license, python_version, and year.

Development

python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest

Part of the ferinazumaDEV ecosystem

scaffld is one of a family of small, focused open-source tools I build and maintain. If it saved you some project-setup time, a few of the sibling projects tackle neighbouring problems in the same practical, batteries-included spirit.

  • The GEO Handbook — the open reference on getting content cited by AI answer engines (ChatGPT, Perplexity, Google AI Overviews, Gemini, Copilot).
  • politeclient — a polite, bulletproof HTTP client for Python: retries with backoff, per-host rate-limiting, caching, and pagination.
  • typedout — reliable structured output from any LLM: schema-validated JSON with tolerant repair and retries.
  • webhook-replay — capture a webhook once, then replay it at your local app as many times as you need.
  • Hub & writing: zentimes.es.

By ferinazumaDEV.

License

MIT — see LICENSE.


Built by Fernando (@ferinazumaDEV).

Metadata

Release files for scaffld 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for scaffld 0.1.1
File Size Uploaded
scaffld-0.1.1.tar.gz 31.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for scaffld 0.1.1
File Interpreter ABI Platform
scaffld-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 64.2 kB

Release files / scaffld-0.1.1.tar.gz

Download URL scaffld-0.1.1.tar.gz
Size 31.7 kB
Tags Source
SHA-256 checksum
How to use checksums
7ebb77575d98b3db1dff4dd98697dac34aadf319307ed74188c2e28745ad4320
BLAKE2b-256 checksum
How to use checksums
6c93ba2761a86b04f6e46f04b908ea293a01249d712589458b1dfeca72151abc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.2

Release files / scaffld-0.1.1-py3-none-any.whl

Download URL scaffld-0.1.1-py3-none-any.whl
Size 32.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
de66a90eb59421cfb970d3e2788b395d48b6f49cccbf00569e1ae528d4a66afd
BLAKE2b-256 checksum
How to use checksums
0d01bababad4f9fec5f7ebc8072fc7de7ed704e09ebeb7037c6181b966d42cb7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.2

Release history Release notifications | RSS feed

0.1.2

2 release files

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page