Skip to content

Repository files navigation

Nakode

Nakode is a provider-neutral agent server for orchestration, continuity, and execution. It owns the workspace runtime and canonical session state while replaceable frontends provide the interface. The included TUI is one thin client, not the application authority.

Nakode is experimental and under active development.

Developers and coding agents can drive the real TUI controls and renderer through the deterministic JSON Lines TUI evaluation harness. Alternative interfaces can use the same native server through the generated API and SDK; the TUI is one renderer of server-owned semantic state. Background clients can read a bounded scalar session status inventory through one SDK query without keeping a renderer or transcript subscription alive.

Explicit image handoffs

Use prepare_image to inspect or explicitly crop/downscale conversation images, then select their references in nakode_agent.image_references. Images accompany the first delegated task and remain visible after transcript restoration. Public SDK clients use GetSessionImage and Delegate. See usage, limits and provider constraints.

Existing image replies

Native tool sessions on Linux/macOS can use return_image({"path":"relative/image.png"}) to attach an existing workspace image to the assistant transcript. This is not image generation. The tool requires filesystem-read permission and accepts PNG, JPEG, GIF and WebP, up to 5 MiB per image, eight images and 20 MiB per turn. Nakode retains the bytes in native-session history and exposes them through public transcript artifacts; deleting the source file does not remove the retained reply. Image bytes are not echoed into provider tool-result text. Compatibility harness adapters are not guaranteed to expose this native tool. Image-input support still belongs to the selected model. Prompt input may contain images without text.

Architecture boundary

The background Nakode service manages every session, turn, queue, provider, tool, artifact, setting, and orchestration run. It performs all operations and mutations, persists canonical state, and continues active work without an attached client.

nakode is that service. Run it directly:

nakode start            # background, returns once it accepts connections
nakode run              # foreground until Ctrl-C
nakode status           # version, process, endpoint, capabilities, log path
nakode status --json
nakode logs -f          # tail the captured service log
nakode restart
nakode stop

start and stop are safe to repeat: an already-running service reports that it is running rather than starting a second one, and stopping a stopped service succeeds. restart starts a stopped service as well as replacing a running one.

One installation-wide service owns the endpoint, provider registry, credentials, transports, and persistence for every session. Working directories and filesystem/tool access remain properties of individual sessions and are supplied by the frontend creating them, never by lifecycle CLI flags.

Remote client access is opt-in and additive to the private Unix endpoint:

nakode remote enable --bind 10.0.0.8:7342 --endpoint executor.example:7342
nakode restart                              # applies listener or credential changes
nakode remote check --endpoint executor.example:7342
nakode remote descriptor --endpoint executor.example:7342
nakode remote regenerate-key --endpoint executor.example:7342
nakode remote rotate-credentials --endpoint executor.example:7342
nakode remote disable                       # restart removes the TCP listener

enable is idempotent: reruns preserve the stable server ID, API key, and TLS certificate while repairing enablement or changing the bind address. regenerate-key revokes only the bearer key; rotate-credentials replaces both key and pinned certificate. Both require a service restart. check performs a real pinned-TLS and authenticated GetServerInfo call and rejects API/server-ID mismatch. A wildcard bind needs a separate reachable --endpoint in enrollment output.

The descriptor contains a random 256-bit bearer key and pinned self-signed TLS identity; handle it as a secret. The installation keeps a stable server ID across key regeneration. Remote frontends use the same nakode.v1 service, including read-only InspectWorkspacePath for server-side canonical path and Git placement checks. A workspace request of ~ or ~/… resolves against the Nakode service runtime user's authoritative home on the execution host; failures name the resolved server path and filesystem cause. Nakode remains the sole session, provider, tool, persistence, lifecycle, and resumability authority.

After installation, Nakode preserves an already-current singleton, restarts it only when it is stale and quiescent, and retires quiescent legacy per-workspace services. Legacy services with active work are left running and reported rather than killed.

The interactive terminal client is one frontend over that service. It derives the new session's working directory from its own current directory:

cd /path/to/project
nakode --tui

The earlier nakode service <action> spellings still work. Each prints a deprecation notice on standard error naming its replacement, then does the work.

Every frontend—including the built-in TUI—only:

  • obtains authoritative state through the generated SDK;
  • maps user intent to distinct typed SDK methods; and
  • renders that state while retaining only ephemeral presentation concerns such as drafts, focus, selection, scrolling, viewport, and device integration.

Frontends never open Nakode's database, connect directly to providers, execute tools, reduce provider events, or decide session and queue policy. This is a hard project boundary: a new capability must be implemented in the server, exposed through proto/nakode/v1/nakode.proto, represented in the SDK, and only then rendered by clients. See Building a Nakode frontend and the SDK architecture.

What does it do?

Nakode brings agentic coding work into a single terminal experience:

  • Run coding agents against a local workspace.
  • Inspect and edit files, search code, run commands, and track task progress.
  • Stream responses, reasoning, plans, tool activity, and diffs as work happens.
  • Resume saved sessions and continue long-running work.
  • Queue follow-up prompts, interrupt active work, and switch models.
  • Delegate bounded investigations to independently tracked agents, including parallel research across providers.
  • Carry work between providers with an explicit continuity handoff instead of claiming that private model context can be transferred.

The longer-term direction is a provider-neutral orchestration and continuity layer where logical work can span multiple agents, models, and providers. That includes richer delegation and review workflows and durable project memory. These are product goals, not all current features.

Supported providers

Nakode currently supports:

  • OpenAI Codex
  • Claude
  • Devin
  • Cursor
  • Kimi For Coding
  • GLM Coding Plan (z.ai)

Providers are disabled on a fresh installation. Start Nakode, open /providers, and sign in to the providers you want to use. Press F2 to browse and select from their available models. Provider details can independently enable a model filter and select exact provider/model IDs from a searchable, scrollable catalogue. Filtering defaults off. When enabled it changes ordinary model discovery only: exact persisted or explicitly requested IDs remain addressable, and stale selected IDs remain visible rather than being substituted. A filter whose selection no longer matches any discovered model (for example an enabled filter with an empty selection) fails open and shows the provider's full catalogue, since silently hiding every discovered model is never the intent of a selection that selects nothing.

Nakode does not require the separate Codex, Devin, Kimi, or z.ai applications. OpenAI Codex sign-in uses the normal browser OAuth flow by default and returns to Nakode through a localhost callback; Nakode then persists and refreshes the OAuth credential. Embedders can retain device-code authentication by explicitly calling BackendConfig::with_device_code_authentication. Claude uses the official Claude Agent SDK and the login managed by an installed Claude Code CLI; install Claude Code and run claude auth login before connecting Claude in /providers. Claude requires Node.js 18 or newer plus npm. Nakode stores only an external-login marker, not Claude OAuth credentials; Claude Code continues to own its configuration and keychain entries. Agent SDK activity is subject to Anthropic's current subscription eligibility, usage limits, and third-party application policies. Cursor uses its local TypeScript SDK and requires Node.js 22.13 or newer plus npm. Cursor, Kimi, and GLM setup in /providers includes an API-key field and a link to the provider's API-key dashboard. Kimi requires a Kimi Coding Plan API key; Moonshot Platform API keys are a separate product and are not interchangeable. GLM requires a z.ai GLM Coding Plan API key and uses the plan's dedicated Coding API endpoint; Team Plan members must use their Team Plan key. No single provider defines Nakode's workflow or session model.

Installation

Nakode requires Git and Rust 1.88 or newer. Source is hosted on GitHub. Install Nakode with this command:

mkdir -p "$HOME/.nakode" && \
  git clone https://github.com/QuillDev/nakode.git "$HOME/.nakode/src" && \
  "$HOME/.nakode/src/install.sh"

This keeps the managed source checkout in ~/.nakode/src and installs the nakode executable to ~/.local/bin. If that directory is not already in your PATH, the installer prints the line to add to your shell profile. Do not run Nakode or the entire installer through sudo; provider sign-in uses your normal desktop account.

Update the checkout, rebuild Nakode, and replace the installed executable with:

nakode update

nakode update retargets a recognized Cursor Origin or non-canonical GitHub remote to https://github.com/QuillDev/nakode.git, then runs git pull --ff-only in the managed source checkout and that checkout's install.sh. The checkout is $NAKODE_HOME/src when NAKODE_HOME is set, or $HOME/.nakode/src otherwise. An explicit --prefix must be absolute; --no-activation leaves running-service activation to the supervisor (and is also accepted as --supervisor-owned). nakode --update remains supported as a convenience alias with the default installation options.

For local development in another checkout, ./install.sh --debug reuses the development build for much faster iteration, at the cost of a larger and less optimized installed executable. Run ./install.sh --help for system and custom-prefix options.

Reset every session

To return Nakode to a clean, first-run session state:

nakode purge-unsafe

The command prints a warning and then asks for confirmation with a default-negative [N/y] prompt. Only an explicit y or Y proceeds; an empty line, n, end-of-input, and any unrecognized answer abort without changing anything. This is deliberately interactive and has no force or bypass flag, so it cannot be scripted by accident.

On confirmation it first stops every discoverable workspace service through its lifecycle socket, so each server terminates its own provider children, shell processes, delegated runs, and frontend transports before persistence is touched. Stale socket sets left by a dead server are removed. It then deletes every logical session, delegated orchestration run, agent turn, and native runtime history — including orphaned histories from dead or partially initialized sessions that ordinary close-first deletion cannot clear.

Provider credentials, provider enablement, default-model preferences, global add-on configuration such as web and memory settings, installed providers, and repository contents are outside the purge boundary and survive it. The command reports what it removed and reports failures instead of claiming success, and running it again on an already-clean install is a no-op.

Start Nakode

Open a terminal in the project and start the TUI. Each invocation creates a new logical session rooted at that current directory:

cd /path/to/project
nakode --tui

Then use /settings to manage general preferences, agents, models, providers, and optional add-ons. The settings menu is searchable. /providers, /agents, and /models remain available as direct shortcuts.

Global agents

Sub-agent archetypes are global to the user rather than tied to a project workspace. Nakode stores them as TOML files under $NAKODE_HOME/agents; when NAKODE_HOME is unset it defaults to ~/.nakode, so the ordinary catalogue is ~/.nakode/agents. Every workspace loads the same catalogue.

A definition names the archetype (slug, description), what it is told (system_prompt, first_message), and how it runs: model, fallback_models, fast_mode, and an optional reasoning_effort. Effort belongs to the model that runs at it, so reasoning_effort is refused without a model and refused when that model does not offer the level named. Omit it and the delegated run uses the model's own default level, which is what every definition written before the field means — nothing on disk needs editing. fast_mode = true is an affirmative request available only when the discovered model advertises it. false does not request a slow tier; it leaves ordinary provider behaviour unchanged. An inherited or fallback model is checked after it resolves, before Nakode projects options onto the delegated session.

CreateSession.initial_instructions is stored separately from accepted user prompts in logical session metadata. Pending-session recovery restores the creation-time instructions, and logical provider transitions preserve them. A new logical session clears the previous session's client instructions. Legacy rows without this metadata remain absent: Nakode does not infer instructions from old user messages or silently rewrite transcript history. Provider-native resume continues to use that adapter's persisted context.

New delegations require a concise, task-specific title (1–120 characters) separate from the full assignment. The native nakode_agent tool and compatibility delegation tool require title; DelegateRequest.title and the SDK delegation methods carry it to the server. The CLI requires --title, for example:

nakode agent repo-explorer --session-id SESSION_ID \
  --title 'Audit session persistence' --task 'Trace session creation and report persistence gaps.'

The server validates and persists the title independently of the objective and exposes it as RunState.title. Legacy runs retain an absent title; continuation runs inherit their source title. An explicit CreateSession.title also remains the logical session title instead of being replaced by its first prompt. Callers using the updated delegation API must supply titles; old calls without one are rejected rather than assigned a task-derived title.

Owner-defined definitions additionally carry ownership and availability, canonical capability/tool allow and deny lists, a tool profile (none, read_only, command_runner, bounded_watcher, or custom), task/output contracts, bounded lifecycle values, fallback policy, and delegation/parent attribution policy. Shipped built-ins are visible but immutable. Nakode validates these fields against its live provider/model catalogue, persists create/update/rename atomically, and remains the sole runtime authority; unavailable choices are reported rather than silently replaced. Native Codex, Devin, GLM, and Kimi sessions receive an authoritative Nakode builtin-tool allowlist, while Claude applies the equivalent SDK allowlist and permission hook. Empty custom policy retains compatibility with definitions written before policy fields existed.

Catalogue changes are loaded without restarting the installation-wide service. After installing a Nakode binary whose public protocol changed, the installer refreshes a quiescent stale singleton and retires quiescent legacy per-workspace services. Active legacy services remain available until their work finishes.

slug = "code-reviewer"
description = "Reviews changes for correctness"
model = "openai-codex/gpt-5.6-sol"
reasoning_effort = "high"   # omit for the model's own default

Use --agents PATH or NAKODE_AGENTS=PATH to override the catalogue. Absolute paths are used as written; relative paths resolve under Nakode home, not under the current workspace. Nakode does not automatically import existing workspace-local .nakode/agents directories; move wanted definitions into the global directory or point --agents at an absolute compatibility directory.

Personalities and Soul

Nakode can append user-specific guidance to every newly created native agent session. By default it looks in the platform configuration directory for personalities.toml and an optional SOUL.md (for example, ~/.config/nakode/ on Linux). It never creates either file.

personalities.toml supports a global default and provider-qualified, per-model overrides:

default = """
Be warm, direct, and explain important tradeoffs.
"""

[models]
"openai-codex/gpt-5.4" = """
Prefer terse answers and make implementation decisions confidently.
"""
"zai-coding/glm-4.7" = """
Show a short plan before changing code.
"""

An exact model entry replaces the default personality for that model. Models without an entry use default. Empty values are ignored. Model keys must use the canonical provider/model form.

SOUL.md describes who the agent is—identity, enduring preferences, and style controls. Nakode has one configured Soul, not one per model or workspace. When present, it is always appended independently of the selected personality, including for delegated agents. Owner-facing clients can read and atomically save this exact file through GetSoul / SaveSoul; saves use the last-read digest so conflicts remain explicit. The default is the platform Nakode config directory's SOUL.md; --soul PATH / NAKODE_SOUL selects the same singleton at another path.

Personality and Soul content is snapshotted when a Nakode logical session is created, and that snapshot is reused by its primary and delegated provider sessions. A successful API save is therefore visible to newly created logical sessions through the installation-wide service; already-running and resumed sessions retain the instructions they started with. Personality and Soul are followed by a protected runtime boundary, so owner content cannot replace security, tool-policy, delegation-limit, objective-mismatch, or run-attribution requirements. Direct file edits do not mutate materialized session snapshots; /reload remains the explicit way to refresh one.

Use --personalities PATH / NAKODE_PERSONALITIES and --soul PATH / NAKODE_SOUL to select other files. Relative explicit paths are resolved from the workspace. Explicit paths must exist at startup; the default files are optional, and SaveSoul can deliberately create the missing default file.

Terminal image previews

Sent image attachments render inline when Nakode detects Kitty, WezTerm, Ghostty, iTerm2, Sixel, or another protocol supported by ratatui-image. Configure the default under /settingsAdd-onsTerminal images:

  • Automatic uses terminal hints and a capability query.
  • On always attempts the capability query, which is useful through tmux or SSH.
  • Off keeps attachment labels without probing.

The NAKODE_TERMINAL_IMAGES=auto|on|off environment variable remains available as a per-launch override.

Usage diagnostics

Nakode records aggregate inference and tool telemetry inside each local native session. Inspect recent usage without exposing prompts, reasoning, tool arguments, tool output, session titles, or credentials:

nakode diagnostics
nakode diagnostics --days 30 --provider openai-codex --sessions 40
nakode diagnostics --days 30 --json > nakode-usage.json

The report includes daily provider usage, reported input/cached/uncached/output tokens, inference rounds, compactions, retries, tool calls, failures, output sizes, runtime, and the highest-input sessions. JSON output is intended for longitudinal analysis. Token and cache values are available only when the provider reports them; cached tokens may still count toward provider subscription or rate limits even when an API pricing plan discounts them.

Long-running turns remain unrestricted. Nakode emits non-blocking transcript warnings after every 25 active inference rounds, when an inference request succeeds only after provider retries, and when the same tool fails three times and then at each additional five-failure milestone in one turn. These warnings are informational and never interrupt the agent.

Canonical transcript entries optionally retain the stable provider ID and qualified model ID active when their turn began. Native runtime history and delegated-run SQLite persistence restore that immutable origin, and TranscriptEntryView plus protobuf fields 9 (provider_id) and 10 (model_id) expose it to SDK clients. Legacy and provider compatibility history without trustworthy origin leaves both fields absent; consumers must not infer them from a current selection or display/model-name parsing.

The public TranscriptPage keeps explicit paged history at 128 entries and 512 KiB, while the live session snapshot projects up to 256 entries and 1 MiB so inspection clients receive materially more recent history without removing a bounded API edge. Newest-page snapshots also project the latest owner entry independently and expose the exact number of omitted Tool/Diff entries carrying that owner turn ID. Historical pages omit both current-turn fields; unrelated omitted rows never contribute to the count. Entry bodies, audits, redaction and truncation retain their existing bounds.

Optional web browsing

For installation, service-user configuration, safe validation, and maintenance, see Linux provisioning. Recorded VPS diagnostics and sandbox repairs are in Visual tools on headless hosts.

Nakode's portable runtime can expose a browser tool when a browser add-on is enabled under /settingsAdd-onsWeb browsing. Browsing is disabled by default and neither backend is required to run Nakode:

  • agent-browser runs the optional open-source agent-browser executable on the local machine. Install and configure it separately, then select it in Nakode. If the executable is missing, only browser calls fail.
  • Firecrawl uses Firecrawl's hosted search and scrape API. Select Firecrawl and enter an API key in settings. The key is stored in Nakode's protected local application database.

Changes apply to the portable browser tool without restarting Nakode. Provider or tool functionality unrelated to web browsing remains available when either add-on is absent or disabled.

Optional vision

The vision tool analyzes workspace images using its own configured provider/model. Under /settingsAdd-onsVision, select a model and its reasoning effort. The picker uses that model's advertised values; vision does not inherit the calling agent's effort or fast mode. Existing installations retain low until changed. Saved effort applies to subsequent vision calls without restarting the server.

Headless integrations can use the public SelectModel operation with the Vision target and reasoning options, or UpdateSettings with a vision model and optional reasoning_effort. See vision provisioning for compatibility and deployment details. The browser tool returns text; capture screenshots separately before passing them to vision.

Optional memory

Nakode can expose provider-neutral memory_search and memory_store tools through Mnemosyne. Memory is disabled by default and writes occur only when an agent explicitly calls memory_store; Nakode does not ingest transcripts automatically.

Install Mnemosyne with its stdio MCP support in an isolated Python environment:

uv tool install 'mnemosyne-memory[mcp]'

Then open /settingsAdd-onsMemory, select Mnemosyne, confirm the executable, and choose the Mnemosyne bank used for global user memory. By default Nakode stores Mnemosyne banks under Nakode home (NAKODE_HOME, defaulting to ~/.nakode), instead of inheriting Mnemosyne's application-wide default directory. Set Data directory explicitly to override this location. Semantic embeddings remain optional and can be installed with mnemosyne-memory[mcp,embeddings]. Nakode supervises local MCP processes and stores memories in Mnemosyne's SQLite data directory.

Nakode manages a deterministic project bank for each workspace; project-bank names are internal and are not user settings. Every memory_store call must explicitly select project or global scope. memory_search searches both scopes by default, while allowing a caller to narrow a query to one scope.

Memory tools are currently available to the portable-tool runtimes used by Codex, Devin, Kimi, and GLM. Cursor continues to work normally but does not receive these tools. Disabling memory, clearing a required field, or removing the executable removes the tools on the next inference request without affecting other providers.

Skills

Nakode discovers portable Agent Skills from these directories, with workspace-local skills taking precedence when names overlap:

  • <workspace>/.agents/skills/<skill-name>/SKILL.md
  • ~/.agents/skills/<skill-name>/SKILL.md

Reference a discovered skill anywhere in a prompt with /skill:<skill-name>. Nakode offers discovered names in composer completion and attaches the selected skill instructions to that turn while keeping the original prompt unchanged in the visible transcript. SKILL.md is the operational entrypoint. Every other Markdown file below the same skill directory is automatically catalogued as a component; references/github/checks.md is exposed as component name references/github/checks with that exact file path. Non-Markdown files and nested SKILL.md entrypoints are not components.

read_skill returns JSON with this shape:

{
  "skill_instructions": "Read skill_content first ... load components with read_skill_component ...",
  "skill_content": "<complete SKILL.md>",
  "components": [
    {"file_path": "references/github/checks.md", "component_name": "references/github/checks"}
  ]
}

Component bodies are not injected eagerly. Load one by exact advertised name with read_skill_component({"name":"code-review","component_name":"references/github/checks"}). This keeps optional reference material out of model context while ensuring the agent never searches package directories or guesses a path.

Only a component outside the skill directory needs an explicit frontmatter entry, for example ../shared-review/policy.md. External declarations must resolve to a Markdown component under the same installed skills catalogue, are exposed with an owner-qualified component name such as shared-review/policy, and can be loaded only when that owning skill is also advertised to the session. Absolute paths, catalogue escapes, SKILL.md imports, symlink escapes, missing files, and unreadable components reject the skill instead of exposing arbitrary filesystem content. Discovery order and JSON component order are deterministic, and canonical identity de-duplicates aliases and directory cycles.

Skill publishers should include a bounded immutable id in YAML frontmatter (for example, id: fragile.code-review.v1) so local invocation history follows a skill when its directory/load name changes. Legacy skills without an id remain compatible and use their exact catalogue name as historical identity.

A package published through FStack's community store additionally requires a canonical SemVer release scalar such as version: 1.2.0. Nakode treats store provenance and version metadata as inert package metadata: it discovers the package only after FStack explicitly materializes it under the normal ~/.agents/skills root. Nakode does not read PostgreSQL, a store cache, or a registry root, and store availability never gates local discovery or startup.

Herdr integration

Run Nakode inside a Herdr pane to expose its lifecycle in Herdr automatically. No Nakode or Herdr plugin is required. When HERDR_ENV=1 and the pane identity is available, Nakode reports itself as idle, working, or blocked, includes its persisted logical session id when one exists, and releases its status authority on exit. Missing or failed Herdr reporting never prevents Nakode from starting or handling a turn.

nakode restart-when-idle waits until the server atomically confirms no live session work or pending delegations remain, then restarts it. It never escalates to forced shutdown. New work can prolong the wait; unsupported quiescence protocols fail without stopping the server.

Authenticated clients can replace a logical session’s ephemeral process environment through SetSessionEnvironment. Values never appear in snapshots or session persistence. Clients reinject them before work after a service restart. Injection accepts exact retained logical identities without activating a provider, so it can precede OpenSession; incomplete inventory is not proof of absence. Environment values are cleared only after successful durable session deletion. Native Bash and PTY tools (including delegates) inherit the logical owner’s variables.

Machine PATH

Owner clients can save a shell command and explicitly Sync the execution service’s PATH through the public SDK. Startup resolves it before runtime preparation; failures retain the last-good/inherited value. See machine PATH for precedence, shell initialization, security bounds and platform limitations.

About

Provider-neutral terminal layer for agent sessions and orchestration

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages