Updating & Uninstalling
Updating
Update to the latest version with a single command:
minerva update
The default Linux/macOS install one-liner also works on an existing installation:
it detects the installed engine and delegates to minerva update, preserving the
same locks, snapshots, running-process checks, and companion-package updates.
Explicit installer options retain the installation/repair flow. If the runtime is
missing, use bash install.sh --skip-setup from a downloaded installer to repair
it rather than bypassing an active update.
All interfaces share one product release version. After updating the engine, Minerva installs the signed VSIX through the editor CLI and applies or opens the native desktop installer for detected installations. The TUI and dashboard ship with the engine. An app that is closed can receive an on-disk update; an older running window must restart before its update is active.
minerva release status
The result lists installed and running versions, pending components, failed installations, and required restarts. A missing editor CLI, unavailable native package, required OS permission, or interrupted update remains explicit. Reopen the interface and choose Update Minerva to retry. Desktop restart preserves the current draft and conversation reference. The public website offers a refresh notice when its loaded version is older than the published release.
For the first upgrade from an engine older than the unified updater, run
minerva update again after the engine upgrade, or run minerva release apply.
Current desktop and editor releases run this as one coordinated transaction.
An update already in progress suppresses new update actions until it finishes.
The publish, notify, update workflow
Editing source does not change the published release. A release must first be versioned, built, verified, signed, and published. All installed interfaces then check that release channel; closed applications check when they next open. The classic CLI also checks while idle, without changing your conversation.
- CLI and TUI: update the engine with
minerva update; restart the old session. - VS Code and desktop: use Update Minerva. Finish any native installer or permission prompt, then reload or restart when requested. A running installer is shown as Installer running, and retries do not open another copy.
- Dashboard: its files update with the engine. An already-open browser tab offers Reload dashboard so drafts are not silently discarded.
- Mainboard: the server deployment publishes the new website. Existing tabs offer a refresh; updating a local engine does not deploy the public website.
Run minerva release status --force after updating. Installed and running
versions are separate: a newer running window or an old successful receipt cannot
hide an older package on disk. A failed version check does not confirm success.
For automation, use the engine virtual environment’s Python to run
python -m minerva_cli.main release apply --yes; this avoids a Windows console
launcher handing off the install and returning early. It returns 0 when detected packages
are installed, 1 for failure, 2 for another update or coordination refusal,
and 3 when installation needs your action. The ordinary minerva update
command remains compatible with older update buttons: a pending installer is
reported in component status rather than being treated as an engine failure.
Recovering a blocked Windows 0.24.1 update
The older updater can stop before fetching the fix when a legacy dashboard still holds Python extensions open. Wait for any active update to finish, close Minerva Desktop and VS Code, and use one Command Prompt window:
minerva serve --stop
"%LOCALAPPDATA%\minerva\minerva-agent\venv\Scripts\python.exe" -m minerva_cli.main update --yes
Use your actual install path if you selected a different location. Invoking the
interpreter directly avoids the old console launcher handing off the installation
and returning early. Run minerva release status --force afterward; reload VS Code
and restart older windows when requested. Do not delete a live update lock or use
--force-venv to bypass locked native extensions.
Current releases pause verified manual dashboard backends for the update and relaunch them on their recorded endpoint. Unknown or supervised Python processes remain protected; stop them through their owning application before retrying.
What the engine fetches depends on how Minerva was installed:
- Release install (the installer's default).
minerva updatereads the release channel at Minerva releases, downloads the newer archive, refuses it unless its size and SHA-256 match the published manifest, and swaps it in. Yourvenv,node_modulesand.envare kept. - Git checkout (installed with
--source git,--branchor--commit).minerva updatepulls the latest code frommain.
Either way it then updates dependencies and prompts you to configure any new options that were added since your last update.
minerva update automatically detects new configuration options and prompts you to add them. If you skipped that prompt, you can manually run minerva config check to see missing options, then minerva config migrate to interactively add them.
Passive update notices
Pinned or noninteractive installations can disable passive CLI version and banner update checks:
minerva config set updates.check false
This suppresses both cached update notices and passive update-check network requests. The default is true. Explicit minerva update --check and minerva update still work; this setting does not control the Desktop application's updater.
What happens during an update
When you run minerva update, the following steps occur:
- Pre-update snapshot — a lightweight state snapshot is saved by default (covers pairing data, cron jobs,
config.yaml,.env,auth.json, and other state files that get modified at runtime; individual files over 1 GiB are skipped so a large sessions DB never slows the update down). Because the code swap and gateway restarts touch every profile, the same snapshot is taken for every profile on the install — each into its ownstate-snapshots/directory — and the post-update cron-jobs safety net checks each profile against its own snapshot. Controlled byupdates.pre_update_backup(quickby default,fullfor a zip of all ofMINERVA_HOME,offto disable). Recoverable via the snapshot restore flow described under Snapshots and rollback. Quick snapshots are file-loss recovery, not code-rollback insurance — for a coherent point-in-time rollback use--backup(full mode). - Code update — a release install downloads, verifies (SHA-256) and swaps in the newer release archive, leaving the existing install in place if anything fails; a git checkout pulls the latest code from the
mainbranch and updates submodules - Post-pull syntax validation + auto-rollback (git checkouts) — after the pull, Minerva compiles the nine critical files every
minervainvocation imports at startup. If any fails to parse (e.g. an orphan merge-conflict marker, an accidentally truncated file), Minerva runsgit reset --hard <pre-pull-sha>to roll the install back so your shell stays bootable. Re-runminerva updateonce the upstream fix lands. - Dependency install — runs
uv pip install -e ".[all]"to pick up new or changed dependencies - Config migration — detects new config options added since your version and prompts you to set them
- Desktop rebuild (stage-and-swap) — if the Minerva Desktop app was built from this checkout, it is rebuilt so the GUI matches the new code. The rebuild packs into a temporary staging directory next to
apps/desktop/release/, verifies the staged app, and only then renames it over the previous build. A rebuild that fails at any point — corrupt Electron download, missing dependency, disk full — leaves the previous app untouched and launchable; the update reports⚠ Update partially completeandminerva desktopretries the rebuild. - Gateway auto-restart — running gateways are refreshed after the update completes so the new code takes effect immediately. Service-managed gateways (systemd on Linux, launchd on macOS) are restarted through the service manager. Manual gateways are relaunched automatically when Minerva can map the running PID back to a profile. Manually-launched
minerva servebackends (for example a network-bound serve powering a remote Desktop) are handled the same way: each backend records its bind address in the install's spawn ledger at startup, so the update stops it before the code swap and relaunches it afterward on the same host and port — a remote Desktop pointed at that endpoint reconnects instead of stranding. Backends owned by a running Desktop app are left to the app's own respawn.
Updating from a release that had the browser dashboard
The current local dashboard ships with the engine. Some older updaters still ask npm for the retired web workspace and report a partially complete update. Run minerva update once more to let the current updater repair the Node dependencies; the dashboard does not require that old workspace.
Missing Windows updater files
If the maintained updater script is missing (for example after antivirus quarantine), the legacy update forwarder fails instead of reporting a successful hand-off. Repair the installation and review the security software's quarantine report before retrying; do not disable antivirus protection. Before reporting success, the maintained updater checks the CLI import, Windows executable header, ASAR header and packaged main entry, readable renderer HTML with a local module entry, initial module files, and current build stamp. These are minimum artifact checks, not a full dependency audit or an application/backend launch test. Missing Python is reported before waiting for Desktop shutdown; dependency repair is still allowed to run as part of the update. Electron checks maintained handoff prerequisites before stopping backends when that layout is present; genuine legacy-flat updater layouts remain supported, so not every missing updater file is detected before backend shutdown.
On Windows, a Desktop reopened during packaging is stopped again immediately before the staged build is promoted. This cleanup is restricted to executables inside that checkout's Desktop release tree; unrelated installations are not stopped. A remaining lock still makes staged promotion fail rather than bypassing the rename error.
Git checkouts only: branches and local changes
The next sections — --branch, parked feature branches, and local source changes — apply only to git checkouts. A release install has no .git: minerva update --branch <name> refuses to run there (releases are published builds), and there is no working tree to stash.
Updating against a non-default branch: --branch
On a git checkout, minerva update tracks origin/main by default. Pass --branch <name> to update against a different branch — useful for QA channels, feature branches, or release-candidate testing:
minerva update --branch release-candidate
minerva update --check --branch experimental # preview behindness only
If your local checkout is on a different branch, Minerva auto-stashes any uncommitted work, switches HEAD to the target branch, and then pulls. Branches that don't exist locally are auto-tracked from origin/<name> (git checkout -B <name> origin/<name>). Branches that don't exist anywhere fail cleanly — your stashed changes are restored before exit so you're never stranded in a weird state. The main-only fork-upstream sync logic is automatically skipped on non-main branches.
Checkout parked on a feature branch
If the source checkout was left sitting on a feature branch (by tooling, a worktree experiment, or a manual checkout), minerva update switches it back to the update target automatically whenever the working tree is clean:
- Branch fully merged (every commit already contained in
origin/main—git cherryreports nothing unmerged): the update says so —Checkout was parked on '<branch>' (fully merged) — switched back to main— and stays onmainafterwards. - Branch has unmerged commits but the tree is clean: the update still switches to
mainso the update can proceed — this is what non-interactive callers (the desktop update button, gateway/update, cron) rely on, since they have no way to resolve a skip. Your commits are untouched:git checkoutnever discards committed work, and the update prints a loud notice naming the branch and commit count, plus thegit checkout <branch>command to pick the work back up later.
If you deliberately run a custom branch (local patches maintained on top of main), set updates.parked_branch_strategy: update_in_place in config.yaml. The update then merges origin/main into your branch instead of switching away from it — the checkout never moves, your commits survive, and the running code advances. Fast-forward when possible; on divergence a true merge behind a pre-update-<stamp> safety tag, stopping cleanly (nothing changed) on conflict. minerva update --switch-branch overrides back to the switch path for one run — useful on a deep feature branch that must not accumulate update-driven merge commits.
When the parked branch has uncommitted changes (dirty tree), Minerva does not touch it. The code update is marked SKIPPED with a loud warning naming the branch, how far behind origin/main it is, and the exact commands to resolve — instead of pretending the update succeeded. The completion line always shows the actual branch and HEAD (✓ Update complete! [main @ 30fcf9580]) so drift is visible at a glance. Set updates.auto_switch_parked_branch: false in config.yaml to disable the auto-switch entirely (the skip warning still fires).
Local changes on non-interactive updates
When you run minerva update in a terminal, Minerva stashes any uncommitted source-tree changes, pulls, then asks whether to restore them — exactly as it always has. Nothing changes for interactive updates.
When the update runs without a terminal — from the desktop/chat app's "Update" button or a gateway-triggered update — there's no prompt to answer. The updates.non_interactive_local_changes setting decides what happens to your stashed changes:
# ~/.minerva/config.yaml
updates:
non_interactive_local_changes: stash # default: keep + auto-restore
# non_interactive_local_changes: discard # throw local source edits away
stash(default) — auto-stash, pull, then auto-restore your changes on top of the updated code. Nothing is lost; if a restore hits conflicts they're preserved in a git stash for manual recovery.discard— auto-stash and drop the stash after the pull, so the update always lands on a clean tree. Use this only on machines where you never intend to keep local edits to the Minerva source. It stash-drops (notgit reset --hard+git clean -fd), so ignored paths likenode_modules,venv, and build outputs are never touched.
In the desktop app this is Settings → Advanced → In-App Update Local Changes.
Desktop updates never auto-restore. The desktop updater invokes minerva update --keep-stash: local source edits are still stashed so the update can proceed, but they are not re-applied afterward — they stay parked in git stash and the update log prints the exact git stash apply <ref> command to bring them back. This prevents local edits from silently riding along across desktop updates and breaking the freshly updated install. (non_interactive_local_changes: discard still wins if you've opted into discarding.) To restore parked changes manually:
cd ~/.minerva/minerva-agent # or your install root
git stash list --format='%gd %H %s' # find the minerva-update-autostash entry
git stash apply stash@{0}
You can pass --keep-stash to a terminal minerva update too if you want the same never-reapply behavior interactively.
Preview-only: minerva update --check
Want to know if an update is available before installing it? Run minerva update --check. On a release install it compares your installed version with the version in the release channel's manifest; on a git checkout it fetches and compares commits against origin/main. No files are modified, no gateway is restarted. Useful in scripts and cron jobs that gate on "is there an update".
When a newer release is available, --check also prints its release notes ("What's new"). The
same notes appear in the dashboard, the desktop app and the VS Code Minerva versions dialog,
and they are part of the signed release manifest, so they cannot be altered by whoever serves the files.
Choosing a version or rolling back: --list and --to
Every published release stays on the channel. On a release install:
minerva update --list # published releases, newest first; marks installed and latest
minerva update --to 0.24.5 # install exactly this release
--to verifies that version's own signed manifest and archive, exactly like a normal update. If
the version is older than the one installed, it is a rollback: Minerva asks for confirmation
(pass --yes in scripts). Settings, sessions and memory are kept; settings that only the newer
version understands stay in config.yaml and are ignored until you update again. Desktop and
VS Code packages follow the engine to the same release when that release published them. On a
git checkout, use git tag -l 'v*' and git checkout v<version> instead.
Fleet preview: minerva update --plan
Before updating a machine that runs several profiles or services, minerva update --plan prints the full update plan without changing anything: the install kind (release archive, git checkout, Docker image, Nix managed), every running Minerva service across all profiles with its supervisor (systemd, launchd, manual) and the code version it is actually serving, and the restart mechanism each one will get. Manually-launched minerva serve backends appear too (from the spawn ledger), with their recorded bind endpoint and a "stop before code swap, relaunch with recorded launch args" restart mechanism. On image- or package-managed installs the plan reports that the install is not updatable in place and names the right update command instead. Read-only and safe on a live fleet.
The same inventory is embedded in every real update's receipt (~/.minerva/logs/update_receipts/), so after an update you can compare what the updater saw against what it did.
Update receipts and the fleet version check
Every minerva update run writes a machine-readable receipt to ~/.minerva/logs/update_receipts/ (last 20 kept, latest.json always points at the most recent): the pre-update fleet plan, each step taken, anything skipped and why, the gateway restart outcome, and the final fleet version matrix. After the restart phase the updater compares each live gateway's running code against the freshly updated checkout and prints a per-profile matrix — a gateway still serving pre-update code is reported loudly with the exact restart command, and the update exits non-zero so automation never treats a mixed-version fleet as healthy. Both --plan and the fleet check ask each running gateway directly over its local control socket (gateway.sock in the profile's data directory, a named pipe on Windows) when available, so version and supervisor information comes from the gateway itself; gateways from older versions are still discovered through their state files as before.
Interrupted gateway restarts
If an earlier update pulled code but did not finish restarting the fleet, the next
minerva update retries even when the checkout is already current. An empty process
scan does not prove recovery: failed systemd units and installed launchd jobs may
have no live PID. The pending restart marker is retained if supervisor discovery
fails, a restart fails, or a requested service cannot be verified active. The update
exits nonzero and reports the affected services; recover them with the printed
commands and retry minerva update.
A failed historical receipt does not by itself prove that gateways are still stale. Startup and gateway-status warnings, as well as update catch-up, check the live fleet before acting on receipt-only restart obligations. Every recorded gateway profile must have a live successor on the current checkout; an unrelated current gateway cannot stand in for a missing, down, unknown-version, or non-gateway runtime. A manual gateway restart can therefore settle the warning without rewriting a failed update as successful. A separate pending marker remains authoritative because it can belong to a newer interrupted update whose inventory never reached the receipt.
Full pre-update backup: --backup
For high-value profiles (production gateways, shared team installs) you can opt into a full pre-pull backup of MINERVA_HOME (config, auth, sessions, skills, pairing):
minerva update --backup
Or make it the default for every run:
# ~/.minerva/config.yaml
updates:
pre_update_backup: full
updates.pre_update_backup is a single knob with three modes: quick (default — the lightweight state snapshot described above), full (the quick snapshot plus a complete MINERVA_HOME zip; can add minutes on large homes), and off (no pre-update backup at all — --no-backup does the same for a single run). Legacy boolean values still work: true means full, false means off.
Update backups protect an in-place update. If you're migrating your whole setup to different hardware, use minerva backup + minerva import instead — see Exporting Minerva to another machine and minerva backup vs minerva profile export.
Windows: another minerva.exe is running
On Windows, minerva update will refuse to run if it detects another minerva.exe process holding the venv's entry-point executable open — most commonly the Minerva Desktop app's spawned backend, an open minerva REPL in another terminal, or a running gateway:
$ minerva update
✗ Another minerva.exe is running:
PID 12345 minerva.exe
Updating now would fail to overwrite ...\venv\Scripts\minerva.exe because
Windows blocks REPLACE on a running executable.
Close Minerva Desktop, exit any open `minerva` REPLs, and
stop the gateway (`minerva gateway stop`) before retrying.
Override with `minerva update --force` if you've already
confirmed those processes will not write to the venv.
Close the listed processes and re-run. If you're sure the concurrent process won't interfere (rare — usually only useful when an antivirus shim is mis-attributed), pass --force to skip the check. In that case the updater will still retry the .exe rename with exponential backoff and, on stubborn locks, schedule the replacement for next reboot via MoveFileEx(MOVEFILE_DELAY_UNTIL_REBOOT) so the update can complete.
A second, separate guard refuses to touch the venv while any process is running from its Python interpreter (the Desktop app's backend, a gateway, a Python REPL). Those processes keep native extension files (.pyd) locked, and a dependency sync that dies partway on an access-denied error strands the install between versions. This guard is not bypassed by --force; if you're certain the detected holders are false positives, use the explicit minerva update --force-venv.
Windows venv recreation is transactional
When the Windows installer must recreate an existing venv, it first moves the old directory to a unique venv.stale.* name, then creates and verifies the replacement. The old tree is deleted only after the dependency install completes and the baseline imports pass in the new tree — until then it is the rollback source (recorded in venv.pending-backup).
If the move cannot be completed, the installer stops and leaves the live venv untouched. If uv fails or reports success without creating the interpreter, any partial replacement is moved to venv.failed.* and the previous venv is restored. This keeps the health and blocker checks usable after a failed install.
A venv.stale.* or venv.failed.* directory can remain when another process still owns a file handle. Close Minerva Desktop, gateways, and Python processes using the install, then retry the install/update; parked directories are cleaned up best-effort after a successful recreation.
On a release install the code-update part of the output looks like this (dependency, config and gateway-restart steps follow):
$ minerva update
→ Checking the release channel...
→ Downloading Minerva v0.23.0...
✓ Download verified (SHA-256)
→ Extracting...
✓ Installed v0.23.0
When nothing newer is published it prints ✓ Already up to date (v…) and stops, first finishing any gateway restart an interrupted earlier update still owes (the same catch-up a git checkout runs). A git checkout prints the git pull progress instead.
Recommended Post-Update Validation
minerva update handles the main update path, but a quick validation confirms everything landed cleanly:
- Git checkouts:
git status --short— if the tree is unexpectedly dirty, inspect before continuing minerva doctor— checks config, dependencies, and service healthminerva --version— confirm the version bumped as expected- If you use the gateway:
minerva gateway status - If
doctorreports npm audit issues: runnpm audit fixin the flagged directory
If git status --short shows unexpected changes after minerva update, stop and inspect them before continuing. This usually means local modifications were reapplied on top of the updated code, or a dependency step refreshed lockfiles.
If your terminal disconnects mid-update
minerva update protects itself against accidental terminal loss:
- The update ignores
SIGHUP, so closing your SSH session or terminal window no longer kills it mid-install.pipandgitchild processes inherit this protection, so the Python environment cannot be left half-installed by a dropped connection. - All output is mirrored to
~/.minerva/logs/update.logwhile the update runs. If your terminal disappears, reconnect and inspect the log to see whether the update finished and whether the gateway restart succeeded:
tail -f ~/.minerva/logs/update.log
Ctrl-C(SIGINT) and system shutdown (SIGTERM) are still honored — those are deliberate cancellations, not accidents.
You no longer need to wrap minerva update in screen or tmux to survive a terminal drop.
Checking your current version
minerva version # same as minerva --version; also says whether an update is available
Run minerva update --check to compare it with the latest published release (release channel).
Updating from Messaging Platforms
You can also update directly from Telegram, Discord, or Slack by sending:
/update
This runs minerva update — installing the newer release (or pulling the latest code on a git checkout), updating dependencies, and restarting running gateways. The bot will briefly go offline during the restart (typically 5–15 seconds) and then resume.
Manual Update
If you installed manually from a git checkout (not via the quick installer):
cd /path/to/minerva-agent
# Activate the venv you created during install (outside the source tree)
export VIRTUAL_ENV="$HOME/.minerva/venvs/minerva-dev"
export PATH="$VIRTUAL_ENV/bin:$PATH"
# Pull latest code
git pull origin main
# Reinstall (picks up new dependencies)
uv pip install -e ".[all]"
# Check for new config options
minerva config check
minerva config migrate # Interactively add any missing options
Rollback instructions
If an update introduces a problem on a git checkout, you can roll back to a previous version (a release install has no git history to check out; restore state with the pre-update snapshot instead):
cd /path/to/minerva-agent
# List recent versions
git log --oneline -10
# Roll back to a specific commit
git checkout <commit-hash>
uv pip install -e ".[all]"
# Restart the gateway if running
minerva gateway restart
To roll back to a specific release tag (substitute your previous tag — e.g. v0.22.0, or any earlier tag from git tag --sort=-version:refname):
git checkout vX.Y.Z
uv pip install -e ".[all]"
Rolling back may cause config incompatibilities if new options were added. Run minerva config check after rolling back and remove any unrecognized options from config.yaml if you encounter errors.
Image-managed installs (Docker): the provenance marker
Docker images built from the release's Dockerfile bake a small read-only marker (/etc/minerva/image-provenance.json) that authoritatively identifies the filesystem as image-managed. minerva update, minerva update --check, and the backend's update API all consult it before touching anything: on an image-managed install they refuse cleanly (exit code 2), print how to update instead (rebuild the image from the newest release and recreate the container, as Docker → Upgrading describes), and write a refused receipt so fleet tooling can see the attempt happened. The marker wins even when a source checkout is bind-mounted into the container — the refusal is based on what the running filesystem is, not what it looks like. A damaged marker still refuses (fail-closed). Nix-managed installs refuse through the same gate using the existing detection.
Note for Nix users
Nix is no longer an explicitly supported install path (best-effort only) — see Nix Setup. If you installed via Nix flake, updates are managed through the Nix package manager:
# Update the flake input
nix flake update minerva-agent
# Or rebuild with the latest
nix profile upgrade minerva-agent
Nix installations are immutable — rollback is handled by Nix's generation system:
nix profile rollback
See Nix Setup for more details.
Uninstalling
minerva uninstall
The uninstaller gives you the option to keep your configuration files (~/.minerva/) for a future reinstall.
Preview the affected paths without deleting anything:
minerva uninstall --dry-run
minerva uninstall --yes keeps local configuration and conversations;
minerva uninstall --full --yes also deletes local data. Remove the VS Code
extension through the editor's Extensions view. Remove packaged desktop apps
through Windows Installed apps, or your Linux package manager
(sudo apt remove minerva-desktop for the published Debian package). These
separately installed packages are not the same as the agent engine.
Take your setup with you before removing anything: minerva backup captures the entire ~/.minerva directory including credentials, while minerva profile export packs a single profile with credentials excluded by design (so an export alone is not a full backup). See minerva backup vs minerva profile export.
Manual Uninstall
rm -f ~/.local/bin/minerva
rm -rf /path/to/minerva-agent
rm -rf ~/.minerva # Optional — keep if you plan to reinstall
If you installed the gateway as a system service, stop and disable it first:
minerva gateway stop
# Linux: systemctl --user disable minerva-gateway
# macOS: launchctl remove ai.minerva.gateway
Check every Minerva interface
Run minerva release status --force to check the CLI/TUI, packaged dashboard,
VS Code extension, and desktop app against the same signed product release.
An installed package and a running window can have different versions: reload
VS Code, restart the desktop app, or reload the dashboard when the status says
restart required. A current component does not need another installation.
Previous failed attempts remain in the update history; they do not make a
successfully updated component outdated.
minerva update coordinates detected companion packages as well as the engine.
An editor that was closed during the update receives its new extension through
its installed editor CLI. Missing packages, installation permissions, and
unconfirmed installations remain listed for follow-up. Windows installers
still require OS confirmation. Platforms without a published installer remain
explicitly unavailable.
Release downloads report downloaded size, percentage, and transfer speed. Interrupted transfers retry up to three times and resume where supported by the server. Every completed download must match the signed size and SHA-256 before it can be installed. A slow healthy connection can still take time; progress shows whether bytes are arriving.