Repository navigation
educatesenv v1.1.0 reworks how list-remote chooses and shows releases,
takes the GitHub token from your environment or the GitHub CLI instead of
a plain-text config file, verifies every download against the release's
checksums, and adds install latest and uninstall. It also fixes the
download command in these release notes, which returned 404 for v1.0.0.
Three changes can break scripts and habits built on v1.0.0. Read
"Breaking changes" before you upgrade.
Breaking changes
list-remote --all means every stable release
In v1.0.0, --all added pre-releases to the list. It now removes the
limit on how many releases are shown, and pre-releases have a flag of
their own, --pre-releases. To get what --all used to show, every
release including pre-releases, run:
educatesenv list-remote --pre-releases --alllist-remote prints a table of the 10 newest stable releases
v1.0.0 printed an Available versions: line and then the stable
releases it found as - <version> lines, sorted as strings. list-remote now
prints the 10 newest stable releases, highest version first by semver,
as VERSION and RELEASED columns under a header, with each release's
publish date in UTC:
$ educatesenv list-remote
VERSION RELEASED
3.8.0 2026-08-26
3.7.3 2026-07-17
...
Showing 10 of 66 stable releases. Use --all to see all, --pre-releases to include pre-releases.The "Showing N of M" line goes to stderr, so a pipe gets only the table.
A script that read the old list needs to skip the header and take the
first column, for example:
educatesenv list-remote --all | awk 'NR > 1 { print $1 }'config.yaml is no longer read from the working directory
v1.0.0 also looked for config.yaml in the directory you ran it from,
and a file found there replaced your own config, including the
development binary location that decides what runs as educates. A
repository that happened to hold a config.yaml could change which
binary you ran. educatesenv now reads only ~/.educatesenv/config.yaml.
If you relied on a per-directory config, set the EDUCATES_* environment
variables instead, which still override the file.
Deprecations
Both keep working in v1.1.0, with a warning on stderr, and a later
release removes them.
list-remote --recentsis hidden and changes nothing, since the
10 newest releases are now the default. Drop it from your scripts.github.tokenin the config file is still read, but as the last
of the token sources, and using it prints a warning that names the
file. SetGH_TOKENor rungh auth logininstead, then delete the
tokenline from~/.educatesenv/config.yaml.initand
config initno longer write atokenkey.
New commands and flags
install latestinstalls the highest stable release by semver and
says which version it resolved to. It takes--useand--overwrite
like a named version.usetakes only installed versions, so
install latest --useis how to switch to the latest release.uninstall <version>...removes one or more installed versions.
It checks every version before it removes any, so a typo removes
nothing. It refusesdevelop, versions that are not installed, and
the active version unless you pass--force, which removes the
educatessymlink as well and leaves no version active.list-remote --recent N, or-n N, shows the N newest releases,
10 by default. It conflicts with--all.list-remote --pre-releasesadds release candidates, alphas and
betas to the list.list-remote --by-dateorders the list by publish date instead of
by version, and combines with every other flag:
--pre-releases --by-dateshows3.8.1-rc.2next to4.0.0-alpha.13.
GitHub token
The token now comes from the first of these sources that has one:
EDUCATES_GITHUB_TOKENGH_TOKENGITHUB_TOKENgh auth token --hostname github.com, when the GitHub CLI is on your
PATHgithub.tokenin the config file, deprecated
If you are logged in with gh, educatesenv uses that token with no
setup. It never writes a token to disk, and only list-remote,
install, init --download and config view look one up, so list,
use and version never run gh. config view shows where the token
came from, such as <set via GH_TOKEN>, and never any of its
characters.
When GitHub rate-limits a request, the error says when the limit resets,
and without a token, how to authenticate. When GitHub rejects a token,
the error names the source it came from.
Verified downloads
install and init --download check every binary against the SHA-256
checksum in the release's checksums.txt. A mismatch fails the install
and installs nothing, and so does a checksums.txt that does not list
the binary. A release without a checksums.txt installs with a
warning.
Fixes
list-remoteconsiders every release. v1.0.0 read only the first 100
of the 276 Educates releases.- Releases and installed versions are ordered by semver, so
4.0.0-alpha.13comes above4.0.0-alpha.2and3.10.0above
3.9.0.listshows installed versions newest first, with the
developentry on top. - One rule decides what a pre-release is: a semver pre-release part in
the tag, or GitHub's pre-release flag. Draft releases are never listed,
and tags that are not semver are left out. init --downloadinstalls the highest stable release by semver. It
used to take the first stable release among the 10 most recently
created ones, so it failed during a long run of release candidates,
as from 2026-08-14 to 2026-08-26, and could pick a backport published
after a higher release.- A binary built with
go installreports the version you installed
instead ofdevelop. - An interrupted download no longer leaves a partial binary that a retry
reports as already installed. Downloads land in a temporary file and
are renamed into place only once complete and verified. - A download times out when the server does not accept the connection,
finish the TLS handshake or start its response in time, and fails as
stalled when no data arrives for 60 seconds, instead of waiting
forever. A slow download that keeps making progress still finishes. usesays what went wrong. It reports a version as not installed only
when its binary is missing, and otherwise passes the cause through.config viewno longer prints the token.initandconfig initcreate the config file readable only by you.
An existing file keeps its permissions, so if yours holds a token, run
chmod 600 ~/.educatesenv/config.yaml.initgivesPATHinstructions for the shell in$SHELL:
~/.zshrcfor zsh,~/.bashrcfor bash,fish_user_pathsfor fish.
It told zsh users, the macOS default, to edit~/.bashrc.- Only
list,use,installandinitclean up a leftover symlink to
a development binary.version,configandlist-remoteno longer
touch theeducatessymlink. - The development-symlink check compares directories, so a binary in a
sibling directory such asbin2is no longer taken for one in the bin
directory. - The warning about a missing home directory is printed once, not twice.
listmarksdevelopas active afteruse develop. v1.0.0 marked it
only when theeducatessymlink held the development binary's
absolute path, anduse developwrites a relative one.- A config value or
EDUCATES_*variable that should be a boolean but
is not, such asEDUCATES_DEVELOPMENT_ENABLED=yes, still reads as
false, as in v1.0.0, and now prints a warning on stderr that names the
key and file, or the variable. - The README documents only the commands and flags that exist.
install latestanduninstall, which it documented before they
existed, are now real, andinstall --force,
list-remote --skip-pre-releasesandmake release-test, which never
existed, are gone from it.
Other changes
These are corrections, but they can turn a command that used to succeed
into one that fails:
- Commands that take no arguments reject stray ones, so a mistyped flag
such aslist-remote 5fails instead of being ignored.
Release assets
The binaries are now named educatesenv-<os>-<arch>, and the download
command in the installation instructions works. v1.0.0 named them
educatesenv-<os>-<arch>_<version>_<os>_<arch>, so that command
returned 404.
educatesenv-darwin-amd64educatesenv-darwin-arm64educatesenv-linux-amd64educatesenv-linux-arm64checksums.txt, with the SHA-256 checksum of each binary
For example, on macOS on Apple silicon:
curl -fLO https://github.com/educates/educatesenv/releases/download/v1.1.0/educatesenv-darwin-arm64
curl -fLO https://github.com/educates/educatesenv/releases/download/v1.1.0/checksums.txt
shasum -a 256 --ignore-missing -c checksums.txtOn macOS, if you download an unsigned binary in a browser, macOS
quarantines it and refuses to run it. Clear the attribute with
xattr -d com.apple.quarantine <path to the binary>. Downloads made
with curl are not quarantined.
With Go 1.26 or later, you can install it with go install as well:
go install github.com/educates/educatesenv/cmd/educatesenv@v1.1.0For contributors
- Go 1.26: go.mod sets
go 1.26.0andtoolchain go1.26.10, and every
workflow reads the version from there. - go-github v93, cobra 1.10.2 and testify 1.12.1.
golang.org/x/mod
handles semver. viper gives way togo.yaml.in/yaml/v3and explicit
environment lookups, andgolang.org/x/oauth2is gone. - golangci-lint is pinned to v2.15.0 and runs on pull requests.
GoReleaser is pinned to v2.19.0. - Every action is pinned by commit SHA, and Dependabot keeps the pins
current. - The release workflow's manual trigger has a
skip-signinginput that
releases without signing the macOS binaries, and aMACOS_SIGNING
repository variable set tofalsedoes the same for every release,
tag pushes included. Every other release signs and notarizes them,
and fails before creating a release when a signing or notary secret is
missing, or when signing or the notarization submission fails. - A new
pkg/releasespackage holds the release selection rules, and
the tests run every command in-process against a fake GitHub server,
with no network, no realghand no real home directory.