scaffld
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 git+https://github.com/ferinazumaDEV/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, asrc/layout,pytesttests that pass out of the box, a GitHub Actions matrix CI, a.pre-commit-config.yaml, a realLICENSE, and a sensible.gitignore. - Three built-in templates —
python-lib,python-cli, andpython-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/templatesand it shows up instantly. Templates are just atemplate.tomlplus afiles/tree. - Scriptable —
--no-inputmakesscaffldbehave in CI and Makefiles. - Zero-config virtualenv — optionally creates
.venvfor the new project.
Install
pip install git+https://github.com/ferinazumaDEV/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).
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file scaffld-0.1.0.tar.gz.
File metadata
- Download URL: scaffld-0.1.0.tar.gz
- Upload date:
- Size: 31.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5f54c88573bfae18d9e3821ed25ff5bf7eef99084b3bd463360eea5562cb4734
|
|
| MD5 |
90d4844902eb01186ce46bc0a0d23170
|
|
| BLAKE2b-256 |
1a86b30d36db6166075528df5072ea60c9f8c79a5e606ef59dd34b6e887ff768
|
File details
Details for the file scaffld-0.1.0-py3-none-any.whl.
File metadata
- Download URL: scaffld-0.1.0-py3-none-any.whl
- Upload date:
- Size: 32.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
286f0a50e97a1beb1686704b7734c4241ea00abb60d8fcb0cc5b48ae2aa56b41
|
|
| MD5 |
ea8b2b8fc027791b01bb5b03146c1236
|
|
| BLAKE2b-256 |
ea9f63aa99c25ae2c0d4f3748f3c3b4746b7f48dca65a2acd9bfa97a1a110576
|