heretic-cli update
The two-phase self-update — release lookup, platform asset naming, staging as .heretic-cli.pending, applying it on the next run with backup and rollback, package-install detection, and manual recovery
Synopsis
heretic-cli update # no flags
A running executable cannot overwrite itself, so the update happens in two phases:
Phase 1 heretic-cli update download the release asset → <exeDir>/.heretic-cli.pending (mode 0755)
Phase 2 the next heretic-cli … rename exe → exe.backup, pending → exe, chmod 0755, delete the backup
The first command after staging is consumed
Phase 2 runs before any argument parsing. When it applies an update the process prints Update applied successfully! and exits 0 without running your command — so run something trivial first:
heretic-cli update
heretic-cli -v # applies the update, then prints the new version
Phase 1 in detail
1. Package-install detection. If the CLI is running from node_modules or as a .js file, no binary update is attempted:
Current version: 0.1.0
This CLI was installed via npm/bun. To update, run:
bun update -g heretic-cli
2. System-directory check. If the executable lives in a system location (/usr/bin, /usr/local/bin, /bin, /sbin, /usr/sbin, /opt, or on Windows %ProgramFiles%, %ProgramFiles(x86)%, %windir%, %SystemRoot%) it warns CLI is installed in a system directory and probes writability with a temporary file. Not writable:
Cannot update: insufficient permissions
Please run with sudo or reinstall in a user directory (e.g., ~/.local/bin)
3. Release lookup. An unauthenticated GET against the GitHub releases API for giglabo/heretic (subject to the 60 requests/hour/IP limit). A non-OK response logs GitHub API returned status <n> and Could not fetch latest release information.
4. Version comparison. A leading v is stripped and the numeric parts are compared, missing parts counting as 0. If the release is not newer: You are already on the latest version!
5. Asset selection. The release must contain an asset named exactly:
heretic-cli-<darwin|linux|windows>-<x64|arm64>[.exe]
Anything else is invisible to the updater — Could not find asset for <name> — and an unsupported host prints Unsupported platform: <platform> <arch>.
6. Download and stage. The asset body is written to <exeDir>/.heretic-cli.pending and chmod'ed 0755; partial downloads are removed on error.
Update staged successfully!
Restart the CLI to apply the update
No checksum, no pinning
The asset is downloaded into memory and written as-is — there is no checksum or signature verification. The updater also only ever moves to the latest release: no version pinning, no downgrade, no channels. Pre-release tags such as v1.0.0-rc1 are treated as not newer.
Phase 2 in detail
- No
.heretic-cli.pendingnext to the executable → nothing happens. - Writability is re-checked. If the directory is not writable,
Cannot apply update: insufficient permissionsis printed and the pending file is deleted — an update staged as one user but landing in a root-owned directory is discarded, not retried. exe→exe.backup, thenpending→exe,chmod 0755→Update applied successfully!, and the backup is removed.- On any error the backup is restored (
Restored from backup) and the pending file cleaned up.
Both phases assume the pending file sits in the same directory as the executable, so a CLI on a read-only mount or baked into a container layer can never self-update.
Which upgrade path applies to you
| Installed as | Upgrade with |
|---|---|
| Bun/npm package | bun update -g @giglabo/heretic-cli |
| Native binary in a user directory | heretic-cli update, then any command |
| Native binary in a system directory | sudo heretic-cli update, or reinstall under ~/.local/bin |
| Locally built from source | bun run build — see the warning below |
update replaces local builds too
Running heretic-cli update on a binary you built yourself replaces it with the latest release asset. Keep development builds off your PATH if that matters.
Checking without staging
There is no --check mode. Compare the tag yourself:
curl -s https://api.github.com/repos/giglabo/heretic/releases/latest | jq -r .tag_name
heretic-cli -v
Manual recovery
which heretic-cli
ls -la "$(dirname "$(which heretic-cli)")" | grep -E 'pending|backup'
rm -f <exeDir>/.heretic-cli.pending # abandon a staged update
mv <exeDir>/heretic-cli.backup <exeDir>/heretic-cli # roll back a bad apply
Exit codes
Every failure inside update is logged and returns normally, so the command almost always exits 0. In scripts, check the log lines (or the version afterwards), not the exit code.
Next Steps
- Installation — install locations and build targets
- Setup & Upgrade — the whole upgrade flow
- doctor — verify the environment after upgrading