Skip to Content
Getting startedInstallation

Installation

One command, one binary, no runtime to install first.

curl -fsSL https://freecode.website/install | bash

On 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 | iex

Then, in any project:

freecode

If 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):

  1. Detects your platform and picks one release artifact — linux-x86_64, linux-aarch64, macos-aarch64, macos-x86_64, or windows-x86_64.

  2. Resolves the latest release through the GitHub API.

  3. Downloads an archive, not a bare binary. The .tar.gz (.zip on Windows) holds the executable and the ONNX Runtime shared library the memory-graph embedder loads at runtime — bun build --compile cannot embed a native .so/.dylib, so it ships beside the binary.

  4. 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
  5. Clears the macOS quarantine flag on the unpacked directory, so Gatekeeper does not block the binary or the .dylib it loads.

  6. Adds the install directory to PATH by appending an export line to ~/.zshenv, ~/.bashrc, ~/.profile, and fish’s config.fish — plus ~/.zshrc, ~/.zprofile, and ~/.bash_profile if 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.

VariableDefaultEffect
FREECODE_HOME~/.freecodewhere 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 dir

The 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

Three things update FreeCode, and the third one is the one to know about:

freecode update # re-runs the installer curl -fsSL https://freecode.website/install | bash # identical, without the binary

FreeCode also updates itself on launch. A release binary checks the GitHub API once per start with a 3-second timeout; if a newer release exists it runs the installer and re-execs through ~/.freecode/builds/stable/freecode, so the TUI you land in is already the new version (apps/tui/src/entry.ts:56). Any failure — offline, rate-limited, install error — is swallowed and your current version opens.

The re-exec goes through the stable symlink rather than the path of the running binary, deliberately: the kernel resolves symlinks at exec time, so re-running your own process.execPath would launch the old version again and you would have to quit and retype freecode to actually get the update.

This check does not run when you are working from a clone — there is no release to compare against. To turn it off, 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/freecode

To stay on it, set FREECODE_NO_UPDATE=1 — otherwise that binary performs the same update check at launch, installs the latest release, and re-execs you into it.

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 prompt

It 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.

--purge is 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 uninstall ignores the variables the installer honours. The handler hard-codes ~/.freecode and a fixed list of four Unix bin paths (cli/commands/uninstall.ts:44). An install done with FREECODE_HOME or FREECODE_INSTALL_DIR set is not removed, and the Windows launcher in %LOCALAPPDATA%\freecode\bin is 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.
Last updated on