⚠️ TEMPLATE FILE - This contains template-specific patterns. After initialization, update for your project's needs.
The main application code lives in the [[MODULE_NAME]] directory (which can be renamed via make init). The default entrypoint is main.py for applications, but make init removes this file for library packages. Tooling metadata (pyproject.toml, uv.lock) defines project dependencies. Expect any future modules (tests, components, helpers) to sit alongside these files unless a new package directory is created. For applications, create an entrypoint file; for libraries, expose the package API through the module's __init__.py.
make init NAME=your-project: initialize the template with your project name (renames module and updates config).source .venv/bin/activate: activate the virtual environment (do this once per session).uv sync --group dev: install dependencies via uv.python main.py: run the main entrypoint (if present, for applications).pytest: run tests.make pytest: run the test suite.make lint: run ruff.
When cloning this template for a new project:
- Run
make init NAME=your-projectto rename the module and update config - Run
uv sync --group devto install all dependencies - Run
source .venv/bin/activateto activate the virtual environment - Start building your project!
Git worktrees allow working on multiple cards in parallel without branch conflicts. This is an optional workflow pattern that many projects don't use.
- Create a branch per card:
git switch -c card/short-slug - Add a worktree:
git worktree add ../project-<slug> card/short-slug - Work only in that worktree for the card; run tests there.
- Keep the branch updated:
git fetchthengit rebase origin/main(or merge). - When merged, remove it:
git worktree remove ../project-<slug> - Clean stale refs:
git worktree prune - WIP limit: 3 cards total in progress across all worktrees.
- Current target: 96% coverage threshold (configured in
pyproject.toml) - Always run
pytest --cov=[[MODULE_NAME]] --cov-report=term-missingto check missing coverage - When touching logic or input handling, ensure tests are added to maintain coverage
- Strategies for increasing coverage:
- Add tests for remaining uncovered edge cases
- Add tests for complex error handling paths
- Add tests for platform-specific code paths
Follow standard PEP 8 spacing (4 spaces, 100-character soft wrap) and favor descriptive snake_case for functions and variables. Retain the current pattern of dataclasses for typed data containers and keep public functions annotated with precise types. Prefer explicit helper names and guard callbacks with early returns rather than nesting.
Ruff configuration (from pyproject.toml):
- Line length: 100 characters
- Python version: 3.13
- Enabled rules: E, F, I, N, UP, B, C4, D, ANN401
- Ignored: D203, D213, E501
- Code comments are discouraged - prefer clear code and commit messages
A pre-commit hook is installed in .git/hooks/pre-commit that automatically runs:
- Check for type/linter ignores in staged files
- Run the shared lint script (
scripts/lint.sh)
The lint script runs:
- Python compilation check
- Ruff linting
- Any type usage check (ruff ANN401 rule)
- Pyright type checking
The hook will block commits containing # type: ignore, # noqa, # ruff: ignore, or # pylint: ignore.
To test the hook manually: make githook or bash scripts/lint.sh
- Run linting after each change:
make lintorbash scripts/lint.sh
- Use specific types instead of
Anyin type annotations (ruff ANN401 rule) - Run tests when you touch logic or input handling:
pytest
- Always write a regression test when fixing a bug.
- If you break something while fixing it, fix both in the same PR.
- Do not use in-line comments to disable linting or type checks.
- Do not narrate your code with comments; prefer clear code and commit messages.
- Keep helpers explicit and descriptive (snake_case), and annotate public functions with precise types.
- Avoid shell-specific shortcuts; prefer Python APIs and
pathlib.Pathhelpers.
- Always create a feature branch from
mainbefore making changes:git checkout -b feature-name- Use descriptive names like
fix-bugoradd-feature
- Push the feature branch to create a pull request
- After your PR is merged, update your local
main:git checkout maingit pull- Delete the merged branch:
git branch -d feature-name
- Automated tests live in
tests/and run withpython -m pytest(ormake pytest). - When adding tests, keep
pytestnaming liketest_example_function. - Always use appropriate fixtures from
conftest.pyfor testing dependencies.
- Use imperative, component-scoped commit messages (e.g., "Add feature X")
- Bundle related changes per commit
- PR summary should describe user impact and testing performed
- Attach screenshots when UI is affected