Installing jcode on nix/NixOS: A Practical Unofficial Guide

Installing jcode on nix/NixOS: A Practical Unofficial Guide

jcode is an open-source AI coding agent
that runs as a local server and drives your editor. It's distributed as a
single self-contained executable, which sounds simple, until you try to run it
in a pure Nix environment
: no system package manager, no Nix channels, no
/usr/bin/env. This post walks through installing the official Nix build from
GitHub releases, the surprising gotchas you will hit, and how to fix them.

the beauty of jcode harness is that it can spawn an AI agents army with very little RAM overhead

What you need

  • A machine where the Nix store is present and mounted: a bwrap-nix sandbox,
    NixOS, or any host with nix installed. The jcode binary is dynamically
    linked against the glibc shipped in the store, so the store must be there at
    runtime.
  • curl and sha256sum for downloading and verifying the release.
  • A writable ~/.local/bin (or any directory on your PATH).

Step 1: Find the release

jcode publishes Nix builds as GitHub releases tagged nix-vX.Y.Z, for example
nix-v0.66.0. Each release carries one asset per platform:

jcode-nix-linux-x86_64

The release page shows the exact sha256 digest for every asset, so you can
verify your download:

curl -s https://api.github.com/repos/grigio/jcode/releases/tags/nix-v0.66.0 \
  | jq -r '.assets[] | .name + "  " + .digest'

Step 2: Download and verify

mkdir -p ~/jcode-install && cd ~/jcode-install
curl -sSL -o jcode-nix-linux-x86_64 \
  https://github.com/grigio/jcode/releases/download/nix-v0.66.0/jcode-nix-linux-x86_64
sha256sum jcode-nix-linux-x86_64

Compare the output against the digest published on the release page. For
v0.66.0 it is:

2faea9dc9f560e6f9a73da360d57b3c1d32f4ccfa90bbea2352237ba43472bb3  jcode-nix-linux-x86_64

A checksum mismatch means a corrupted download or a tampered asset. Stop and
re-download.

Step 3: Confirm it is a real executable

The Nix build is a genuine ELF binary, not a script. file should show a
dynamically linked PIE with a Nix store interpreter:

file jcode-nix-linux-x86_64
# ELF 64-bit LSB pie executable, x86-64, dynamically linked,
# interpreter /nix/store/<hash>-glibc-<ver>/lib/ld-linux-x86-64.so.2

Then check the version:

chmod +x jcode-nix-linux-x86_64
./jcode-nix-linux-x86_64 --version
# jcode v0.66.0 (nix-build)

Step 4: Install

Put the binary on your PATH:

mkdir -p ~/.local/bin
cp jcode-nix-linux-x86_64 ~/.local/bin/jcode
chmod +x ~/.local/bin/jcode
~/.local/bin/jcode --version

Replacing a running jcode: "Text file busy"

If you are upgrading and a jcode server is currently running from that path, a
plain cp fails with Text file busy. Linux refuses to truncate an executable
that is mapped by a live process. Copy to a temporary name and atomically
rename it instead:

cp jcode-nix-linux-x86_64 ~/.local/bin/jcode.new
chmod +x ~/.local/bin/jcode.new
mv -f ~/.local/bin/jcode.new ~/.local/bin/jcode

The old server keeps running from its in-memory image; the new version is used
by the next server start.

Step 5: Understand jcode's layout

jcode manages its own builds under ~/.jcode/builds/:

~/.jcode/builds/
  shared-server/jcode     # what the server actually launches
  stable/jcode            # the stable build
  versions/<version>/     # per-version builds from self-update
  shared-server-version   # version marker
  stable-version          # version marker

After a manual Nix install, point the shared-server and stable symlinks at
the real ELF in ~/.local/bin/jcode:

ln -sfn "$HOME/.local/bin/jcode" "$HOME/.jcode/builds/shared-server/jcode"
ln -sfn "$HOME/.local/bin/jcode" "$HOME/.jcode/builds/stable/jcode"

and keep the version markers in sync:

echo 0.66.0 > ~/.jcode/builds/shared-server-version
echo 0.66.0 > ~/.jcode/builds/stable-version

The Nix gotcha: self-update breaks the sandbox

jcode self-updates by downloading a new build into
~/.jcode/builds/versions/<version>/jcode and pointing shared-server/jcode
at it. That downloaded file is not the binary. It is a wrapper shell script
whose first line is:

#!/usr/bin/env sh

In a Nix-only environment /usr/bin/env does not exist (the env binary lives
in the store under coreutils), so execve(2) fails with ENOENT and the
server never starts. Verified with strace:

execve(".../.jcode/builds/shared-server/jcode",
       ["...", "--provider", "auto", "serve"], ...) = -1 ENOENT

Two equivalent fixes. Do one of them.

ln -sfn "$HOME/.local/bin/jcode" "$HOME/.jcode/builds/shared-server/jcode"

No wrapper, no interpreter, no breakage. This also pins the server to the
binary you installed instead of an untested self-update.

Option B: provide /usr/bin/env

Give the shebang what it wants by symlinking the store env into /usr/bin
(only possible when /usr/bin is writable):

ln -sf "$(dirname "$(readlink -f "$HOME/.local/bin/env")")/env" /usr/bin/env
# e.g. /nix/store/<hash>-coreutils-9.10/bin/env

Run the server

~/.jcode/builds/shared-server/jcode --provider auto serve

or directly:

~/.local/bin/jcode --provider auto serve

Notes:

  • Only one server instance may run per runtime dir. A second launch fails
    with Error: Another jcode server process is already running for runtime dir /tmp/<...>/jcode-<uid>. To restart, kill the existing PID first, then start
    again.
  • Verify the daemon is alive with jcode --version or by checking the runtime
    dir (/tmp/<...>/jcode-<uid>/) for jcode.sock and jcode-debug.sock.

Upgrading to a new release

The process is the same every time: download the new jcode-nix-linux-x86_64
asset, verify its digest, mv it over ~/.local/bin/jcode, re-run the
symlink command if anything changed, update the version markers, and restart
the server. The old binary can be kept as a rollback:

cp ~/.local/bin/jcode ~/.local/bin/jcode.v0.65.0.bak

Checklist

  • [ ] sha256sum matches the digest on the release page
  • [ ] file reports an ELF, not a shell script
  • [ ] ~/.local/bin/jcode --version prints jcode vX.Y.Z (nix-build)
  • [ ] shared-server/jcode and stable/jcode are symlinks to the ELF
  • [ ] version markers match the installed version
  • [ ] the server starts and binds its socket

Conclusion

Installing jcode on Nix is straightforward once you know the rules: download
the Nix-built ELF, verify it, drop it on your PATH, and keep jcode's own
symlinks pointed at the real binary instead of a self-update wrapper. The
/usr/bin/env trap is the one thing that will bite you, and Option A above
makes it a non-issue forever.