Repository navigation
Troubleshooting
Usually uv is missing or can't reach the package index. Copier removes the half-made project on a failed task, so re-run with --skip-tasks, then run sh scripts/bootstrap.sh and read its error.
An update that stops part-way is incomplete: Copier has written the new template over your files but not put your edits back, and no conflict markers show it. Templates up to v0.1.20 ran scripts/bootstrap.sh during the update, so a failing uv sync or npm install stopped it there (#82). Don't commit the result. Reset with git checkout -- . && git clean -fd, then run uvx copier update --trust --skip-tasks and sh scripts/bootstrap.sh (Updating from the Template).
An update from v0.1.20 or earlier without --skip-tasks can delete files from .venv or node_modules and leave the directories. Delete the directory and run sh scripts/bootstrap.sh again.
The GitHub wiki's git repository exists only after its first page is created in the web UI. Enable the wiki, create any page, and re-run the job: it replaces that page.
The update changes .github/workflows/, and without the release GitHub App the workflow can't push those files ("refusing to allow a GitHub App to create or update workflow"). Run uvx copier update --trust --skip-tasks --conflict inline and then sh scripts/bootstrap.sh locally, push a branch and open the PR. Set up the App (Release Process) to stop this.
The GHCR package is still private, which is the default for a new package. Make it public in its package settings (Docker Images).
Runs on a PR opened by github-actions[bot] wait for a maintainer's approval, after every push to it. Approve them on the PR's Checks tab, or with gh api -X POST repos/<owner>/<repo>/actions/runs/<id>/approve. Approve only the runs for the PR's latest commit: a stale run approved later cancels the current one (cancel-in-progress). The release GitHub App avoids all of this.
GitHub never counts an author's approval, so if the only member of code_owners opens a PR, nobody can approve it. Give organisation admins (or yourself) bypass in main's ruleset, and merge with gh pr merge --squash --admin once CI is green. New projects' Contributing page says so. Contributing is project-owned, so an existing project gets this step only by copying it.
Those PRs were opened with GITHUB_TOKEN, which can't trigger workflows. Set up the release GitHub App (Release Process). Meanwhile, closing and reopening the PR by hand triggers CI.
The lock-refresh job didn't run, or was overwritten when release-please force-pushed the branch. Push to main again or re-run the Release workflow: it refreshes uv.lock after every Release PR update.
A reviewer adds the no-docs-needed label, and the check is skipped, which counts as passed. No such label? wiki.yml creates it on each push to main. A project updated before it did can update from the template, or run gh label create no-docs-needed once. If it fires on a path that is never user-facing, change [docs_touched] watch in project-template, not locally.
Code changed the settings, CLI or API: run uv run scripts/gen-wiki.py and commit. Never edit between the markers.
Before 0.1.5, gen-wiki.py rendered only the root app's commands, without positional arguments: a sub-app (app.add_typer(sub, name="grp")) showed as one grp entry. Take the template update, run uv run scripts/gen-wiki.py, and delete any hand-written table of sub-commands. The update makes generated section is stale fail until you do.
The app binds 127.0.0.1, which can't be reached through a published port. Before 0.1.5 the image used the app's default listen address. Take the template update, which sets <PREFIX>_LISTEN_HOST=0.0.0.0 in the image, and drop any project-side ENV for it from the Dockerfile (Docker Images).
The image sets <PREFIX>_LISTEN_HOST=0.0.0.0, and environment variables beat the config file. Pass -e <PREFIX>_LISTEN_HOST=... instead. <project> config shows where each value came from.
docs/wiki/Troubleshooting.md:5 MD012/no-multiple-blanks: before 0.1.7, a library project's Diagnostics section rendered empty, leaving two blank lines. The page is project-owned, so the update doesn't change it: delete one blank line, and write the section (how a user sees what the library is doing).
Run scripts/check-docs-secrets.sh docs: it runs the same markdownlint-cli2 version, globs and .markdownlint-cli2.yaml as CI. A common one is MD014, a $ prompt in a fenced block of commands without output: drop the $.
Since 0.1.9, the checks print one line when they pass. Run python3 scripts/check-wiki.py --verbose to list the warnings. Errors are always listed in full.
The template's pytest options gained -q and term-missing:skip-covered (quieter output on a pass), and your project changed the same line. Keep your options, and add those two.
Starlette 1.x builds its TestClient on httpx2. A service project's dev group now lists httpx2 instead of httpx; after copier update, run uv lock so the lock file follows. If you dropped the template's dev group, swap httpx for httpx2 yourself.
filterwarnings = ["error"] makes every warning a failure, so a deprecation shows up in the PR that brings it. Fix the cause (usually what the warning says to use instead). If it comes from a library you can't change yet, ignore that one warning in pyproject.toml, narrowly and with a reason, for example "ignore:Using `httpx` with:UserWarning" (the category must be the warning's real class or a parent of it: check where it is defined), and add a TODO.md line to remove it.
The coverage floor in addopts is for the whole unit suite: integration tests alone, or a few unit tests, can't reach it. Add --no-cov: RUN_INTEGRATION=1 uv run pytest -m integration --no-cov. copier update brings the fix to AGENTS.md, but Testing-Guide.md is your own page: add --no-cov to its commands yourself. TypeScript is unaffected: only npm test measures coverage.
A test vector or a documented sample (RFC 6455's Sec-WebSocket-Key, for example). Allow-list it in .gitleaks.toml (a [allowlist] regex, or the finding's fingerprint in .gitleaksignore), never by disabling the job. scripts/check-docs-secrets.sh secrets re-runs CI's scan locally, on committed history.
Grant the repository's Actions Admin access in the package settings, or add a PACKAGES_DELETE_TOKEN secret (delete:packages).
ruff's output depends on target-version (from python_version). For example, 3.14 formats except A, B: without parentheses. Template-owned scripts avoid version-dependent syntax; in project code, follow what ruff says for your minimum version.
project-template | The metalayerlab project template
GitHub β’ Releases β’ Changelog β’ Contributing
This wiki is generated from docs/wiki/ on every push to main: edits made here are overwritten. Change it with a pull request.
- π
copier updatekeeps every project in step - π·οΈ release-please: reviewed Release PRs and generated changelogs
- π A standardised, CI-checked wiki in every repo
- π€ One
AGENTS.mdfor Claude, Codex, Copilot, Gemini and Cursor - π³ Hardened Docker, Kubernetes and systemd manifests