Article

NoirCode API and Event Flow

Every NoirCode interface is a client of the local server. The full-screen TUI, noircode mini, the desktop app, and the web UI from noircode pair send work to that server and render what it streams back. noircode run is the same server path without an interactive UI.

TUI / mini / desktop / web / noircode run
                 |
                 v
          local NoirCode server
                 |
        sessions, permissions, tools
                 |
                 v
           provider adapter
                 |
                 v
          the model you selected

The HTTP API is the server’s own API. noircode api discovers the background service and authenticates to it. Compaction, for example, is noircode api post /api/session/<id>/compact. The live feed is server-sent events at /api/event, not a separate WebSocket product and not a set of invented event names.

A prompt, as the server actually runs it

  1. The client creates or resumes a session. The server records session.created with the project, location, agent, and model. Changing either later emits session.agent.selected or session.model.selected.
  2. The user message is stored on the session. Instructions from the agent, config, and any active skills are part of that session.
  3. Execution starts (session.execution.started). A model step starts (session.step.started). Text and reasoning stream as session.text.delta and session.reasoning.delta.
  4. If the model calls a tool, the server emits session.tool.input.* and then session.tool.called. The tool runs locally: read, grep, glob, edit, write, patch, shell, web, todo, skill, question, subagent, or an MCP tool. Permission rules are checked first. ask waits for the client. deny blocks the call. A policy can deny the tool with no prompt.
  5. The tool finishes with session.tool.success or session.tool.failed. The result goes back into the conversation for the next model step. Shell commands also emit session.shell.started and session.shell.ended.
  6. The step ends, usage is recorded (session.usage.recorded), and execution succeeds, fails, or is interrupted.
  7. A provider error can schedule session.retry.scheduled with an attempt count. That retry uses the same session and model. It does not classify the task and switch vendors.
  8. Near the context limit, compaction emits session.compaction.started, streams a summary, and ends with session.compaction.ended. The recent token window stays in the prompt.
  9. /undo stages session.revert.staged, restores the files captured by the step’s snapshots, and commits the rollback when you submit the restored prompt.

File changes are results of the edit, write, and patch tools, plus the snapshot taken around the model step. There is no parallel event bus of file.read, file.created, and file.deleted driving plugins. A plugin is a package or local directory listed in plugins. It loads into the server. It does not receive a config block that formats, tests, and commits on every write.

What you can rely on the stream for

The event log is enough to show a live transcript, tool progress, permission prompts, token usage, compaction, and undo. It is the contract the TUI and the web app already use. External dashboards, multi-user sync, load balancing, and consensus between models are not part of this flow.

A short example

“Refactor the auth module” becomes a session message, a model step, tool calls that read and search the files the agent chooses, streamed text, and, if the agent edits, patch or edit tool calls whose paths are recorded for /undo. Tests run only if the agent uses the shell and permissions allow the command. Nothing in the server automatically runs the suite and opens a commit.

The API is the local control plane for one user’s sessions. The model is a step inside that loop, called through the provider adapter with the context the session has gathered so far.