Install cin90
cin90 ships as a single static binary for macOS and Linux.
Windows students use cin90 inside WSL2. Install the Linux artifact in the WSL2 distribution and run all cin90 commands from that Linux shell.
Install From A Release
The download page on coderin90.com is the bootstrap for a machine that does not have cin90 yet. The binaries are hosted on S3; each version publishes four artifacts plus their checksums:
cin90_<version>_darwin_amd64·cin90_<version>_darwin_amd64.sha256cin90_<version>_darwin_arm64·cin90_<version>_darwin_arm64.sha256cin90_<version>_linux_amd64·cin90_<version>_linux_amd64.sha256cin90_<version>_linux_arm64·cin90_<version>_linux_arm64.sha256
(<version> is the version string exactly as the manifest gives it, which is
unprefixed — e.g. 0.1.0-beta.2, not v0.1.0-beta.2, even though the matching
git tag carries the v. The artifact URL is
https://cin90-releases.s3.us-east-1.amazonaws.com/<version>/<artifact>, and
each artifact's .sha256 and .sig sit beside it at that URL plus the suffix.
The bucket has no listing, so the manifest at
https://cin90-releases.s3.us-east-1.amazonaws.com/latest.json is where the
current version and the four binary URLs come from.)
Releases may be stored gzip-compressed and served with Content-Encoding: gzip, which cuts a 9.4MB download to 3.8MB. No published version is compressed
yet, and browsers and cin90 update decode it without being asked in any case.
curl does not, unless you pass --compressed, so use it either way:
curl -fsSL --compressed -O \
https://cin90-releases.s3.<region>.amazonaws.com/<version>/cin90_<version>_<platform>
Against a compressed release, omitting --compressed saves the compressed
stream as if it were the binary. That is not a silent failure — the checksum
below will not match, and the file will not run — but the checksum is the only
thing that tells you. Against an uncompressed one, --compressed is a harmless
no-op, which is why it is the safe habit.
A first install is verified by hand, because the embedded signing key can only
be checked by a binary that already runs. Download the artifact and its
.sha256 sidecar, then compare:
shasum -a 256 -c cin90_<version>_<platform>.sha256
# or on GNU Linux: sha256sum -c cin90_<version>_<platform>.sha256
The sidecar describes the raw binary — the decompressed bytes — so this is the same check it always was.
An "OK" line means the artifact matches the published checksum. Each release
also publishes <artifact>.sig (the detached Ed25519 signature) — the CLI
verifies the checksum and that signature before cin90 update replaces the
local executable.
Update
Run:
cin90 update
The updater first compares the version the manifest names against the running
one and refuses anything that is not newer, so a manifest pointing at an older
genuinely-signed build cannot roll you back. Already on the published version,
it says so and downloads nothing. A deliberate rollback is
cin90 update --force.
Past that guard it downloads the platform artifact named by the manifest, verifies sha256 and the detached signature, writes the replacement beside the current executable, and then atomically renames it into place. A failed download, checksum mismatch, or bad signature leaves the current binary in place.
Install The Push-Time Hook
Run this once per assignment clone:
cin90 install-hook
It sets the repository's core.hooksPath to .githooks and writes a pre-push
hook there.
Setting core.hooksPath stops git reading the repository's old hooks directory
at all, so hooks that were already installed there — yours, or another tool's —
are copied forward as one-line scripts in .githooks that run the original.
They keep firing, and a pre-push of your own still decides whether the push
goes through. If .githooks already contains a hook cin90 did not write, the
install refuses and says so rather than overwriting it.
The directory it copies from is whichever one git is reading, which includes a
core.hooksPath you set globally in ~/.gitconfig — the same directory a
second run comes back to. Only the hook names git actually runs are copied
forward, so a shell library or a spare copy kept alongside them stays where it
is.
Run it again after installing another hook. Something like pre-commit install
writes into .git/hooks, which git no longer reads, so the new hook would never
fire; a second cin90 install-hook re-scans and chains it. Nothing else
changes — the same scripts and the same core.hooksPath.
If cin90 cannot capture a push it says so once on stderr and lets the push
through: it is a capture trigger, never a gate. The usual cause is cin90 not
being on PATH for the program running the hook — a GUI git client or an IDE
starts with a minimal environment, so a PATH exported only in ~/.zshrc does
not reach it. Install the binary somewhere already on the system PATH, and run
cin90 reconstruct to record the session for a push that went uncaptured.
To undo it:
cin90 uninstall-hook
core.hooksPath goes back to whatever it was before — another directory, or no
setting at all. The one exception is the mirror image of the clobber above: if
core.hooksPath now points somewhere that is not .githooks, something else
was installed after cin90, and putting the old value back would silently
disable it. cin90 leaves the setting alone, says so, and forgets what it had
recorded. Either way the scripts in .githooks are left where they are, inert,
because nothing points at them any more.
Read this page in your terminal: install the cin90 CLI and run
cin90 docs. The same page is served as
raw markdown.