-
Notifications
You must be signed in to change notification settings - Fork 1
releasing
How to cut a new version of eVi.
-
PyPI Trusted Publishing. On https://pypi.org → Manage → Publishing,
add a pending publisher for the
evi-assistantdistribution (the import package and CLI stayevi; only the PyPI name isevi-assistant) pointing at this repo'srelease.ymlworkflow. No API tokens required. -
Docker Hub / GHCR (optional). If you want to push the image too,
add
DOCKER_USERNAME/DOCKER_TOKENsecrets and a job torelease.yml(not enabled by default — see Roadmap below).
# 1. Bump the version in two places (they're tripwired by the release CI):
# pyproject.toml → [project] version
# evi/__init__.py → __version__
#
# 2. Update CHANGELOG.md — add a section under the new version with the
# notable changes. Phase memory ($CLAUDE_HOME/.claude/.../project_evi.md)
# is a good source of truth.
#
# 3. Commit, tag, push.
git add pyproject.toml evi/__init__.py CHANGELOG.md
git commit -m "release: 0.8.0"
git tag v0.8.0
git push origin main --tagsThe release.yml workflow:
- Verifies the git tag matches both
pyproject.toml's version andevi/__init__.py's__version__(fails on any drift). - Installs the package + all useful extras.
- Runs the full test suite.
- Builds sdist + wheel via
python -m build. - Publishes to PyPI via Trusted Publishing (OIDC — no API token).
- Keyless (OIDC) sigstore-signs the artifacts and creates a GitHub release
with auto-generated notes + attached artifacts (wheel/sdist +
*.sigstore.json).
If anything fails before publish, fix it on a new commit and retag with a
patched version (v0.8.1). Don't re-push the same tag — GitHub releases
get confused and PyPI rejects duplicates.
# Test
.venv/Scripts/python -m pytest -q --timeout=30
# Lint
.venv/Scripts/python -m ruff check evi tests scripts
# Build
.venv/Scripts/python -m build
# Outputs to dist/. Both sdist + wheel should appear.
# Smoke-test the wheel in a fresh venv:
python -m venv /tmp/wheel-check
/tmp/wheel-check/bin/python -m pip install ./dist/evi_assistant-X.Y.Z-py3-none-any.whl
/tmp/wheel-check/bin/evi --versionThe Tauri desktop app versions independently of the Python package
(desktop/src-tauri/tauri.conf.json → version, currently 1.0.0), so it
has its own workflow — .github/workflows/desktop-release.yml — driven by
desktop-v* tags, not the PyPI v*.*.* tags above.
# Bump desktop/src-tauri/tauri.conf.json "version" first if needed
# (keep Cargo.toml / package.json in lockstep), then:
git tag desktop-v1.0.0
git push origin desktop-v1.0.0The workflow (Windows / macOS / Linux matrix, fail-fast: false):
- Freezes the practical-tier sidecar in an isolated
.venv-build(build-sidecar.{ps1,sh}) and runsevi-server --check. - Builds the standalone app via
tauri-actionwith--config src-tauri/tauri.standalone.conf.json(ships the onedir sidecar throughbundle.resources). - Creates a non-draft (published) GitHub release for the tag and attaches
the minisign-signed installers (
.msi/-setup.exeon Windows,.dmg/.appon macOS,.deb/.rpm/.AppImageon Linux) plus a generatedlatest.jsonfor the in-app updater. Also uploads them as workflow artifacts, so a manualworkflow_dispatchrun (no tag) still produces downloadables.
Caveats:
- Installers carry a minisign signature (for the in-app updater), but are not OS code-signed — Windows SmartScreen and macOS Gatekeeper still warn on first run. Authenticode/Apple notarization is still TODO (see Roadmap below).
- All three OSes are verified end-to-end as of the desktop-v1.0.0 matrix
(2026-07-01): the Windows / macOS / Linux jobs all built and published signed
installers +
latest.jsonto the public release.
The desktop app self-updates directly from the public evi-assistant/evi-ai
GitHub releases. On launch the Rust shell checks
releases/latest/download/latest.json, and if a newer signed build exists it
downloads, installs, and restarts. Opt out with EVI_AUTO_UPDATE=0.
-
No separate release channel. Because the repo is public,
desktop-release.ymlattaches the signed installers +latest.jsonstraight to the repo's own releases and the updater reads them there — no mirror repo orRELEASES_TOKENneeded. (Historically, while the repo was private, amirrorjob copied assets to a separate public releases channel; that's been removed.) -
Signing keys. The updater only installs bundles signed with our key. The public key lives in
tauri.conf.json(plugins.updater.pubkey); the private key + its password are repo secretsTAURI_SIGNING_PRIVATE_KEYandTAURI_SIGNING_PRIVATE_KEY_PASSWORD, consumed bydesktop-release.yml. A local backup is in~/.evi/evi-updater.key(+.pub) and~/.evi/evi-updater.pass— keep these safe; losing them means no client can verify future updates (you'd have to ship a new pubkey + re-onboard). -
Cutting an updatable release. Bump
desktop/src-tauri/tauri.conf.jsonversion(andCargo.toml/package.jsonto match), then push adesktop-v<version>tag.createUpdaterArtifacts: truemakes the build emit the.sigfiles;tauri-action(with the signing env) attaches them plus a generatedlatest.jsonto the release. The updater compares the running app's version tolatest.json, so the version must increase for clients to update. -
Rotating the key.
npx tauri signer generate -w ~/.evi/evi-updater.key -f, update the pubkey intauri.conf.json, and reset the two repo secrets (gh secret set …). Clients on the old pubkey won't auto-update across the rotation — they'll need a manual reinstall once. -
OS code-signing is separate (and still TODO): the updater's minisign signature is not Authenticode/Apple notarization, so SmartScreen/Gatekeeper still warn until those are added.
The CI workflow doesn't push images by default. To do it manually after a release:
docker build -t evi:0.8.0 .
docker tag evi:0.8.0 evi:latest
# Push to GHCR or Docker Hub from here.The Dockerfile is set up for the headless web-server use case — pair it
with docker-compose.yml for an Ollama + eVi stack out of the box.
Loose semver:
- 0.x.0 minor — new features. We're here.
- 0.x.y patch — bug fixes, polish, no surface changes.
- 1.0.0 — when the surface is stable enough that breaking changes warrant a deprecation path. Not there yet.
Until 1.0, breaking changes are allowed in minor versions. Call them out
clearly in the CHANGELOG under a ### Breaking heading.
- Optional Docker push step in
release.yml(commented out for now). - macOS/Windows code-signing for the Tauri desktop bundle — the build
pipeline now exists (
desktop-release.yml); signing the artifacts (so SmartScreen/Gatekeeper don't warn) is the remaining gap. Needs an Authenticode cert (Windows) and an Apple Developer ID (macOS), wired intotauri-actionvia its signing inputs / env.
Generated from docs/releasing.md — edit there, not here.
Start here
Guides
- Architecture
- [[Agent SDK (
evi.sdk)|sdk]] - SDK coverage + borrowable features
- Multi-machine setup
- Self-update design (Phase 29 proposal)
- [[Self-build — developing and building eVi with eVi|self-build]]
- Development notes
- Releasing
- Desktop bundling
- Code signing policy
- Surface parity — CLI ↔ Web ↔ Desktop
- eVi vs Claude Code — feature comparison
- Future integrations — backlog
- Roadmap
Feature deep-dives
- eVi feature guides
- Agents & Orchestration
- Recipes, Routines, Scheduled tasks, Channels
- Evals & LLM-as-judge
- Content Guardrails
- Hooks (tool + lifecycle, command/url)
- MCP (client + serve)
- Memory & Context management
- Observability (OpenTelemetry, stats, crash reports)
- Permissions & Sandbox
- Plugins & Marketplace
- Sessions, Resume, Handoff, Checkpoints
- Skills
- Slash commands
- Structured Outputs & Batch
- Ultracode
- Voice (TTS engines, STT, AutoSpeaker)
- Web & Desktop (settings, multi-user, deep links, updater)