@standardagents/code
v0.13.11
Published
Standard Code — a terminal coding agent whose LLM loop runs on a Standard Agents instance while its tools execute on your machine via this CLI.
Readme
█████████████
███ ██
██ █
████ ████████ ██
███ ████████ ███
██ ████████ ████
█ ██
██ ███
█████████████Standard Code
A best-in-class terminal coding agent.
The LLM loop runs remotely on a Standard Agents instance; every filesystem and shell tool executes on your own machine, through that machine's Standard Code daemon — so the agent works in your environment, against your code, with your permissions. The CLI is the terminal you watch and steer it from, and it never executes tools itself: a session survives closing the terminal, and any client can attach to it.
┌─────────────────────────┐ bridge (WebSocket) ┌──────────────────────┐
│ Standard Agents instance│ ── tool_request ──────────────▶ │ Standard Code daemon │
│ (the agent's LLM loop) │ ◀──────────── tool_response ── │ (your machine) │
└─────────────────────────┘ └──────────────────────┘
│ ▲
│ conversation, steering, approvals │ same machine,
▼ │ or a VPS
┌─────────────────────────┐
│ Standard Code CLI │ the terminal you watch and steer from
└─────────────────────────┘🔒 Early Access
Standard Code is in early access. The agent loop, tooling, and backend are evolving fast, and we're rolling it out gradually to keep the feedback loop tight.
Access is invite-only. To run Standard Code you need:
- A spot on the early-access list — request one at standardagents.ai/early-access.
- A Standard Agents instance exposing the
standard_code_agent(see agentbuilder).
If you're already on the list, you'll have received an instance URL and an API token. Jump to Quick start. If not, join the waitlist — we're letting new folks in every week.
Why Standard Code
- Your machine, your rules. Tools run on your own machines — read/write/edit files, list, grep, glob, bash, delete — never in some sandboxed cloud container. The agent edits the same files you do.
- The daemon is the executor. Every machine that runs sessions installs one
(
standardcode daemon install); the CLI, web console, and macOS app all attach as clients. Work continues on that machine after you close the terminal, and a machine without a daemon still runs the full CLI as a watcher of sessions executing elsewhere. - Permission-aware by design. A single auto-accept level (1–5) controls what runs unattended; higher-risk calls prompt you first. Operations explicitly marked as requiring permission prompt regardless of their numeric risk unless you previously granted that exact tool. Accepting a risk tier raises the shared thread level so every client displays and enforces the same policy. A catastrophic-command guard blocks dangerous shell calls at every level.
- Real project containment. File destinations and background-process working directories are checked through filesystem symlinks; any path that resolves outside the project always requires a fresh human approval.
- Durable, resumable sessions. Long-running and permission-gated calls park and resume over HTTP — a slow approval or a dropped socket can't kill your turn. Resume the same session from any machine.
- Background processes that survive. Dev servers, watchers, queue workers are tracked in the thread and keep running across reconnects and resumes.
- Idle attachments stay dormant. Queue/draft snapshots refresh from events and lifecycle transitions, stream and idle execution-bridge heartbeats use Durable Object hibernation auto-responses on a 30-second quiet cadence (real traffic suppresses the keepalive), and transcript safety requests run only while the agent is active. The bridge switches to a 5-second observable liveness heartbeat only during a forwarded tool or approval, so leaving a terminal attached does not continuously wake an idle thread. Each running client owns one account user stream; a machine daemon opens a per-thread execution bridge only while forwarded work is active. Stream transitions update machine presence once. Remote filesystem responses arrive through account events and trigger one response read, with no response loop.
- Subagents & research built in. Delegate focused subtasks to a coding subagent, or spin up a non-blocking web-research agent that returns source-backed findings.
- MCP, first-class. The CLI is a Model Context Protocol host — connect local MCP servers (Playwright, databases, issue trackers, anything) and the agent can use them. Install new ones in natural language: "install the playwright mcp server" and it researches and wires them up.
- Stable progressive Markdown. Streaming buffers are parsed into shared, source-offset-keyed blocks and inline runs. An open fence is a persistent code node and incomplete emphasis is a styled run, so later chunks extend existing UI state instead of replacing raw Markdown. The shared live-draft reducer appends monotonically across provider/reconnect message-ID aliases, and the durable answer uses the same document renderer for a geometry-preserving handoff.
Quick start
Standard Code has one exact runtime dependency on its version-matched
@standardagents/code-network package. Both packages use Node built-ins and
web-platform APIs without third-party runtime dependencies. For local
development the CLI runs through tsx; published builds are bundled with
tsup:
pnpm install # installs dev dependencies
pnpm code <dir> # run against a project directory (defaults to cwd)
pnpm code --endpoint http://localhost:5178 <dir>The parallel Rust TUI preview signs in, loads the shared machine → project →
session projection, and attaches through the same version-matched network
core. It owns the terminal's alternate screen and does not open native HTTP or
WebSocket connections. Terminals at least 100 columns wide keep the session
tree available as a full-height left column; Tab or its clickable divider
collapses it to a one-column rail with a vertically stacked Tab hint. A
one-column gutter separates that rail from the conversation while the
transcript, composer, and chat controls expand into the reclaimed space.
Narrower terminals show the session tree full-screen when focused and omit the
sidebar collapse control. An authenticated launch with no attached session uses
that same shell. A normal launch registers or refreshes the current directory
as a project and highlights its row without creating a thread. --browse
opens the account-wide picker without a project target. The sidebar remains
available while the right column presents a session-selection empty state.
Machine and project headings sit on the same left edge, sessions use one
shallow indentation step, and a blank row separates machines. A one-cell ⣿
texture marks machine headings and continues through their divider. Machine
rows have no disclosure glyph; a collapsed machine instead shows its known
thread count, such as (13); offline machines show that retained count too.
Collapsed projects likewise append their known thread count.
Each machine's green/red presence dot precedes its name. The leading texture
cell takes the branch accent only while that machine is active, hovered, or
keyboard-highlighted; inactive machine texture remains structural gray.
Machines receive stable colors from DMUX's eight-accent palette, so color
belongs to a branch rather than to global selection. Machine color is limited
to its texture/divider while the active machine name stays white. Project
headings and dividers remain structural gray at every state. Unrelated
hierarchy recedes to dark gray.
The attached project and thread use typography without persistent row fills;
the thread title inherits its machine accent. Hover or keyboard navigation uses
the same brighter row background for machines, projects, and threads;
navigated threads also add a › marker. Every thread has a status cell: hollow gray is idle, solid
blue is unread, and a green animated texture is working. Unread state uses the
shared core's account-scoped, message-recency watermark; opening a thread
advances that shared state, and background activity timestamps never create a
false unread dot.
Click a heading or select its name and press Enter to collapse it. Right moves
keyboard focus to the heading's complete [+] button; Enter activates it,
Left returns to the name, and Right again returns to an attached conversation.
The button is hidden until its row is hovered or keyboard-highlighted; while
hidden, the heading divider fills those final three cells instead of reserving
an empty control gap.
The project [+] opens a prospective session composer. The machine [+]
opens its structure-only directory picker and registers the chosen project
before opening that composer. The canonical thread is created when its first
message is submitted, so closing an untouched composer leaves no empty thread.
The composer takes keyboard focus and explains that the first message creates
the session.
An offline machine has no disclosure/collapse action and hides its retained
project/session branch. Its machine row keeps the last known thread count and
can still receive keyboard or mouse highlight, but its foreground remains gray
and activation does nothing. Creation controls are absent while that machine is
offline, and presence is checked again before a core request is sent.
Those actions use the shared core's project.open, session.start, and
machines.fsBrowse operations. The Rust face receives filesystem data and
canonical session metadata from the core.
Press Tab to reveal and focus sessions, use ↑/↓ or j/k and Enter to activate,
and press Esc or Tab to return to the composer. Clicking anywhere in the
expanded sidebar also transfers keyboard focus there, beginning on the clicked
row when there is one. Left from an empty composer
also reveals and focuses the sidebar; Left retains normal cursor movement when
the composer contains text. Activating a prospective or existing chat returns
keyboard focus to the conversation. Switching saves the current shared draft
before detaching, and never stops the session's remote work. While the selected
conversation loads, the full-height session tree stays mounted and only the
right chat column enters its loading state. Session rows also switch on one
click. Passive mouse motion gives clickable session rows a high-contrast
surface, highlights the sidebar toggle rail, Markdown
links, and the jump-to-latest pill, and asks supporting terminals such as
Ghostty for a pointer cursor. Redraws are coalesced until the semantic hover
target really changes. The transcript owns pane-local click-drag selection, so it copies
semantic Markdown text without Shift and never sweeps through the sidebar.
White is reserved for user text and high-value accents. Assistant prose and
tool, system, reasoning, and structural rows use sampled cool-gray tiers;
semantic states and Markdown keep muted accent colors. Live thought and answer blocks grow from a stable prefix,
so streamed chunks extend visible text without deleting and reflowing its
beginning. Running subagents retain a bounded list of their reads, searches,
edits, and other tool actions beneath the current activity phrase.
Settled reads and searches roll up under Explored while preserving every
action. Successful commands use one compact highlighted row. Failures retain
their complete output as a quiet gray block beneath the highlighted command,
and prose-like tool results share the transcript's word wrapper. Known
arguments and results receive muted semantic syntax colors. Consecutive edits
roll up under Edited N files; their complete red and green hunks fill the
available conversation width.
Thinking appears in an expandable block with an animated Braille texture while
the trace is active. Active traces start collapsed, and completed traces retain
a one-line disclosure. Click any thinking row to toggle its trace, or press Ctrl+T
to toggle the newest trace.
Releasing the button clears the highlight and shows Copied text in the status
row. Clicking anywhere in the active conversation column returns keyboard
focus to its composer without disrupting drag selection. Prose wraps at word
boundaries; long unbroken tokens and code still
hard-wrap to the pane. The complete loaded transcript remains scrollable with
the mouse wheel or Page Up/Page Down. Ctrl+Home jumps to the beginning and
Ctrl+End resumes bottom-follow; output that arrives while scrolled up leaves
the viewport anchored and shows a one-click “Jump to latest” pill at the bottom
of the conversation. The pill calls out new output when it arrives. Wheel bursts
accumulate between frames, preserving responsive trackpad motion instead of dropping input.
While a turn runs, an animated amber/coral/violet Braille status row stays
directly above the composer, after the optional Session todos card.
The composer and submitted user messages share one quiet filled rectangular
surface with a chevron gutter. One empty surface row sits above the editable
rows and one below, so the empty composer is three terminal rows; it grows
from one to eight content rows, wraps prose on word boundaries,
preserves hard newlines from Shift+Enter and multiline paste, and then scrolls
internally without displacing more of the transcript. Short conversations use
natural document flow: the composer and telemetry follow the final transcript
row, leaving unused space below. Once the transcript consumes the available
viewport, the composer stays pinned at the bottom and the transcript scrolls
above it. The mouse
wheel follows the pane under the pointer, so a capped composer scrolls without
moving the conversation; the next edit resumes caret-follow. Pastes over 1,000
characters render as an atomic cyan [Pasted Content N chars] element while
their exact text remains in the shared draft and submitted message. Backspace
or Delete at that element removes the complete paste. Enter sends or queues,
while Ctrl+Enter steers. Up/Down moves through visual editor
rows before recalling the core-backed per-thread sent history at the top or
bottom edge.
Structured session todos appear in a collapsible card above the composer. One
blank row separates the neutral teal-gray card from the transcript. Todo
descriptions and steps wrap to show their complete content. Escape promotes the
oldest queued message through the shared core. During active work with an empty
queue, Escape stops execution and releases the composer for a new message.
An offline runner does not make its cloud conversation disappear: the session
still opens for review, but the composer pauses instead of letting new work
silently wait for a missing executor. There is no separate offline banner; the
composer becomes a hollow, unfilled surface carrying the state inline. If work
is already waiting, it says Waiting for <machine> — Esc stops. Pushed machine-presence events unlock
the composer and restore the retained sidebar branch as soon as the daemon
reconnects; there is no presence poll or session relist.
The line beneath the composer is session telemetry rather than a persistent
keyboard cheat sheet: it shows the attached thread's agent, runner machine,
current working directory, running background-process count, and
compaction-scaled context usage. The muted path gets priority over the literal
context label. Full agent names stay visible at comfortable widths; only a
narrow footer abbreviates them (Unlimited One → U1, Sama One → S1)
before squeezing the deepest complete path breadcrumbs further.
The row ends with the old terminal face's five colored permission dots, so the
current effective auto-accept ceiling remains visible without adding another
row. Accepted risk grants raise the dots immediately and reconcile from the
persisted approval state. Approval requests show the tool summary, stated
reason, execution machine, five-dot risk level, and fully labeled decisions in
a bordered card. These
values come from the shared roster, session tree,
approvals, process registry, and context projections in the network core.
Headings, emphasis, links, lists, tables, quotes, and fenced code use
the same progressive parser contract as the TypeScript UI. PNG attachments use
Kitty Unicode placeholders in verified Kitty/Ghostty/WezTerm environments,
including configured tmux; other terminals keep the same layout and show a
text fallback:
pnpm tui:rust
# Open the account-wide project picker:
pnpm tui:rust -- --browse
# Optional direct-attach fast path:
pnpm tui:rust -- --thread <thread-id>This preview is additive; the TypeScript CLI remains the normal entry point while the Rust face is brought to feature parity.
Installed from npm:
npx @standardagents/code@latest <dir>
# or
npm install -g @standardagents/code
standardcode <dir>
standardcode --endpoint https://your-instance.example.com <dir>
standardcode -e -- <dir> # prompt for the endpoint for this runOn first run it connects to the hosted Standard Code instance
(https://api.standardcode.ai) and walks you through a one-time browser sign-in — press
Enter, approve in the browser, and your key is stored in ~/.standardagents/credentials.
Choosing an agent
Session start opens with an agent picker: Frontier One (coming soon),
Unlimited One (the default — adaptive high/low routing), Sama One
(OpenAI-only, powered by your own ChatGPT authorization), and Dario
(unavailable). Skip the menu with --agent unlimited or --agent sama.
Sama One is BYOK: the first time you pick it, the CLI opens
https://standardcode.ai/app where you connect your ChatGPT account once.
That connection installs the authorization in your account's secret
environment on the instance — shared by the CLI, web console, and macOS app —
and the CLI itself never sees or stores the OpenAI key. Connection changes are
pushed over the existing account WebSocket to every open client; the clients
do not poll account metadata. Sama One sessions are not limited by the
simultaneous-thread lease.
You only do this once per machine. Session start then asks where the session should run — this machine or any machine whose daemon is online — and offers to resume a session for that project or start a new one.
The first time you choose this machine, the CLI offers to install its daemon in one keypress
(the same flow as standardcode daemon install), because that daemon is what runs sessions
here. Declining leaves local execution unavailable; remote machines and watching stay available,
and the command sets it up any time.
Manage the local daemon from any shell:
standardcode daemon status
standardcode daemon restart
standardcode daemon update
standardcode daemon add-project /absolute/path/to/project
standardcode daemon uninstallrestart immediately reloads the installed launchd or systemd service. update lets active tool
calls finish, installs the latest Standard Code package, and restarts the daemon.
Use --endpoint [url] or -e [url] to point a single CLI run at a different Standard Agents
instance (local dev, self-hosted). If you omit the URL, the CLI prompts for it. Tokens are
remembered per endpoint, but this override does not change the saved default endpoint.
Endpoints without a scheme default to https://; using plaintext local development requires an
explicit URL such as http://localhost:5178.
For HTTPS on a loopback, private, .local, or .localhost endpoint, the CLI can relax certificate
verification for its own instance connections. That process-local setting is stripped from every
browser, shell, background process, package-manager, git, clipboard, and ripgrep child so local
development never disables TLS verification in unrelated commands.
Requirements
- Node 22+
- A Standard Agents instance exposing the
standard_code_agent(see the agentbuilder repo). For local development, run that backend on:5178and point this CLI athttp://localhost:5178.
Features
- Forwarded tools executed by the session's machine daemon: read/write/edit files, list, grep, glob, bash, delete.
- Permissions: a shared auto-accept level 1–5 (shift-tab cycles it); accepting a risk tier raises the stored thread level across clients; server-marked permission requests cannot be downgraded by a model-supplied risk. A catastrophic-command guard blocks dangerous shell commands at every level.
- Durable, resumable long-running/permission-gated tool calls (park & resume over HTTP).
- Background processes tracked in the thread (survive resume from any machine).
- Subagent delegation and non-blocking web research.
- MCP (Model Context Protocol): connect MCP servers on your machine — the daemon is the MCP
host, negotiating JSON-RPC over stdio. Manage the machine's server list with
/mcp(the daemon connects the enabled ones when it next starts a session there); install new ones in natural language ("install the playwright mcp server") and the agent researches + installs them.
Tests
pnpm test # TypeScript checks/tests plus Rust unit and PTY tests
pnpm check:rust # rustfmt and clippy with warnings deniedscripts/run-tests.mjs owns the explicit no-backend test manifest, prints each
file as it runs, and fails when a new scripts/*-test.ts file is not classified.
Run an individual file with pnpm exec tsx scripts/<name>-test.ts.
Architecture & contributing
Standard Code is the client half of a two-part system. The agent loop and tool definitions
live on the Standard Agents instance (agentbuilder);
this CLI connects to a thread and renders, steers, and approves the session, while the machine
daemon (src/daemon.ts) executes the agent's forwarded tool calls.
See AGENTS.md for the full source map, bridge protocol, MCP internals,
test layout, and contributor conventions.
- Two version-locked packages:
@standardagents/codeand its shared@standardagents/code-networkclient. Both use Node built-ins and web-platform APIs without third-party runtime packages. src/progressive-markdown.tsis the canonical structured streaming parser used by every face. The Node face-core sends its versioned documents to Rust, which handles terminal layout and paint. Web receives an exact source copy, and macOS runs the generated JavaScriptCore bundle. Shared vectors cover parser output and Rust transport-schema compatibility. Runpnpm markdown:syncafter changing the authored TypeScript parser andpnpm markdown:checkin CI.- The hosted instance authors the session-state reducer published through
@standardagents/code-network. It owns live-draft accumulation and busy/tool/message reconciliation; a changed chunk ID is an alias, never permission to erase text. - Commit messages use Conventional Commits, scope
cli(e.g.feat(cli): …).
Built by Standard Agents.
