> ## Documentation Index
> Fetch the complete documentation index at: https://smithers.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Nanocodex

> Run the pinned stock Nanocodex agent as a short-lived, checkpoint-aware Smithers worker.

`NanocodexAgent` connects Smithers to the external
[`smithers-nanocodex`](https://github.com/N0xMare/smithers-nanocodex)
bridge. The adapter does not bundle or download the executable at runtime. You
build, qualify, and install the pinned-source artifact separately, then select it with
`binary` or `PATH`.

The v0.0.1 integration is deliberately fixed: one fresh `serve` worker and one
stock Nanocodex turn per `generate()` call. There is no daemon, worker pool, or
bridge-session reuse. `generate()` also performs a short, provider-free
capability check before starting that worker.

## Requirements

* Linux x64 with the `x86_64-unknown-linux-gnu` ABI
* glibc 2.35 or newer; Ubuntu 22.04 is the oldest supported baseline
* [Bubblewrap](https://github.com/containers/bubblewrap) at `/usr/bin/bwrap` or
  `/bin/bwrap`, with usable private PID namespaces; other locations and `PATH`
  lookup are not trusted, and the adapter fails closed if neither path works
* Smithers on Node.js 22 or Bun 1.3 or newer

macOS, Windows, Linux arm64, musl, and older glibc versions fail before the
bridge starts. Install Bubblewrap with your distribution package manager. On
Ubuntu:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
sudo apt-get update
sudo apt-get install -y bubblewrap
```

## Build the pinned release from source

Smithers assigns source-build provenance only to an artifact matching the
checked-in pin produced from the exact source commit below. Smithers does not
record, execute, or qualify the published `v0.0.1` binary.

The qualified consumer pin is:

| Field                 | Value                                                              |
| --------------------- | ------------------------------------------------------------------ |
| Release               | `v0.0.1`                                                           |
| Source repo           | `N0xMare/smithers-nanocodex`                                       |
| Source commit         | `56d8b4fd54bf14e9f2874e5a010b8e301f8f695b`                         |
| Source tree           | `b8a092569e579c21e2ae288a470a6881022b61f2`                         |
| `Cargo.lock` blob     | `808504efe6b6ea6c43705205ca3182be0dee1afe`                         |
| Rust toolchain        | `1.97.0`                                                           |
| Target                | `x86_64-unknown-linux-gnu`                                         |
| Source-build bytes    | `6286499`                                                          |
| Source-build SHA-256  | `3348b8a7818b4c759748e2cf0ecc9e0e4857f33ef6c3a92417655bfc0c73fdff` |
| Maximum archive bytes | `8388608`                                                          |

Build and install that artifact:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
target=x86_64-unknown-linux-gnu
package="smithers-nanocodex-v0.0.1-${target}"
archive="${package}.tar.gz"
artifact_dir="$(mktemp -d)"
smithers_checkout=/absolute/path/to/smithers

git clone https://github.com/N0xMare/smithers-nanocodex
cd smithers-nanocodex
git checkout 56d8b4fd54bf14e9f2874e5a010b8e301f8f695b
test "$(git rev-parse HEAD)" = 56d8b4fd54bf14e9f2874e5a010b8e301f8f695b
test "$(git rev-parse 'HEAD^{tree}')" = b8a092569e579c21e2ae288a470a6881022b61f2
test "$(git hash-object Cargo.lock)" = 808504efe6b6ea6c43705205ca3182be0dee1afe

rustup toolchain install 1.97.0 --profile minimal
RUSTUP_TOOLCHAIN=1.97.0 \
RUSTFLAGS="--remap-path-prefix=$PWD=/usr/src/smithers-nanocodex" \
  cargo build --locked --release --target "$target"

# Package deterministically so the qualification command can inspect it.
install -d -m 0755 \
  "$artifact_dir/$package" \
  "$artifact_dir/$package/docs" \
  "$artifact_dir/$package/third-party"
install -m 0755 "target/${target}/release/smithers-nanocodex" "$artifact_dir/$package/"
install -m 0644 README.md LICENSE "$artifact_dir/$package/"
cp -R docs/. "$artifact_dir/$package/docs/"
find "$artifact_dir/$package/docs" -type d -exec chmod 0755 {} +
find "$artifact_dir/$package/docs" -type f -exec chmod 0644 {} +
install -m 0644 third-party/README.md third-party/THIRD-PARTY-LICENSES.html \
  "$artifact_dir/$package/third-party/"
source_date_epoch="$(git log -1 --format=%ct)"
tar --sort=name --mtime="@${source_date_epoch}" \
  --owner=0 --group=0 --numeric-owner \
  --pax-option=delete=atime,delete=ctime \
  -C "$artifact_dir" -cf - "$package" | gzip -n -9 > "$artifact_dir/$archive"

# From a Smithers checkout with dependencies installed, inspect this archive.
node "$smithers_checkout/scripts/qualify-nanocodex-release.mjs" \
  --archive "$artifact_dir/$archive"

# Install only if the report says artifactProvenance is
# "pinned-source-build-sha256".
sudo install -m 0755 "$artifact_dir/$package/smithers-nanocodex" \
  /usr/local/bin/smithers-nanocodex
```

Smithers validates every tar header and rejects path traversal, links, devices,
extended headers, duplicate paths, and anything outside the exact package root
before using the executable. A locally built archive that differs from the checked-in
pin can still receive the provider-free behavioral report, but its
`artifactProvenance` is `unverified-input` and its source fields are `null`.

## Configure the adapter

With the executable on `PATH`, no binary option is needed:

```tsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { NanocodexAgent } from "smthrs";

const agent = new NanocodexAgent({
  cwd: "/absolute/path/to/workspace",
  thinking: "high",
  reasoningMode: "standard",
});
```

Set `binary` to an executable name resolved through `PATH` or to a path. The
adapter resolves and canonicalizes the executable during preflight.

```tsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
const agent = new NanocodexAgent({
  binary: "/opt/smithers/bin/smithers-nanocodex",
  cwd: "/srv/workspaces/project",
  inheritEnv: false,
  env: {
    PATH: "/usr/local/bin:/usr/bin:/bin",
    NANOCODEX_OPENAI_KEY: process.env.NANOCODEX_OPENAI_KEY!,
  },
  auth: {
    mode: "api-key-env",
    environmentVariable: "NANOCODEX_OPENAI_KEY",
  },
});
```

When `inheritEnv` is `false`, ambient process variables are not inherited. The
`serve` worker receives variables configured in `env` plus any Smithers
task-context identifiers supplied for the call: `SMITHERS_RUN_ID`,
`SMITHERS_NODE_ID`, `SMITHERS_ITERATION`, and `SMITHERS_ATTEMPT`. Include `PATH`
in `env` if `binary` is a command name; ambient `PATH` is not used in this mode.
Prompts, credentials, and snapshots never appear in process arguments.

## Authentication

API-key mode is the default and reads `OPENAI_API_KEY`. You can name another
bridge-process environment variable as shown above. The credential value stays
out of protocol JSON, although same-UID host processes may still inspect the
bridge environment through facilities such as Linux `/proc`.

Managed ChatGPT mode uses the normal Nanocodex/Codex auth file or an explicit
absolute path:

```tsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
const agent = new NanocodexAgent({
  auth: {
    mode: "chatgpt",
    authFile: "/home/worker/.codex/auth.json",
  },
});
```

Within one Smithers JavaScript process, managed-ChatGPT `generate()` calls that
resolve to the same canonical auth file are FIFO-serialized across
`NanocodexAgent` instances. The gate covers the `serve` worker through verified
process closure; provider-free preflight may still run concurrently, and the
gate releases before checkpoint publication. Calls using different auth files
and all API-key calls remain concurrent. A queued caller may abort promptly,
but later waiters do not overtake the active call.

This serialization is process-local. Do not run another Smithers process,
Nanocodex bridge, or other credential-refreshing process against the same auth
file concurrently.

`preflight()` checks the host, executable, namespace profile, and declared
target/version/capability surface without loading credentials or contacting a
provider.
The actual managed-ChatGPT adapter suite is
`packages/agents/tests/nanocodex-live.test.js`. It is opt-in/manual through
`SMITHERS_RUN_NANOCODEX_LIVE=1`, not part of normal package-test execution, and
must run only in a trusted environment. The engine cold-restart suite at
`packages/engine/tests/nanocodex-live-workflow.test.js` uses the same opt-in
gate. Never enable either suite in a fork pull request or any job that exposes
repository secrets.

## Fixed v0.0.1 surface

| Capability                               | v0.0.1 behavior                                            |
| ---------------------------------------- | ---------------------------------------------------------- |
| Model                                    | Stock Nanocodex 0.3.0, fixed `gpt-5.6-sol` adapter model   |
| Native tools and Code Mode               | Enabled                                                    |
| Transport                                | WebSocket preferred, with stock sticky HTTPS fallback      |
| Checkpoints                              | `nanocodex.session-snapshot/1`, resume only                |
| Structured output                        | Prompt-based Smithers extraction, not native schema output |
| JavaScript tools and MCP                 | Unsupported                                                |
| Subagents and steering                   | Unsupported                                                |
| Custom provider endpoints                | Unsupported                                                |
| Code Mode disablement                    | Unsupported                                                |
| Workspace relocation and checkpoint fork | Unsupported                                                |

`instructions` replaces the stock instructions completely. Per-call system
messages, JavaScript tools, provider options, and `resumeSession` are rejected.

## Checkpoints and workspace identity

Each completed turn returns a durable Smithers checkpoint containing the exact
opaque Nanocodex snapshot. Resume is accepted only when the checkpoint's
`canonicalWorkspace` exactly matches the current canonical workspace, along
with the bridge, Nanocodex, snapshot, codec, and policy versions. Moving a
checkpoint across worktrees, machines, symlink-resolved roots, or absolute
workspace paths is unsupported. Fork mode is unsupported.

Treat checkpoints as secrets. A snapshot may contain conversation context,
tool results, source material, paths, or credentials that the agent read.
Smithers validates and bounds the envelope but does not sanitize the opaque
snapshot.

## What Bubblewrap contains

The adapter requires this PID namespace profile:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
bwrap \
  --unshare-pid \
  --die-with-parent \
  --new-session \
  --bind / / \
  --proc /proc \
  --dev-bind /dev /dev \
  -- /bin/true
```

This profile makes descendant membership and cleanup authoritative, including
detached native-tool processes. It is PID containment only. It is **not**
filesystem, network, device, or credential isolation: `/` is bound read-write,
host networking remains available, `/dev` follows host permissions, and
readable auth files and environment credentials remain reachable. Use a
stronger external mount, environment, network, or credential-broker policy when
your deployment requires those boundaries.

## Qualify the release

`packages/agents/tests/fixtures/nanocodex/source-build-v0.0.1.json` records the
pinned source build and provider-free adapter preflight. It makes no checksum
claim about the separately published release artifact.

From a Smithers checkout on a supported host, this command inspects a local
archive and runs the public adapter preflight:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
node scripts/qualify-nanocodex-release.mjs \
  --archive /absolute/path/to/smithers-nanocodex-v0.0.1-x86_64-unknown-linux-gnu.tar.gz
```

`--archive` is required. The command reads no remote source, rejects the input
unless it is a non-empty regular file no larger than 8 MiB, computes its
SHA-256, and safely inspects its layout. Only the pinned source-build digest and
size receive `pinned-source-build-sha256` provenance; every other input is
explicitly reported as `unverified-input`, with no source commit or tree claim.

A direct local invocation does not itself initiate a network request, but the
probed executable retains the PID-only adapter profile's host networking. Add
an external network boundary when running an untrusted local input.

In a temporary scratch workspace, the verifier materializes the archive
executable and bounded probe launchers. It runs exact-version and
full-capability probes, then invokes public `NanocodexAgent.preflight()` against
the same path with `inheritEnv: false` and an empty environment. Neither probe
performs a model turn or needs a provider credential. Scratch state is removed
on success or failure.

**See also:** [`NanocodexAgent` reference](/reference/agents#nanocodexagent) ·
[`NanocodexAgentOptions`](/reference/types) ·
[`smithers-nanocodex` v0.0.1 tag](https://github.com/N0xMare/smithers-nanocodex/releases/tag/v0.0.1)
(source reference; the release's prebuilt binary is not qualified by Smithers)
