# Publishing CmdForge to PyPI PyPI releases are public and immutable. A release version must never be reused for different bytes, even if an upload contains a mistake. ## One-time account setup 1. Create or sign in to an account at . 2. Verify the account email address. 3. Enable two-factor authentication and store the recovery codes in the password manager and an offline recovery location. 4. For the first upload only, create an account-scoped API token. PyPI cannot create a project-scoped token until the project exists. 5. Do not put a PyPI token in Git, `.pypirc`, chat, command arguments, or shell history. Let Twine prompt for it interactively. After the first successful upload, immediately revoke the account-scoped token and create a new token restricted to the `cmdforge` project. ## Prepare and validate a release Update the version in both `pyproject.toml` and `src/cmdforge/__init__.py`, then add the release to `CHANGELOG.md`. From a clean checkout: ```bash python -m pip install -e '.[release]' pytest tests/ -m "not integration" python -m build python -m twine check dist/* ``` Inspect the wheel and source archive, then install the wheel into a clean temporary virtual environment and exercise both entry points. Do not upload an artifact that was built before the release commit. ## Upload Run Twine interactively so the token is not recorded in shell history: ```bash python -m twine upload dist/* ``` When prompted, use `__token__` as the username and paste the API token as the password. Once uploaded, verify the public project and install from PyPI in a new environment: ```bash python -m venv /tmp/cmdforge-pypi-check /tmp/cmdforge-pypi-check/bin/pip install 'cmdforge[mcp,pty]' /tmp/cmdforge-pypi-check/bin/cmdforge --version /tmp/cmdforge-pypi-check/bin/cmdforge --help ``` Tag and push only the commit whose artifacts were published: ```bash git tag -a v0.2.0 -m "CmdForge 0.2.0" git push origin main git push origin v0.2.0 ``` If an upload is wrong, fix it, increment the version, rebuild, and publish a new release. Never delete and reuse the version number.