tula

Install

One file, and nothing else to install beside it. Three ways to get it, and the same binary at the end of all of them.

install
curl --proto '=https' --tlsv1.2 -LsSf https://usetu.la/install.sh | sh
--proto '=https'
Only HTTPS, on redirects too
--tlsv1.2
Nothing older than TLS 1.2
-L
Follow a redirect
-s
No progress bar
-S
But still show errors
-f
Stop on an HTTP error, so an error page is never piped into a shell

This pipes a script into your shell, so read it before you run it. install.sh is the file the command fetches, copied from the one in the repo — the same file, and the one every test runs against.

tula checks for a new release once a day and says so in a line. It never installs one without asking: /update shows what it would install and where to check it, and /update install is the step that goes ahead.

Where it puts things

Everything goes under ~/.tula. Each version gets its own folder, and ~/.tula/bin/tula is a link pointing at the one you run.

If ~/.tula/bin is not on your PATH, the installer adds a line to your zsh, bash or fish profile and tells you which file it changed. On any other shell it prints the line and changes nothing. Set TULA_NO_MODIFY_PATH=1 to make it print rather than edit, whatever your shell.

One exact version

Set TULA_VERSION to install a version instead of the newest. It also takes latest, which is what you get anyway. In CI, add TULA_REQUIRE_ATTESTATION=1 to stop the install when the build attestation cannot be checked, rather than warn about it.

Update

/update install from inside tula does this without leaving it. Running the command again does the same thing, and is the one that still works when tula will not start.

It downloads nothing when the newest release is the one you already have — it says so and relinks, which takes about a second. TULA_FORCE=1 fetches and checks that same version again anyway.

update
curl --proto '=https' --tlsv1.2 -LsSf https://usetu.la/install.sh | sh

Go back

Old versions stay on disk, so going back is a change of link rather than another download.

ln -sf ~/.tula/versions/<version>/tula ~/.tula/bin/tula

Remove

Delete the folder, and the line the installer added to your shell profile. Your keys are kept elsewhere, so this leaves them alone.

rm -rf ~/.tula

Confirm it worked

tula --version

It prints the version. If your shell says it cannot find tula, it is on disk and your PATH does not reach it — which line fixes that is the one thing the three channels do not share.

Install script
Near the end it printed one of three. added to or already in means the PATH line is in a profile already, and this shell started before it — open a new one. add it yourself means it changed nothing, and the export line beside it is yours to add.
Homebrew
A pinned tula@<version> is keg_only, so it is installed and deliberately not on your PATH until you brew link it.
npm
Its launcher goes to npm’s global bin directory, which has to be on your PATH. npm prefix -g names the folder that bin sits in.

Every install is checked

Published checksum

Always. The install stops if the download does not match it.

Build attestation

GitHub signs it as the release is built. Checking it needs the GitHub CLI, which most people do not have — read the section below before you count on it.

Versioned installs

Every release keeps a name of its own, so an older build is still there after a newer one arrives.

What it runs on

macOSYesIntel and ARM, 64-bit.
LinuxYesIntel and ARM, 64-bit. Needs glibc.
Alpine, or any musl LinuxNoThe installer says so and stops.
WindowsThrough WSLInstall inside WSL, where it is Linux. There is no native build.

Proving who built it

A checksum proves the file arrived whole. It does not prove who made it: the checksum is published beside the file, so whoever could swap one could swap the other. The build attestation is the part that proves origin — GitHub signs it as the release is built, and nobody who gets hold of the files afterwards can reissue it.

Checking one needs the GitHub CLI, signed in with gh auth login. It will not fetch an attestation without a token, even for a public repository.

Most people do not have the GitHub CLI, and nothing here requires it. Without it you still get an HTTPS-only download and a checksum the installer will not skip — but nothing has proved who built the binary, and the installer says so in as many words when it finishes.

verify
curl --proto '=https' --tlsv1.2 -fLO https://github.com/hsnice16/tula/releases/download/v0.1.2/tula-v0.1.2-darwin-arm64.tar.gz
gh attestation verify tula-v0.1.2-darwin-arm64.tar.gz --repo hsnice16/tula --signer-workflow hsnice16/tula/.github/workflows/release.yml

The download is the first step, not a repeat of one: the attestation covers the archive rather than the binary inside it, and the installer keeps no copy of the archive.

Your keys are kept apart

Whichever way you installed it, what you save lives in ~/.config/tula, away from the binary. Reinstalling does not touch it, updating does not touch it, and removing tula leaves it where it is.

So deleting it is a separate step, and a deliberate one. Run this when you are done with tula, not when you are reinstalling it.

rm -rf ~/.config/tula