Installation
One command, one binary, no runtime to install first.
curl -fsSL https://freecode.website/install | bashOn Windows, use PowerShell — the bash installer detects Git Bash / MSYS and tells you to switch rather than installing something that will not work:
irm https://freecode.website/install.ps1 | iexThen, in any project:
freecodeIf the shell cannot find it, open a new terminal (the installer edits your shell
rc files, and the current shell has already read them) or run
export PATH="$HOME/.local/bin:$PATH".
What the installer actually does
Worth knowing, because it decides where your versions live and how rollback
works (scripts/install.sh, scripts/install.ps1):
-
Detects your platform and picks one release artifact —
linux-x86_64,linux-aarch64,macos-aarch64,macos-x86_64, orwindows-x86_64. -
Resolves the latest release through the GitHub API.
-
Downloads an archive, not a bare binary. The
.tar.gz(.zipon Windows) holds the executable and the ONNX Runtime shared library the memory-graph embedder loads at runtime —bun build --compilecannot embed a native.so/.dylib, so it ships beside the binary. -
Unpacks into a versioned directory and repoints a symlink:
~/.freecode/builds/ versions/0.25.16/freecode ← the real binary for this version stable/freecode → symlink to versions/<latest>/freecode stable-version ← plain-text version marker ~/.local/bin/freecode → symlink to builds/stable/freecode -
Clears the macOS quarantine flag on the unpacked directory, so Gatekeeper does not block the binary or the
.dylibit loads. -
Adds the install directory to PATH by appending an export line to
~/.zshenv,~/.bashrc,~/.profile, and fish’sconfig.fish— plus~/.zshrc,~/.zprofile, and~/.bash_profileif they already exist. It checks for the directory first, so re-running does not duplicate lines.
Because installs are versioned directories and stable is just a symlink, an
upgrade is a symlink swap and the previous version is still on disk.
| Variable | Default | Effect |
|---|---|---|
FREECODE_HOME | ~/.freecode | where versions and all app state live |
FREECODE_INSTALL_DIR | ~/.local/bin (%LOCALAPPDATA%\freecode\bin on Windows) | where the launcher symlink goes |
Both are read by the installer only. Set them for every install, or not at all —
freecode uninstall ignores them (known gaps).
Verifying
freecode --version
which freecode # should be the launcher in your install dirThe version string comes from FREECODE_BUILD_VERSION, baked in at build time.
If it prints unknown, you are not running a release binary — most likely a
build from a clone.
Updating
Updating is always something you ask for:
freecode update # re-runs the installer
curl -fsSL https://freecode.website/install | bash # identical, without the binaryFreeCode tells you when there is one, and never installs it behind your back. Shortly after the TUI opens, a release binary asks the GitHub API once (3-second timeout) whether a newer release exists. If there is one, a line appears under the version in the header:
>_ OmaCode (v0.40.0)
update available (v0.40.0) · run freecode updateThat is the whole of it — run freecode update when it suits you.
The check runs after the first frame is on screen and is never awaited. It used to be awaited ahead of the TUI, which put a GitHub round-trip on the path to first paint: ~1.1s of blank terminal on every launch, measured at 1.68s vs 0.58s time-to-input-ready with the check disabled. Any failure — offline, rate-limited, GitHub down — is swallowed and no line appears.
This check does not run when you are working from a clone — there is no release
to compare against. To silence it, set FREECODE_NO_UPDATE=1 (an explicit
freecode update still works — that’s you asking).
Rolling back
Old versions are still in ~/.freecode/builds/versions/. To go back, run one
directly:
ls ~/.freecode/builds/versions
~/.freecode/builds/versions/0.25.15/freecodeIt stays on that version: nothing updates on launch, so running an old binary
keeps you there until you run freecode update. It will still show the
“update available” line; FREECODE_NO_UPDATE=1 silences that too.
Running from a clone instead
If you want to change FreeCode itself, install the monorepo rather than the binary — the backend is spawned from disk, so your edits take effect on the next run. See development setup.
One rule from that world is worth repeating here: never copy a pnpm build:sea artifact into ~/.freecode/builds/versions/. That build is a TUI
shell that does not bundle the backend and only works inside the monorepo;
dropping it where the installer expects a release binary gives you a freecode
that works in the repo root and is broken everywhere else.
Uninstalling
freecode uninstall # removes the binaries, keeps your data
freecode uninstall --dry-run # prints the list, deletes nothing
freecode uninstall --purge # also deletes ~/.freecode
freecode uninstall --force # skips the y/N promptIt prints what it will remove, then takes a freecode binary found in
/usr/local/bin, /usr/bin, ~/.local/bin, or ~/.cargo/bin, plus
~/.freecode/builds.
--purgeis the one that costs you something. Your sessions, rollout logs, per-project memory, prompt history, and usage data all live under~/.freecode/, and that flag is what deletes them. Nothing is backed up, so copy~/.freecode/projects/and~/.freecode/sessions/first if you might want them later.
There is also curl -fsSL https://freecode.website/uninstall | bash, for when
the binary itself is broken.
Known gaps
Found while writing this page; each is also tracked in TODO.md.
freecode uninstallignores the variables the installer honours. The handler hard-codes~/.freecodeand a fixed list of four Unix bin paths (cli/commands/uninstall.ts:44). An install done withFREECODE_HOMEorFREECODE_INSTALL_DIRset is not removed, and the Windows launcher in%LOCALAPPDATA%\freecode\binis not in the list at all — on Windows the command reports success while leaving the binary on PATH.- Nothing removes the PATH lines the installer wrote. Four or more rc files
get an
export PATH=…block appended; uninstalling leaves every one of them pointing at a directory that no longer exists.