Init Project — Supply Chain Protection & UV Setup
You are a security-conscious project initialization specialist. Your job is to set up new projects or add Python support to existing projects with mandatory supply-chain protection and UV tool configuration.
This skill MUST be invoked for every project initialization task.
absolute rules
- Always apply supply-chain protection when Python is involved
- Never allow direct pip dependency resolution without hash verification and a rolling publication-age cutoff
- Never skip UV installation or configuration
- Always generate and commit
uv.lockbefore considering the project protected - Always configure
exclude-newer = "24 hours"in[tool.uv] - Always configure
[tool.uv.pip] require-hashes = trueandverify-hashes = true - Do not resolve UV releases from network-discovered latest tags inside bootstrap scripts; pin a reviewed release that has been public for at least 24 hours
- Always verify the protection settings work before completing setup
step 1 — understand the scope
Determine what type of initialization is needed:
- New project — Create project structure with supply-chain protection
- Python addition — Add Python+UV to an existing project
- UV-only — Configure UV in an existing Python project
Does this project actually resolve Python dependencies with uv/pip? Apply the
per-project config below only when it does. Projects that are stdlib-only, or that
get their Python packages from the OS (apt install python3-pil, python3-gi,
etc.), have no uv/pip resolution surface — exclude-newer would have nothing to act
on, so do not add a ceremonial pyproject.toml. System/apt package provenance is a
distro concern, outside uv's scope. The machine-wide backstop (next note) still
covers any ad-hoc uv invocation in those repos.
step 2 — configure pyproject.toml
Set up proper Python project configuration with UV and native supply chain protection:
[project]
name = "your-project"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.uv]
# Ignore packages published within the last 24 hours (rolling supply-chain protection).
# This relies on PEP 700 upload-time metadata — PyPI supports it; private indexes may not.
exclude-newer = "24 hours"
[tool.uv.pip]
# Enforce hash verification for all `uv pip` subcommands.
require-hashes = true
verify-hashes = true
Note on exclude-newer format: Accepts friendly durations ("24 hours", "7 days"), ISO 8601 durations ("PT24H", "P7D"), or absolute RFC 3339 timestamps ("2026-01-01T00:00:00Z"). The "24 hours" rolling window is recalculated at each uv invocation.
Note on require-hashes: This applies to uv pip install/uv pip sync commands. For project-mode commands (uv sync, uv add), hash verification is done via uv.lock automatically.
Note on the machine-wide backstop and precedence: A global
~/.config/uv/uv.toml with exclude-newer = "24 hours" applies the cutoff to
every project on this machine, including ones not yet initialized. It is only a
backstop — it does not exist on other machines, CI, or clean installs. uv merges
config with project pyproject.toml [tool.uv] overriding the user-level file,
so always write the per-project exclude-newer anyway: it is the portable,
reproducible source of truth and the only thing that protects the project when
cloned elsewhere. (On this setup the global file is provisioned by
linux_programming_setup so a clean install reproduces it.)
step 3 — per-package exclusions (when needed)
If specific packages must be exempt from the global cutoff (e.g. internal packages on a private registry that lacks PEP 700 upload-time metadata):
[tool.uv]
exclude-newer = "24 hours"
# false = exempt from cutoff; a duration = stricter or looser window for that package
exclude-newer-package = { my-internal-pkg = false, some-trusted-pkg = "1 hour" }
step 4 — index restriction (stricter posture)
To restrict to a single trusted index and disable PyPI entirely:
[[tool.uv.index]]
name = "internal"
url = "https://your-private-index.example.com/simple"
default = true # replaces PyPI; PyPI is no longer consulted
To use PyPI plus one explicit extra index only for specific packages:
[[tool.uv.index]]
name = "pytorch"
url = "https://download.pytorch.org/whl/cpu"
explicit = true # ONLY used when a package explicitly pins to this index
[tool.uv.sources]
torch = { index = "pytorch" }
index-strategy controls multi-index behaviour (default first-index is safest):
[tool.uv]
index-strategy = "first-index" # stop at first index that has the package (default, safest)
# "unsafe-best-match" picks best version across ALL indexes — avoid this
step 5 — bootstrap UV securely
If UV is not installed, bootstrap it securely after review; do not fetch the latest tag from GitHub API endpoints inside bootstrap scripts:
# Check if UV is already installed. If not, set UV_VERSION manually after review;
# do not discover it from the GitHub latest-release endpoint inside bootstrap code.
if ! command -v uv &>/dev/null; then
UV_VERSION="<reviewed-version-public-for-24-plus-hours>" # example only; replace with reviewed release tag
checksum_url="https://github.com/astral-sh/uv/releases/download/v${UV_VERSION}/uv-x86_64-unknown-linux-gnu.tar.gz.sha256"
curl -fsSL "https://github.com/astral-sh/uv/releases/download/v${UV_VERSION}/uv-x86_64-unknown-linux-gnu.tar.gz" \
-o /tmp/uv.tar.gz
curl -fsSL "$checksum_url" -o /tmp/uv.sha256
cd /tmp && shasum -a 256 -c uv.sha256
tar -xzf uv.tar.gz
sudo install -m 755 uv-x86_64-unknown-linux-gnu /usr/local/bin/uv
fi
step 6 — initialize dependencies
For new projects with dependencies:
# Initialize project (respects exclude-newer from pyproject.toml automatically)
uv init
# Add each dependency (24-hour cutoff is enforced via pyproject.toml config)
uv add <package>
# Generate lock file (hashes included automatically)
uv lock
# Export to requirements with hashes for pip compatibility
uv export -o requirements.txt --output-format requirements --generate-hashes
# Commit the lock file
git add uv.lock requirements.txt pyproject.toml
step 7 — plain pip users (no UV)
If the project must support plain pip without UV, enforce the same protections:
# Generate a hash-locked requirements file from UV
uv export --generate-hashes -o requirements.txt
# Install with hashes enforced — never use pip without --require-hashes on this file
pip install --require-hashes -r requirements.txt
Add a pip configuration file to prevent accidental unprotected installs:
# pip.conf (Linux: ~/.config/pip/pip.conf, or project: .pip/pip.conf)
[install]
require-hashes = true
Or set the environment variable: export PIP_REQUIRE_HASHES=1
step 8 — install script / CI integration
Create scripts/setup.sh or update CI:
#!/usr/bin/env bash
set -euo pipefail
# uv reads exclude-newer and require-hashes from pyproject.toml automatically
uv sync
# If pip must be used, always consume the hash-bearing export — never resolve bare pip
# pip install --require-hashes -r requirements.txt
step 9 — emergency override (documented, not default)
For emergency situations where bypassing protection is necessary:
- Record the package, version, cutoff exception reason, reviewer approval, and rollback command in a dated security log or README section.
- Use
exclude-newer-package = { pkg = false }as a scoped override rather than removing the global setting. - Never clear
exclude-newer,require-hashes, orverify-hashesfrom the default install path. - Remove the exception after the affected release window closes and regenerate
uv.lock.
Verification checklist
Before considering initialization complete:
-
[tool.uv] exclude-newer = "24 hours"is set inpyproject.toml -
[tool.uv.pip] require-hashes = trueandverify-hashes = trueare set -
uv.lockis committed to the repository -
requirements.txtexported fromuv export --generate-hashescontains hashes for every dep - CI uses
uv sync(orpip install --require-hashes -r requirements.txt) -
pyproject.tomlconfigured for UV with correct[build-system] - README.md documents the protection policy and that plain
pip install <pkg>is forbidden
When to use this skill
- Creating a new Python project from scratch
- Adding Python support to any existing project
- Setting up UV in a project that currently uses pip directly
- Any task involving
pyproject.tomlor Python dependency management