newstack
Scaffold a new project on any popular stack — and every starter it emits is proven green in CI.
$ newstack new python-lib ~/code/mylib
newstack 0.1.0 · python-lib → /home/you/code/mylib
created 8 files
git initialised on main, first commit made
next:
cd /home/you/code/mylib
uv sync
uv run pytest
Why this exists
cookiecutter, copier, yeoman, degit, npm create … and gh repo create --template
all solve part of the problem. Two things are still missing in practice:
- One tool for every stack. Python templates are Python-only, JS templates are
JS-only, and
gh repo create --templateclones a whole repository with no variables. - A guarantee that the template still works. Templates rot silently. You find out the starter is broken after you have already started building on top of it.
newstack fixes both. It is one zero-dependency CLI that carries a curated stack
registry, and every stack in that registry is generated and checked on every push
(newstack check --all in CI). If a starter breaks, the badge goes red — not your
first day of work.
Install
uvx newstack list # run without installing
uv tool install newstack # or put it on your PATH
pipx install newstack # any of the usual runners works
From a clone:
git clone https://github.com/DawnofGenX/newstack && cd newstack
uv sync && uv run newstack list
Use
newstack list # what is available, and what each stack needs
newstack new react-vite-ts ~/code/app
newstack new fastapi ~/code/api -d "Billing service" --author "Your Name"
newstack new python-lib ~/code/lib --dry-run # preview, write nothing
newstack new python-cli ~/code/tool --github # create the repo and push it too
newstack adopt ~/code/old-project --dry-run # retrofit CI/lint onto existing code
newstack check --all # prove every stack on this machine
newstack doctor # which toolchains do I have?
Every command takes --json where it makes sense, so the tool is scriptable.
newstack new renders variables, initialises git with a first commit, and (with
--github) creates the remote repository and pushes — one command from empty
directory to CI-ready project.
Stacks
| Stack | What you get | Toolchain |
|---|---|---|
python-lib |
src layout, hatchling build, pytest, ruff, 4-version CI matrix | uv |
python-cli |
console entry point on argparse, zero runtime deps, tested CLI | uv |
fastapi |
typed JSON API, pydantic models, TestClient tests, Dockerfile | uv |
django |
Django 6.1 app: config/core split, SQLite, pytest-django, migration drift check | uv |
react-vite-ts |
React 19 + Vite + TS, Vitest + Testing Library, typecheck + build | node, npm |
node-express-ts |
Express 5 API, typed handlers, supertest tests | node, npm |
svelte-kit-ts |
SvelteKit + TS, Svelte 5 runes component, Vitest, static adapter build | node, npm |
go-cli |
stdlib-only Go CLI: flag parsing, table tests, vet/test/build gates |
go |
rust-cli |
std-only Rust CLI: lib+bin split, fmt/clippy/test/release-build gates | cargo |
static-site |
HTML/CSS/JS page, node:test suite, GitHub Pages deploy workflow |
node |
Each generated project ships its own .github/workflows/ that is ready to run, plus a
README, an MIT licence and a .gitignore.
Adopting an existing project
Most projects do not start from a scaffold. adopt retrofits a stack's infrastructure
onto a directory that already has code — and it is additive by construction: an existing
file is never opened for writing.
$ newstack adopt ~/sites/analytics-dashboard
newstack 0.3.0 · adopt → /home/you/sites/analytics-dashboard
stack static-site (auto-detected)
added 2 files
+ .github/workflows/deploy-pages.yml
+ .gitignore
tests not copied — rerun with --with-tests if you want starter tests
- Detection reads the project's own markers (
go.mod,Cargo.toml,manage.py, the dependencies inpyproject.toml/package.json, a bareindex.html). If two stacks match, it prints the candidates and exits 2 rather than guessing;--stackoverrides. - Scope: workflows,
.gitignore, and per-stack lint/type config only. It will not copy a README, a LICENSE, apyproject.toml, or source files — those carry your project's identity, not infrastructure. - Merges are reported, not attempted. If your
pyproject.tomlneeds the stack's[tool.ruff]block, adopt says so and leaves the file alone. --dry-runprints the same report without writing. Re-running is a no-op.--with-testsadditionally copies the stack's starter tests — experimental, because those tests import the sample module and usually need adapting to your code.
The green guarantee
A template is only as good as its last successful run, so newstack treats
verification as a first-class command:
$ newstack check --all
django PASS 1.5s 5 step(s)
fastapi PASS 1.4s 3 step(s)
go-cli PASS 0.3s 3 step(s)
node-express-ts PASS 6.1s 3 step(s)
python-cli PASS 0.5s 4 step(s)
python-lib PASS 0.5s 3 step(s)
react-vite-ts PASS 5.5s 4 step(s)
rust-cli PASS 0.5s 4 step(s)
static-site PASS 0.1s 3 step(s)
svelte-kit-ts PASS 7.1s 4 step(s)
(Real timings from a warm package cache — a cold run takes about a minute because
npm install and uv pip install have to fetch packages.)
check generates the stack into a throwaway directory, runs the commands listed in its
manifest (install → lint → test → build), reports per-step timings, and deletes the
directory unless you pass --keep. The same command runs in this repository's CI, once
per stack, on every push.
How it compares
| newstack | cookiecutter | copier | yeoman | degit / npm create |
gh repo create --template |
|
|---|---|---|---|---|---|---|
| Cross-language stacks in one tool | yes | no | no | partial | no | n/a |
| Runtime dependencies | 0 | Python | Python + git | Node | Node | gh |
| Generated starter verified in CI | yes, per stack | no | no | no | no | no |
| Template updates after generation | no (roadmap) | no | yes (copier update) |
no | no | no |
| Creates the git repo + remote | yes (--github) |
no | via hooks | no | no | yes |
Pick copier if you need copier update three-way merges against a single template you
own. Pick newstack when you want the same standard applied across several languages
without maintaining one template per stack.
Adding a stack
A stack is a directory with a manifest and a template tree. The manifest carries four
optional keys beyond the basics — detect (how a directory is recognised as this stack),
detect_fallback (a generic stack that must lose to a specific match), and the adopt /
adopt_tests allow-lists used by newstack adopt:
src/newstack/data/stacks/my-stack/
├── stack.json
└── template/
├── README.md
└── ... # {{ project_name }}, {{ package_name }}, {{ npm_name }},
# {{ title }}, {{ description }}, {{ author }}, {{ email }},
# {{ year }}, {{ date }}
{
"name": "my-stack",
"title": "My stack",
"language": "python",
"blurb": "One line shown by `newstack list`",
"requires": ["uv"],
"next_steps": ["cd {path}", "uv run pytest"],
"verify": [
{"name": "test", "cmd": "uv run pytest", "tools": ["uv"], "timeout": 600}
],
"detect": [{"file": "pyproject.toml", "contains": "my-framework"}],
"adopt": [".github/workflows/ci.yml", ".gitignore"],
"adopt_tests": ["tests/test_smoke.py"]
}
adopt entries must exist in the template and must never be an identity file
(README.md, LICENSE, pyproject.toml, package.json, go.mod, Cargo.toml) — a
test enforces both rules.
{{! escapes a literal {{, and ${{ ... }} (GitHub Actions) is left untouched.
Point NEWSTACK_STACKS at a directory of your own stacks to use private ones — same
manifest format, no fork required.
Design
- Zero runtime dependencies.
argparseand the standard library only, souvx newstackstarts instantly and works offline. - Templates are plain files. No Jinja, no DSL — a reviewer can read a template and know exactly what gets written.
- Verification is a product feature, not an afterthought.
checkis the same code path CI uses.
Roadmap
newstack update— re-apply upstream template changes to an existing project.- More stacks: Vue, Next.js, Flask.
--license apache-2.0|bsd-3and other variable choices beyond the current defaults.
Licence
MIT — see LICENSE.
Metadata
Release files for newstack 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| newstack-0.3.0.tar.gz | 49.1 kB | Without provenance | Details for newstack-0.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| newstack-0.3.0-py3-none-any.whl | Python 3 | none | any | Details for newstack-0.3.0-py3-none-any.whl |
Total release size: 135.4 kB
Release files / newstack-0.3.0.tar.gz
| Download URL | newstack-0.3.0.tar.gz |
|---|---|
| Size | 49.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
13028aee01c383c1686a3f4a8c4470a2ae50059e6d0ec94b460c00bcd152dc1d
|
|
BLAKE2b-256 checksum How to use checksums |
a1782ddb7f7d3557d7a3e5864fb5a6c8d5d6832ba258740441004a0527bd5e7d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / newstack-0.3.0-py3-none-any.whl
| Download URL | newstack-0.3.0-py3-none-any.whl |
|---|---|
| Size | 86.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e8b1d19cdda12ccaa49a103770f453bef31b13992c82e4dd28a3b95bef6099e5
|
|
BLAKE2b-256 checksum How to use checksums |
9ae985eeb8d7619bca2738986e9bf5ab7e27dfaf939bd70727b0950f6772f024
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for newstack 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.