CarrNexa's starting point for Python CLI projects. It keeps the setup lean, uses a namespaced src layout, and ships with the tooling we want by default: uv, Typer, Ruff, pytest, and pre-commit.
The goal is simple: start from something clean, consistent, and easy to grow instead of rebuilding the same scaffolding for every new project.
- A
carrnexa.*namespace package layout - A Typer CLI entrypoint with subcommand organization
uvfor environment management and dependency syncing- Ruff, pytest, and pre-commit for day-to-day quality checks
- A small example command you can keep, replace, or delete once your real CLI takes shape
- A
CHANGELOG.mdusing the Keep a Changelog format - A documented release process for CI, release preparation, and tag-based publishing
- Python: Tested on 3.12.10
- Git: Tested on 2.55.0
- PowerShell 7: Tested on 7.6.4
- uv: Tested on 0.11.24
Clone the repository:
git clone git@github.com:carrnexa/template-python-cli.git
cd template-python-cliSync dependencies:
uv syncFrom there, use uv run for the default workflow. It keeps the commands the same on Windows, Linux, and macOS, and avoids shell-specific activation steps in the common path.
uv run app --help
uv run app exampleDirect module execution also works:
uv run python -m carrnexa.app_name --helpIf you prefer to work inside the virtual environment instead of prefixing commands with uv run, use the command that matches your shell.
Unix shells:
source .venv/bin/activateWindows PowerShell 7:
.\.venv\Scripts\Activate.ps1Once the environment is active, the commands become:
app --help
app exampleInstall pre-commit, then copy the tracked post-commit hook into .git/hooks:
pre-commit install
cp hooks/post-commit .git/hooks/post-commitThe expected release flow uses CI on pull requests and pushes to main, then publishes releases from semantic version tags like v0.3.0.
The planned automated checks should cover release metadata validation, Ruff linting, Ruff formatting, and pytest. Release metadata validation makes sure the package version, lockfile version, tag, and changelog notes stay in sync.
Normal feature and bugfix pull requests should not bump the package version. User-facing changes should be recorded as small release-note fragments under changes/; release preparation later assembles those fragments into CHANGELOG.md, bumps the version, and opens a dedicated release-prep pull request.
For the full release workflow, including release-note fragments, release-prep pull requests, and tag-based publishing, see docs/release-process.md.
This template is intentionally close to a real CarrNexa project, so creating a new service or library is mostly a focused rename pass rather than generating a project from scratch.
At minimum, update these places:
project.nameinpyproject.tomldescriptionand repository URLs inpyproject.tomltool.uv.build-backend.module-nameproject.scriptssrc/carrnexa/app_name- Imports that still reference
carrnexa.app_name
The bundled example command is only there to verify the CLI wiring before you replace it with project-specific commands.