# Installing jcode on nix/NixOS: A Practical Unofficial Guide

> Source: <https://grigio.org/installing-jcode-on-nix-nixos-a-practical-unofficial-guide/>
> Published: 2026-08-03 14:16:03+00:00

# Installing jcode on nix/NixOS: A Practical Unofficial Guide

[jcode](https://github.com/1jehuang/jcode?ref=grigio.org) 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 itin a pure Nix environment](https://github.com/1jehuang/jcode/issues/115?ref=grigio.org): no system package manager, no Nix channels, no

`/usr/bin/env`

. This post walks through installing the official Nix build fromGitHub releases, the surprising gotchas you will hit, and how to fix them.

## 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:

``` bash
#!/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.

### Option A (recommended): point shared-server at the real binary

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