Skip to content

packages coding agent interactive mode

Zachary BENSALEM edited this page Aug 15, 2026 · 1 revision

Interactive mode

Active contributors: Mario Zechner, kt, Armin Ronacher

Purpose

Interactive mode is the terminal chat UI for Prime Agent. It renders the conversation, the prompt editor, tool output, and the working indicator on top of the @earendil-works/pi-tui rendering engine, and drives the session exclusively through the AgentConnection seam (packages/coding-agent/src/modes/agent-connection/types.ts). It works identically against an in-process runtime (InProcessAgentConnection) and the background daemon (DaemonAgentConnection); process-local extension surfaces degrade gracefully on daemon transports via tryExtensionSurface and AgentConnectionUnsupportedError. All the code lives under packages/coding-agent/src/modes/interactive/.

Directory layout

packages/coding-agent/src/modes/interactive/
  agent-activity.ts               # Derives the live working state (waiting/thinking/writing/...)
  auth-flows.ts                   # Provider login/logout dialogs and OAuth selectors
  feature-hints.ts                # Rotating feature hint deck
  heartbeat-scope.ts              # Heartbeat scope helpers
  image-markers.ts                # Image content markers for the transcript
  interactive-mode-services.ts    # Client-local services (settings, registry, themes)
  interactive-mode.ts             # InteractiveMode: the full terminal UI (~9800 lines)
  onboarding.ts                   # First-run onboarding decision (prime cli splash, missing auth)
  prompt-stash-state.ts           # Draft prompt stash/restore (Ctrl+S)
  resume-hint.ts                  # Hint shown on startup about resume
  components/                     # All TUI components (57 files, see below)
  theme/                          # Theme registry, editor theme, code highlighter

The components/ directory holds every UI piece: agent-message.ts and assistant-message.ts (message renderers), bash-execution.ts (the ! / !! shell runner), config-selector.ts and configuration-menu.ts (the config command and settings tabs), context-tree-format.ts, conversation-components.ts, custom-editor.ts (the default editor), custom-message.ts, countdown-timer.ts, bordered-loader.ts, centered-overlay.ts, collapsible-error.ts, compaction-outcome-message.ts, compaction-summary-message.ts, branch-summary-message.ts, plus tool-execution.ts, ipython-cell.ts, login-dialog.ts, oauth-selector.ts, model-selector.ts, settings-selector.ts, tree-selector.ts, footer.ts, and many more (see components/index.ts).

Key abstractions

Type Path One-line description
InteractiveMode packages/coding-agent/src/modes/interactive/interactive-mode.ts The terminal chat UI: renders the conversation, editor, queue, and side questions
AgentConnection packages/coding-agent/src/modes/agent-connection/types.ts The typed client seam InteractiveMode consumes; never touches session internals
AgentActivityTracker packages/coding-agent/src/modes/interactive/agent-activity.ts Turns the event stream into a live working state and output-token count
ProviderAuthFlows packages/coding-agent/src/modes/interactive/auth-flows.ts Runs the /login provider selector and OAuth/API-key dialogs
InteractiveModeUiServices packages/coding-agent/src/modes/interactive/interactive-mode-services.ts Client-local settings, model registry, and theme access, separate from AgentConnection
CustomEditor packages/coding-agent/src/modes/interactive/components/custom-editor.ts Default editor component implementing EditorComponent from packages/tui/src/editor-component.ts
KeybindingsManager packages/coding-agent/src/core/keybindings.ts App + TUI keybinding definitions, user overrides from ~/.prime/agent/keybindings.json
ClientPromptStashStore packages/coding-agent/src/modes/interactive/prompt-stash-state.ts Durable draft stash/restore for prompts

How it works

main.ts constructs InteractiveMode with an AgentConnection plus InteractiveModeUiServices. In-process sessions pass InProcessAgentConnection and bindLocalSessionExtensions: true; daemon-backed interactive sessions pass DaemonAgentConnection and bindLocalSessionExtensions: false. The UI subscribes to session events through the connection, renders them with the TUI, and sends every user action back through agentConnection.prompt (with streamingBehavior: "steer" | "followUp" and queueIfBusy).

graph TD
    A[InteractiveMode.run] --> B[TUI engine (packages/tui)]
    B --> C[CustomEditor / EditorComponent]
    C -->|submit| D{queue behavior}
    D -->|Enter| E[steer: after current turn's tools]
    D -->|Alt+Enter| F[follow-up: after all work]
    E --> G[AgentConnection.prompt]
    F --> G
    G --> H{connection type}
    H -->|InProcessAgentConnection| I[AgentSessionRuntime in-process]
    H -->|DaemonAgentConnection| J[DaemonClient to daemon worker]
    I -->|session events| K[event loop]
    J -->|session_event stream| K
    K --> L[AgentActivityTracker]
    K --> M[message / tool / compaction components]
    K --> N[tryExtensionSurface fallback]
Loading

Editor integration

The editor interface is EditorComponent in packages/tui/src/editor-component.ts; interactive mode's default implementation is CustomEditor in packages/coding-agent/src/modes/interactive/components/custom-editor.ts. It supports @ file reference completion, path completion, multi-line input, pasted images, !command / !!command shell execution (rendered by bash-execution.ts), and Ctrl+G to open the external $VISUAL/$EDITOR. Extensions can replace it through the editor factory on the process-local extension surface.

Slash commands and keybindings

Typing / opens command completion driven by packages/coding-agent/src/core/slash-commands.ts (BUILTIN_SLASH_COMMANDS); the full catalog is on the slash commands page. Keybindings are defined in packages/coding-agent/src/core/keybindings.ts (app-level app.* plus TUI_KEYBINDINGS from packages/tui), are remappable in ~/.prime/agent/keybindings.json, and are never hardcoded per the repo convention. Examples: Ctrl+C interrupt/exit, Escape clears, Ctrl+L model selector, Ctrl+T thinking toggle, Ctrl+O tool output, Alt+Enter follow-up queue, Alt+Up dequeue, Ctrl+S prompt stash, Ctrl+G external editor.

The message queue (steering and follow-up)

While the agent is working, Enter queues a steering message (delivered after the current assistant turn finishes its tool calls) and Alt+Enter queues a follow-up (delivered after all work completes). Both are AgentConnection prompts with streamingBehavior set; queue state is tracked locally in connectionQueue and echoed by session_action_update events from the connection, and delivery modes are configurable via steeringMode / followUpMode settings. Queued messages can be pulled back into the editor with Alt+Up.

Login and provider auth flows

/login runs ProviderAuthFlows.runLogin (auth-flows.ts). It lists providers by category (OAuth subscription providers, built-in API-key providers, and service credentials such as web search), shows OAuthSelectorComponent or LoginDialogComponent, and writes credentials to auth.json (getAuthPath() in packages/coding-agent/src/config.ts). MCP integrations authenticate through runMcpLogin as mcp:<server> service credentials. The same flows are reused by the agents view, and hosts get onAuthChanged / onLoginCompleted hooks.

Graceful degradation on daemon transports

The AgentConnection.extensions sub-interface (argument completions, diagnostics, keyboard shortcuts, message/tool renderers, editor replacement) is permanently process-local. Daemon adapters throw AgentConnectionUnsupportedError from those members. Interactive mode wraps every extension read in tryExtensionSurface / tryExtensionSurfaceAsync, which catch AgentConnectionUnsupportedError and fall back to safe defaults, so interactive startup and chat work unchanged over the daemon. Extension UI dialogs on the daemon travel as extension_ui_request events handled by the interactive mode, mirroring the extension_ui client capability.

Integration points

  • main.ts builds the connection (InProcessAgentConnection or DaemonAgentConnection via createDaemonClientConnection) and the UI services, then runs InteractiveMode. The agents view (packages/coding-agent/src/modes/agents-view/) reuses InteractiveMode for per-session chat and the same auth flows.
  • Everything interactive reads and writes the session through AgentConnection; the daemon adapter (packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts) maps it onto the daemon protocol.
  • The TUI engine, editor, and rendering primitives come from packages/tui; themes and the code highlighter come from packages/coding-agent/src/modes/interactive/theme/.

Entry points for modification

  • Add a new chat UI feature: touch interactive-mode.ts and a component under packages/coding-agent/src/modes/interactive/components/, keeping all session access on AgentConnection.
  • Add a keybinding: extend KEYBINDINGS in packages/coding-agent/src/core/keybindings.ts (defaults belong there, not in matchesKey call sites).
  • Add an auth provider or login flow: extend auth-flows.ts and the selectors in components/.
  • Change how the connection degrades: update tryExtensionSurface in interactive-mode.ts and the AgentConnectionUnsupportedError contract in packages/coding-agent/src/modes/agent-connection/.

Key source files

File Why it matters
packages/coding-agent/src/modes/interactive/interactive-mode.ts The whole terminal UI
packages/coding-agent/src/modes/agent-connection/types.ts The AgentConnection contract interactive mode depends on
packages/coding-agent/src/modes/interactive/auth-flows.ts Login/logout and provider selection
packages/coding-agent/src/modes/interactive/agent-activity.ts Live working state and token counting
packages/coding-agent/src/modes/interactive/components/custom-editor.ts Default prompt editor
packages/coding-agent/src/core/keybindings.ts Keybinding definitions and user overrides
packages/coding-agent/src/core/slash-commands.ts Built-in slash command catalog

Related pages

Clone this wiki locally