Where localcode differs

localcode supports multi-model approval, scheduled execution, and validated multi-agent plans. This page describes capabilities that are not standard in coding agents and states the use case for each capability.

English  ·  한국어

version    0.143.1
date       2026-09-22
source    github.com/dennis2lee/localcode
related   Coding agents on one model (SWE-bench Verified)

Bottom line

Fourteen capabilities in two groups: task execution and client operation. Three capabilities change task execution directly:

The rest cover cost, auditability, running on models you host yourself, and several front ends over one daemon.

Capability comparison

The right column describes what is common across coding agents in general use, not any one product. See Qualifications for how to read it.

CapabilitylocalcodeCommon elsewhere
Adversarial reviewUp to 3 reviewers, each a separate agent with its own model profile and its own sub-session kept across rounds, unanimous boolean approval requiredOne model reviewing its own output, in the same context
Scheduled workNatural-language booking, time parsed by the harness, missed times reported as missedNone; a prompt runs when it is sent
Multi-agent plansPlan authored into a tool schema, validated whole before execution, hard ceilings on stages, turns and wall timeFree-form delegation the model narrates and may abandon
Cross-conversation reference#<name> lets the model read another session's messages, delivered as an untrusted tool result rather than spliced into the promptManual copy and paste between sessions
Prompt auditability/context reports every assembled piece with its source, trust class and token estimate, with no model callThe assembled prompt is not inspectable
Model-run commandsOff by default; on, the model may run a named built-in, custom command or skill as its own turnCommands are typed by a person only
Search completeness reportingTruncation, unreadable files and oversized lines are each named in the resultSilent truncation at a result cap
Per-endpoint concurrencymax_concurrent_tasks per provider, taken before the daemon-wide limitOne global concurrency number, or none
FailoverWith Smart Agent on, a per-profile fallback chain with the request re-derived for the new model familyRetry on the same endpoint, then fail
Local modelsReasoning read from both runtime spellings, context window read from the server, per-family behaviour correctionsHosted APIs first, local endpoints as a generic OpenAI shim
Model switchingChange model inside one conversation, across providers: a hosted model and one on your own machine are two stops in the same conversationA model picked from one vendor's list
Client architectureOne daemon, three front ends (terminal, browser, native window), any number attached to the same session at onceOne process per client
Turn navigationAlt and the arrows move the view between your own turns, separately from prompt history recallScrollback search, or scrolling
Workspace boundaryEvery path judged after symlink resolution; leaving the project is its own permission question, separate from the tool'sA single allow list of directories
Conversation storageArchive that keeps the full event log and refuses only new work; rename, reorder and fork alongside itDelete, or an unbounded list
Part 1

Task execution

1. Multi-model review

Debate

Self-review provides limited independence. Debate assigns the work to separate reviewer agents. Each reviewer uses its configured model and an independent context. Completion requires approval from every reviewer.

Use different models when model diversity is required. Reviewer profiles can point to the same model; the configuration does not prevent this.

Use case: a schema change before it reaches main

/debate girl,tom 5 migrate the session store to the new event schema

Runtime controls:

2. Scheduled tasks

Scheduled tasks

A prompt with a supported time expression creates a scheduled task. localcode executes it at the parsed time.

Use case: an overnight run booked from the prompt box

tomorrow at 9am run the full test suite and summarise only the failures
One limit, stated in the product

A booking fires only while localcode is running. A time that passed while it was closed is reported as missed rather than run late, because the request was for a time.

Three entry points: plain language in the prompt box, the clock button under it, or /schedule in 30 minutes run the tests. /show-scheduled-task is the same list in the terminal.

3. Validated multi-agent plans

Orchestrate

Delegation tools start other agents but do not enforce a declared procedure. A model can stop before completing every stated review. Orchestrate moves the procedure into validated data executed by localcode.

Orchestrate makes the plan data. The model authors it by filling in the tool's own input schema, so the whole plan is validated before a token is spent on running it.

Checked before executionRefusal
Every agent named against the roster the turn was admitted withWhole plan, with the reason
Every reference against a stage that really precedes itWhole plan, with the reason
Every count against its ceilingWhole plan, with the reason

Use case: a review where every finding must be verified

Ceilings are refusals rather than truncations, except a fanout over an earlier stage's results, whose width is not known until the run: there the surplus items are dropped and the report names how many. The permission prompt shows the ceilings rather than an estimate it cannot keep:

LimitValue
Stages per plan8
Agent turns per run32
Wall time per stage10 min
Wall time per run30 min

A stage names a role rather than tools, intersected with the agent's own restriction, so a plan can neither hand bash to a reviewer nor widen what an agent may do. Every stage is a synchronous child, so Esc stops the whole run.

4. Cross-conversation reference

Cross-conversation reference

The model can read the contents of a different session. Write #<name> in a prompt and the named conversation becomes readable: its prompts, its replies, and the files its tools touched. Analysis done last week in another session does not have to be repeated, and does not have to be pasted in by hand.

Use case: checking this project against a report written in another session

#S2 has the final report. Check it against the file here.

A conversation belonging to another project is flagged as one, with both directories named. #42 stays an issue number. The right arrow completes a conversation name the same way it completes a command, which is what makes a renamed conversation worth naming well.

5. Specialist delegation

Smart Agent

Smart Agent delegates work to six specialists, each with a separate session and context. The main session receives their results without retaining every file they read.

SpecialistWork
exploreFind things
librarianDigest long material
oracleReview
planDecompose
implementMake one self-contained change
verifyRun the build

On the 25-instance SWE-bench Verified run in the benchmark, Smart Agent on resolved 21 of 25 against 19 with it off, on the same model. That spread is inside run-to-run variance and does not rank anything; the measured difference that run does support is output tokens, 7,586 against 9,434 per instance.

6. Local models and failover

Local models and failover

Local endpoint support includes reasoning fields, server-reported context limits, request concurrency and fallback handling.

ProblemHandling
Reasoning has no field in the OpenAI API, so every runtime invented oneBoth spellings read: reasoning_content (DeepSeek, vLLM, SGLang, LM Studio, llama.cpp, Ollama) and reasoning (OpenRouter and others)
A local server's window is whatever was loaded, not what the model supportsRead from the server: GET /v1/models, or /props on llama.cpp
An endpoint supports fewer concurrent requests than the daemonPer-provider max_concurrent_tasks, acquired before the daemon-wide slot
A rate limit or an expired credential ends the turnWith Smart Agent on, two retries on the failing endpoint (1s, 2s), then a per-profile fallback chain with the request re-derived for the new family
A request refused for length ends the turnSummarise, then trim, shrinking until the server accepts it

A 401 or an unknown model id skips the wait, because time does not fix those, and a malformed request retries nowhere.

7. Model switching within a conversation

Switching models mid-conversation

An agent names a profile; a profile names a provider and a model. Switching the agent switches the model, and the conversation is left alone: the next message goes to the new model carrying everything said before it, the previous model's own answers included.

Agents in one conversation can use different providers, including Bedrock and a local server. Each agent resolves its provider and model from the configured profile.

Use case: hosted-model review and local-model implementation

"agents": {
  "general-purpose": { "profile": "smart-deep" },   // Claude, through Bedrock
  "on-the-laptop":   { "profile": "local-qwen" }    // llama.cpp on localhost
}

Switching agents can change the system prompt and tool schemas. The first request after a switch may therefore require a new provider cache entry.

Choosing the model is separate from choosing the agent. /model <profile> points one conversation at that profile's model and keeps the agent — its prompt, its tools, its permissions — so answering on a bigger model no longer means writing a second agent that is the first one with another profile. The choice is kept per agent in each conversation, survives a fork, and is announced on a model.changed event so a second client follows it. Bare /model reports the model in force and every profile the config can reach; the terminal opens a picker with agents and models in one list (/models and /mo are aliases), and default hands the choice back to the agent.

8. Prompt inventory

Prompt inventory

The system prompt is assembled from registered assets. Each asset has a stable id, source, trust class, request placement and activation condition.

Use case: finding out what is actually being sent

/context        what the next turn would send, with no model call
/context all    and what was left out, and why
/context <id>   the manifest a given model call was built from

The same manifest ids appear in the trace, so a failover that reused the failed model's prompt is visible as an unchanged manifest id on a changed model family.

The terminal keeps the same window in view another way: the footer under the prompt box shows context: N% beside the model, warning at 70% of the window and critical at 90%. The Web UI has long had its own indicator; the terminal ignored the usage events that feed it, so it had none.

9. Execution traces

Trace

With Smart Agent on, one JSON line per event is written to ~/.localcode/trace/.

10. Commands the model may run

Model-invocable commands

Shipped in v0.83.0, off by default. On, the model may run a built-in, a custom command or a skill itself, each as a turn of its own in the same conversation.

Use case: cleanup the model decides is due

Read the mail. If there is anything from the release manager, run /tidy-context.
Read before turning this on

The model decides when to run a command from what it has read: files, command output, and whatever an MCP server returned. Anything on the list is reachable from text the model did not write. The switch, the list and the settings note all say so.

Part 2

Client operation

One daemon holds every session. What attaches to it is a choice, and more than one thing can attach to the same session at the same time. The screenshots below are of localcode 0.115.0; the claims in this document were last checked against 0.122.0.

11. A terminal, a browser tab, and a native window

Three front ends, one daemon

The localcode Web UI: a session list on the left, the transcript in the middle, background tasks, scheduled tasks and MCP servers on the right, and the prompt box with a status bar along the bottom.
The browser front end. The desktop window renders the same page in a native OS window, with no browser and no visible server.
Front endHow it startsSuited to
Terminal (TUI)localcodeWorking inside an existing terminal session, over SSH, in tmux
Browserlocalcode, then open the listen addressReading long output, drag-and-drop file attach, watching several tasks
Native windowA build made with -tags gui: LocalCode.app on macOS, the MSI on WindowsUsing localcode as a desktop application. Experimental, and not available on Linux
Daemon onlylocalcode --headlessA remote machine you attach to

All three render the model's markdown — headings, emphasis, code, lists, blockquotes and links — rather than showing it raw. The terminal does it with a renderer of its own rather than a dependency, so the two differ in two places worth knowing: the terminal nests lists and the browser does not, and the browser lays out tables where the terminal passes them through as lines. Styling is applied when a reply is drawn and never when it is stored, so an exported conversation and a session log carry the markdown a model wrote and no escape sequences.

Use case: showing a running session to someone else

The daemon serves the interface over HTTP, so a second person who can reach that address opens the same live session: the same transcript, the same running tools, the same permission prompts, updating as it happens. Nothing is exported and no copy is made.

# on the machine running localcode
localcode --headless --listen 127.0.0.1:4096

# on the other person's machine
ssh -L 4096:127.0.0.1:4096 you@your-machine
# then open http://127.0.0.1:4096

The same address also takes a second terminal: localcode --server http://127.0.0.1:4096 attaches a TUI to a session someone else is watching in a browser.

There is no authentication token

Anyone who can reach the listen address gets the entire API, shell execution included. Bind to loopback and share through an SSH tunnel, as above. Do not bind 0.0.0.0 on an untrusted network.

12. The prompt box

Completion and turn navigation

Command completion

Type part of a name and press the right arrow. One completion list includes skills, custom commands, daemon commands and client commands.

The prompt box holding the text 'read the mail, then run /s', with the line below it reading: agent general-purpose, model qwen3-coder-30b, then an arrow, then /skill, then 4 matches, arrow cycles.
The line under the box names the first match and how many there are, before the key is pressed.

Moving through your own turns

Use case: finding what you asked, forty turns ago

Scrolling up holds the view where you put it, however much the model writes underneath, in both clients and in a background task's own window. Following the newest output resumes when you scroll back to the bottom.

13. Conversation management

Rename, reorder, archive, retrieve

The session panel: three conversations titled parser rewrite, release v0.105.1 and schema migration. The open one shows fork, rename, archive and delete in place of its date; the other two show their workspace path and when they were started. Below them an Archive section holding one conversation, with retrieve and delete.
Three active conversations and the archive list. A row carries its controls where its date is, on the conversation you are in and on the one you are pointing at.
ActionWhat it doesWhere
RenameGives a conversation a title of your own instead of its generated id. The title is what #<name> resolves against, so renaming is also how a conversation becomes worth citing from another one.Both clients (/rename)
ReorderDrag a card up or down. The order is saved on the daemon, so it is the same order in every client and after a restart.Browser and desktop window
ArchiveMoves a quiet conversation off the list, keeping everything it had, the whole event log included.Both clients (/archive)
RetrieveBrings it back with one press, restoring its rank rather than its number, and says which.Both clients (/retrieve)
ForkCopies a conversation, so a different approach can be tried from the same point.Both clients (/fork)
ExportRenders the conversation to a Markdown file from its own log, so an archived conversation exports as readily as an open one. Written rather than printed, 0600. Tool output past 4000 characters is cut, and the file says where.Both clients (/export)

Use case: retaining a completed conversation for reference

14. Paths that leave the project

Workspace boundary

A path that leaves the session's own workspace is its own question, separate from whether the tool is allowed at all. Answering "yes, this agent may read files" is not answering "yes, it may read ~/.ssh".

A second boundary guards destinations rather than paths. network.egress bounds the connections localcode itself makes: the model providers, remote MCP servers, the update check. The list holds host names and *.base entries; loopback is always allowed and needs no listing. It is enforced only when asked for, so a list can be written down and tried before it is relied on. A shell command and a subprocess MCP server are separate processes with their own sockets and stand outside it, and the setting says so rather than implying otherwise.

The permissions dialog: two skip switches, then a section headed Outside this project explaining that paths landing outside the project directory include an absolute path, a dot-dot, or a symlink that leads out, with separate checkboxes for allowing reads and writes outside without asking, and a note that a shell command is not a path.
The boundary is a section of its own in the permissions dialog, with reading and writing answered separately.
CaseTreatment
An absolute path, or one containing ..Resolved, then judged against the session's workspace
A symlink inside the workspace pointing at ~/.awsOutside. The resolved physical path determines access
A file about to be createdJudged by where its link leads, before it exists
A path that cannot be resolved at allRequires permission
A credential store: .env, *.pem, id_rsa, ~/.ssh, ~/.aws/credentials, .netrcRefused outright with Smart Agent on. Deny class, so no skip unlocks it; a rule for the same tool in config.json does, which is how a project that must edit a .env says so
A shell command that leaves the workspaceNot covered by these two, and the dialog says so: a shell command is not a path. bash asks on its own terms

Use case: one project, one boundary, several sessions

Smaller differences

AreaWhat differs
Search resultsA 200-match cap, a line over 1MB and an unreadable file are each named in the output. Paths, at most three, rather than a count. With Smart Agent on, no single file may take more than 30 of grep's 200 results.
Lifecycle hooksBeyond tool hooks: pre_model (block a request, or inject a fact the model could not look up), post_model, delegate (refuse a sub-agent, which a prompt cannot do), compact, retry. A hook may carry "timeout" in seconds (30 by default) and "fail_closed": true, which blocks the action when the hook never finishes — killed at its timeout, or unable to start. Off by default: a hook that cannot run and blocks everything locks somebody out of their own tools, the more common accident. A hook that ran and exited non-zero has decided, so fail_closed does not touch it.
Per-session workspaceTwo sessions in two projects on one daemon. Only that session's own turn blocks its own switch. /workspace reports the directory and moves it; a move waits for an idle session the way /clear and /rewind do, and the other client's button follows on a workspace.changed event.
Review/review reads what changed — the uncommitted diff by default, or staged, head, a revision, a range or a path — and says what is wrong with it, worst first, modifying nothing. A custom command of the same name wins: the name was in people's .localcode/commands before the built-in existed.
Status and debug/status reports what is attached: every MCP server with connected, degraded or disconnected and the last error, plus skills, custom commands, agents and the workspace. /debug prints version, platform, session, agent, model, effort, workspace and config as one plain block to paste into a bug report. Both are answered by the daemon, so both clients read the same answer.
MCP servers/mcps lists every server with whether it is working and whether this conversation uses it. /mcps off <server> hides that server's tools from the next request here; the server stays connected, because another conversation may be using it and reconnecting is the expensive part.
Usage/usage answers for this conversation. /usage all|today|week|month counts every conversation from the logs at the moment it is asked, archived ones included; a turn that was later undone still cost what it cost, so it is still counted.
Samplingtemperature, top_p and top_k live on the profile — muse's own vLLM recipe names all three with temperature 1.0. top_k is a vLLM extension on OpenAI-compatible endpoints, sent only when set, and travels in additionalModelRequestFields on Bedrock. Both are dropped while a Claude model is reasoning, and out-of-range values are refused at load rather than mid-turn.
Effortoff, low, medium, high, xhigh, per profile, or per conversation and per model within it. Only the levels a model tells apart are offered. Unset sends nothing, so an unchanged setup produces byte-identical requests.
SteeringA message typed during a turn reaches that turn at the model's next tool call, in the order typed.
Nearly-right tool namesA decorated name that unambiguously means one tool the agent has runs it and says which spelling worked. Resolution searches only the tools that agent was offered, so a misspelling cannot reach past a tools restriction.
Model-specific handlingSelected by model ID: continuation instructions for muse models that stop during a task, a note asking Gemma for the character itself rather than LaTeX. The Web UI unwraps the LaTeX that arrives anyway, whoever wrote it.
Config from the environmentAny string may be {env:NAME} or {env:NAME:-fallback}. A missing variable is an error naming it and the field that asked for it, not an empty string that fails later as a 401.
Event deliveryA client that falls behind is told rather than silently skipped: the stream ends, it reconnects, and it replays what it missed from the session log with no gap and no duplicate.
Linux installNo root: a static binary in ~/.local/bin, nothing written outside $HOME. A .deb and a portable tarball where root is available.

Parity, not difference

These are deliberately the same as elsewhere, and are listed so the tables above read as a difference rather than a feature count.

Qualifications