# Nanocodex is the agent loop as a library, installed by pipe to shell and updated hourly

> Nanocodex is a headless Rust SDK that hands you an OpenAI coding agent with an owned lifecycle rather than a model client and a loop you assemble. What it claims to remove is a specific list of five rebuilds, from replaying previous messages every turn to orphaning subprocess trees on cancellation. What it ships around that library is unusually wide: a native CLI, a macOS desktop app, a voice bundle, a credential vault, an SMS login flow, a micropayments client, and eight separate deployment targets.

**gakonst/nanocodex** — Building blocks for frontier OpenAI agents in Rust. Nanocodex empowers you with Codex-level performance anywhere.

- Repository: https://github.com/gakonst/nanocodex
- Website: http://docs.rs/nanocodex
- Stars: 540 · Forks: 71
- Language: Rust
- License: Apache-2.0
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/gakonst-nanocodex

## The product is five things you do not have to rebuild

The README states what this library is by listing what it saves you from, and that list is more informative than any feature list.

You do not pass previous messages, response identifiers, or tool results back on every turn.

You do not write a separate state machine for prompt ordering, steering, compaction, reconnect replay, or partially completed responses.

You do not couple receiving a typed result to consuming an event stream.

You do not leave orphaned shell sessions or subprocess trees when a turn is cancelled.

And you do not run a second orchestration runtime when an agent forks or delegates work.

That is the specification. Everything else in the repository, the loop, retained sessions, branches, retries, cleanup, the code mode, is the machinery that makes those five statements true.

The positioning is explicit too. It is a headless, library-first SDK, it is not a provider abstraction, and it is not an app server. One stack is deliberately supported.

The interface is deliberately excluded from the contract, and the wording is worth quoting in substance: consume ordered typed events in whatever renderer you want. The included renderers, a native terminal interface, a terminal emulator component, a JavaScript terminal component, a React component, and plain logs, are described as complete consumers rather than a UI protocol every embedding must adopt.

That is a sharper boundary than most agent libraries draw, and it is the part most likely to matter to you if you are embedding this.

## A Claude crate sits inside a single-provider workspace

The workspace manifest is a thirty four member list, and scanning it produces one result that contradicts the README.

Alongside crates for the OpenAI API and the OpenAI tools, with a separate macros sub-crate for them, there are two crates named for a different provider: one for the provider itself and one for its tools.

The README says the project supports one deliberately supported stack, says twice that it is not a provider abstraction, and lists the keyword for that provider in the manifest. So the documentation describes a single provider and the workspace contains a second.

There are several innocent explanations. The crate could be for translating a competitor's tool definitions into the internal representation so an agent trained on one schema can be pointed at another. It could be behind a feature flag. It could be a compatibility shim. The README does not say which, and the README does not mention the crate at all.

What it means for a reader is narrower and still worth knowing. If you are choosing a library partly because it refuses to be a provider abstraction, and the workspace carries a second provider's crates, then the abstraction line exists somewhere you cannot see from the documentation.

The rest of the member list is much easier to read as scope. There are separate crates for the agent, the managed mode, a phone client, a remote mode, durability, browser automation, computer use, egress, five voice crates, a virtual machine, observability, subagents, and two experimental crates for evaluation and its adapters.

## One member is the default, and the comment says why

The workspace declares thirty four members and then declares exactly one as the default, and the comment attached to it explains the reasoning.

The default member is the public library crate, and the manifest comment says root cargo commands target the public library facade, with a pointer to a task runner or an explicit package invocation for anyone who wants the executable.

That is a small decision with a large effect on a workspace this size. Without it, a bare build command at the root would compile the terminal interface, the account authentication binary, the two service binaries, every voice crate, and the browser and virtual machine crates. With it, the same command compiles the one crate most consumers depend on.

It is also a statement about what the project considers its product. Thirty four members exist and one is the default, and that one is the library rather than the CLI.

The workspace also excludes one path outright, a voice directory inside a third-party folder, which is a separate codebase rather than a member.

The rest of the shared metadata is ordinary and worth reading for compatibility: the workspace version, the edition, a minimum Rust version, the dual licence, the keywords, and the category markers that tell a registry indexer this is an asynchronous API binding rather than a command line tool.

## Python has no registry release, so Python means a source build

The install section is three languages, and one of them is a footnote.

Rust and Node are one line each, a cargo add and an npm install. Both are registry releases, and so is the core JavaScript binding.

Python is not. The README states that the Python binding and the JavaScript companion packages are currently built from a repository checkout, and then gives you five commands.

```sh
# Python 3.11+ (from a checkout)
uv venv --python 3.11 py/bindings/.venv
uv pip install --python py/bindings/.venv/bin/python 'maturin>=1.9,<2'
VIRTUAL_ENV="$PWD/py/bindings/.venv" \
  py/bindings/.venv/bin/maturin develop --manifest-path py/bindings/Cargo.toml
```

So a Python consumer needs a Rust toolchain, a specific major version of the maturin build tool, and a checkout. There is no wheel to install.

The Node story has a second wrinkle worth noting. The published package declares a consumer floor of one Node release line, and the repository's own package manifest declares a stricter engine requirement for development, and a pinned Node version file sits at the root alongside the package manager pin.

So you can install and run on the older line and you cannot build or develop on it. That is a normal split between consumer and developer support, and it is worth reading both numbers before you pin a base image.

## The installer is pipe to shell, and it installs an hourly updater

The native command line install is two lines, one per platform family, and the second thing those lines do is leave you with a background process.

```sh
curl -fsSL https://nanocodex.paradigm.xyz | bash
nanocodex
```

The Windows equivalent pipes a script into the interpreter. The stated scope is narrow: the script only selects and checksum verifies one platform bootstrap. So the pipe-to-shell pattern fetches a small chooser, and the checksum gate is on the binary it selects rather than on the script itself.

What happens next is where the operational weight is. With an interactive terminal, the installer immediately runs a setup command that does account sign-in by SMS, platform computer-use setup, the persistent background agent on that machine, and the browser extension prompt where one applies. The flow is described as idempotent and resumable, which is the right property for an installer that may be interrupted.

Then native code installs the matching CLI, the background agent, and the voice bundle, updates the shell path, and configures an hourly per-user updater through the platform scheduler on macOS, the Linux init system, or the Windows task scheduler.

Two details are worth pausing on. The updater is hourly and unattended, so running the installer is agreeing to let the project modify your machine once an hour. And the activation is described as transactional with the background agent on macOS and Windows, with the guarantee that a running agent is never silently restarted.

For upgrading from an older updater, the README says the CLI repairs its matching runtime automatically on first voice use, which is a fallback rather than a plan.

## Platform support is spelled out three ways and they do not match

The native binaries cover two architectures on macOS and Linux and one on Windows, and the names are explicit.

Apple Silicon macOS and x86-64 Linux with glibc for the first script. x86-64 Windows 10 or 11 for the second. No Intel macOS binary and no Windows on arm, which is a narrower story than the registry and the libraries imply.

The computer-use runtime is described differently again, and differently per platform. On macOS the CLI range-fetches only the signed upstream computer-use and browser-bridge components. On Windows it uses the official Microsoft Store package rather than fetching anything.

So the same feature is delivered two ways: partial range fetch on one platform, a store install on the other. That is a reasonable answer to code signing on Windows and a narrower one on macOS, but it means the install size and the failure modes are not comparable across platforms.

There is a repair command and an off switch, both spelled out. The repair command refreshes the runtime. One environment variable disables computer use entirely.

And there is a fallback path: every platform's background agent publishes a native controllable screen, and when no upstream provider is attached, the virtual machine and Cloudflare desktop agents expose that same native action schema through the same workdir-routed entry point. So the capability exists without the provider, just without the signed runtime.

## A credential vault, an SMS login, and a micropayments client

The environment template is the most revealing file in the repository, because it describes what the product actually does rather than what it claims.

One variable is genuinely required: the model provider key. Everything else in the file is commented out, and the comments explain what each one is for.

There is an SMS one-time-code login, implemented through a commercial messaging service that generates, delivers and checks six-digit codes, with an automatic upgrade to rich messaging where the carrier supports it. That is a full account provisioning flow, and it has its own signing key.

Then there is a credential vault. The comment is specific: production deployments require a base64url encoded thirty-two byte key, it encrypts provider credentials and persistent account root wallets at rest, and it must be configured as a worker secret or a secrets store binding, never as browser or Vite configuration. Local development falls back to a fixed development-only key when it is unset.

And there is a previous-key variable, which exists so that encryption can be rotated without a downtime window. That is a mature detail and it is mentioned in a comment.

Then the optional connectors: a music service using PKCE with no client secret, and a second one needing a client secret. Then a reasoning-effort default. Then a build profile switch. Then a credits client, which talks to a local service by default, and a second model provider that pays a charge challenge through that service with a wallet store and an RPC address.

So the picture is an agent that holds encrypted provider credentials, signs into accounts by phone, and can pay for compute.

## No stable release exists, and there are eight deploy targets

Two repository level facts to end on, both of which affect how you deploy.

The first is the release train. All three recent releases are nightlies. Two are tagged with a full commit hash and titled with the date and a short hash. The third is tagged with the bare word nightly and is dated two months before the other two, which is either a stale tag or a rolling pointer that has not moved.

There is no stable version among them. Meanwhile the workspace declares a plain version number in its shared metadata and marks itself publishable, which is the crates.io path. So a Rust consumer pinning a version from the registry and a user installing the command line from a release are on different version lines, and only one of them has a stable number.

The second is deployment surface. The monorepo manifest has eight separate deploy scripts, each one filtering a different service package and running its own deploy. Egress, an API, a managed service, a dialog, another API, a chief-of-staff service, a playground, and the web app.

That is eight independently deployed units from one repository, and each script builds its package first. It is a fair structure for a monorepo with a shared library, and it is also eight things that can be deployed at different versions of the same library.

The development server adds one more wrinkle: it starts a proxy on port 443, which needs a certificate trust step and on macOS an administrator approval, with a documented port override that appends a suffix to every route name instead.

## Conclusion

Nanocodex suits someone building a product on top of a coding agent rather than using one, since the ownership model and the ordered typed event stream are the actual product and everything else in the repository exists to prove the contract holds across a CLI, a desktop app, browser clients, and durable actors. Three things to know before you commit. The Python binding and the JavaScript companion packages are not on a registry and must be built from a checkout, so a Python deployment is a source build. The bootstrap is a pipe to shell that installs an hourly per-user updater through the platform scheduler, which is a standing background process you are agreeing to. And the workspace contains a crate for a second model provider in a repository whose stated scope is a single supported stack, so read the member list before you rely on that framing.

## FAQ

### What is Nanocodex and what does the library handle for me?

It is a headless, library-first Rust SDK that embeds the OpenAI Responses loop with retained sessions, typed history, tools, branches, events, retries and cleanup. It removes the need to replay messages every turn, write a state machine for prompt ordering and compaction, couple typed results to an event stream, orphan subprocess trees on cancellation, or run a second orchestration runtime when an agent forks.

### Does Nanocodex force a UI on me?

No, and that is deliberate. The interface is explicitly excluded from the library contract. You consume ordered typed events in a native terminal interface, a terminal emulator, a React component, logs, or your own renderer. The included renderers are described as complete consumers rather than a protocol every embedding must adopt.

### Can I install Nanocodex for Python from a package index?

Not currently. The Rust crates and the core JavaScript binding are registry releases, but the Python binding and the JavaScript companion packages must be built from a repository checkout using a virtual environment, the maturin build tool, and a manifest path, so a Python consumer needs a Rust toolchain.

### What does the Nanocodex installer do beyond installing the CLI?

With an interactive terminal it runs a setup command covering SMS account login, computer-use setup, the persistent background agent, and a browser extension prompt. Native code then installs the matching CLI, background agent and voice bundle, updates the shell path, and configures an hourly per-user updater through the platform scheduler. The flow is described as idempotent and resumable.

### What are the host requirements for Nanocodex?

The published package supports Node.js from one release line upward while the monorepo requires a newer line for development, with the version pinned in a file at the root. Native binaries are built for Apple Silicon macOS and x86-64 Linux with glibc, plus x86-64 Windows 10 and 11; there is no Intel macOS binary and no Windows on arm.

### Does Nanocodex ship stable releases?

Not on the repository. All three recent releases are nightlies, two tagged with a full commit hash and titled with the date and a short hash, and one with a bare nightly tag dated two months earlier. The version number that matters for Rust consumers is the workspace version published to the crates registry.

## Sources

- [gakonst/nanocodex on GitHub](https://github.com/gakonst/nanocodex)
- [License: Apache-2.0](https://github.com/gakonst/nanocodex/blob/master/LICENSE)
- [Project website](http://docs.rs/nanocodex)
- [README](https://github.com/gakonst/nanocodex/blob/master/README.md)
- [Releases](https://github.com/gakonst/nanocodex/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/gakonst-nanocodex
