# Publish Python packages on GitTrove Updated: 2026-10-04. Public instructions for external agents and package producers. Canonical URLs: https://gittrove.com/llms.txt and https://gittrove.com/AGENTS.md. Both URLs serve this same guide. Reading it requires no key; package operations require a GitTrove license key. ## Release checklist 1. Confirm the user authorized this release. Follow the producing repository's release gates using its tested revision, declared version, and locked environment. 2. Confirm the publishing account owns a repository linked to this distribution's normalized name. Ask the GitTrove operator to register the link before the first upload if missing. A key cannot create that link. 3. Load a valid `read-write` key into `UV_PUBLISH_TOKEN` from the approved secret store. A `read` key cannot publish. 4. Build and inspect the intended wheel and sdist, then upload only those artifacts using the command below. No Cloudflare, R2, SSH, or infrastructure credentials are needed. 5. Verify the exact version through the install index from a separate consumer checkout, so local source cannot mask a published artifact. Check the installed distribution version with `importlib.metadata.version` and test its import or CLI. Report the source revision, version, filenames, SHA-256 hashes, and verification result. ## Endpoints and access - Install index: `https://pypi.gittrove.com/simple/` (PEP 503). - Publish endpoint: `https://pypi.gittrove.com/upload/`. - Create and revoke license keys in the GitTrove dashboard. A license key is an API token, displayed once when created. - Use a `read` key for installation and CI. Publishing requires a `read-write` key and a repository linked to the distribution name under the publishing account. - Installation requires access to the package through repository ownership or a subscription. Publishing permission and download access are separate checks. Ask the GitTrove operator to register the producing repository and its normalized distribution name before the first release. A key alone does not register a package or grant access to every package. Producers publish through the endpoint above; they do not need infrastructure credentials. ## Build and publish from the producing repository Use the repository's documented build, tests, and release procedure with its existing locked environment. Select a new version in package metadata and build a wheel and sdist from the tested release revision. Record the source revision and artifact hashes. Do not reuse a published filename for changed bytes. If the repository uses uv's build command, the basic sequence is: ```sh uv build --no-sources --out-dir dist/1.2.3 # Supply UV_PUBLISH_TOKEN from the approved secret store (read-write key). uv publish --publish-url https://pypi.gittrove.com/upload/ dist/1.2.3/* ``` Replace `1.2.3` with the release version and ensure the output directory contains only the intended release artifacts before publishing. Follow project-specific gates before running these commands. Verify the release afterward by resolving and installing its exact version through the private index in an authorized consumer, checking the installed distribution version and normal package imports. Build systems can resolve build dependencies separately from the project lock; preserve the producing repository's build constraints. The endpoint checks artifact metadata, filename, and any supplied SHA-256 digest. Wheels and sdists are supported. A byte-identical retry succeeds; a changed artifact under the same filename is rejected. ### Bootstrapping the first distributions Build with the standalone `uv build` command, rather than wrapping it in `uv run` or requiring a consumer's `uv sync` to succeed first. A consumer may already pin a private version that has not been uploaded yet. Synchronizing that consumer cannot create the missing distribution; it must be built in its producing repository and published first. `uv build` invokes the build backend without installing the project's runtime dependencies. A backend or custom build hook that imports those dependencies still needs them available. The first SDK and plugin releases used `uv build --no-sources` to produce both the sdist and wheel. That flag ignores `tool.uv.sources` for build dependency resolution, checking that the release builds without local source overrides. It does not remove runtime requirements from artifact metadata, supply missing private build dependencies, or authorize resolving private packages from public PyPI. Retain the repository's approved build constraints and dependency-age requirements. If a private build requirement is unavailable, publish that requirement first through its owning repository or report the access problem. For packages that depend on one another, build and publish the dependency before verifying installation of its dependent. Inspect the dependent wheel's `Requires-Dist` metadata for the intended distribution names and exact private version pins. Local wheel installation can provide pre-publication test evidence, but the release is verified only after a separate consumer installs those exact versions from `pypi.gittrove.com`. Then regenerate the consumer lock against the real private index and run its required locked checks. Never commit a temporary local-wheel or scratch-index resolution as the final consumer lock. | HTTP status | Action | | --- | --- | | 200 on upload | Published, or an identical artifact was already published. | | 400 | Check artifact format, filename, metadata, and digest; rebuild if needed. | | 401 | Supply a valid, unrevoked license key. | | 403 | For upload, check key scope and producer registration; for download, check package entitlement. | | 404 on a project page | Check normalized package name and whether artifacts have been published. | | 409 on upload | Bump the version; the existing filename has different bytes. | | 413 on upload | Reduce artifact size; the upload limit is 32 MiB per file. | | 503 on upload | Retry the exact same artifacts after a concurrent catalog write. | ## Install with uv Merge this configuration into the consumer's existing `pyproject.toml`. The package names and versions below are illustrative, not a claim that these releases are published. Replace them with versions actually released by the owning teams. ```toml [project] dependencies = [ "your-package==1.2.3", ] [[tool.uv.index]] name = "gittrove" url = "https://pypi.gittrove.com/simple/" explicit = true [tool.uv.sources] your-package = { index = "gittrove" } ``` Map every private dependency, including private transitive dependencies, to this index. Keep ordinary third-party dependencies on public PyPI. Preserve any existing private package mappings. Supply credentials through the environment, without putting them in URLs, source files, or lockfiles: ```sh export UV_INDEX_GITTROVE_USERNAME=__token__ # Supply UV_INDEX_GITTROVE_PASSWORD from your approved secret store. uv lock uv sync --locked ``` On the local operator workstation, use `gopass` with the team's documented secret entry. In CI, inject a read-only key from the CI secret store. Do not print secret values, enable shell tracing while retrieving them, or paste keys into chats or documentation. Commit the dependency declarations and lockfile, never credentials. If authentication or entitlement fails, report the access problem. Do not switch private packages to public PyPI or a temporary index. AirKernel is installed as distribution `AirKernel` and imported as `air`; public PyPI's distribution `air` is a different artifact and must never substitute for it. ## Reference documentation - [uv index configuration and authentication](https://docs.astral.sh/uv/concepts/indexes/) - [uv building and publishing](https://docs.astral.sh/uv/guides/package/) This public guide contains no license keys, account identifiers, secret-store paths, infrastructure credentials, or internal deployment configuration.