agentconsole

module
v0.0.12 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 11, 2026 License: MIT

README

agentconsole

A terminal client for agents built on the transparent-ai stack (openresponses, agentturn, agentsession), and for foreign agents over ACP.

It renders a conversation from the agent's session record, and overlays live events only for what the record does not hold yet. A conversation, its branches, its policy decisions and its verification are one view, whether the run is live or long finished.

Status: the conversation, turn, tree and record-detail views work against an agent run in process. The ACP backend is a later step. The design is in docs/plans/client.md.

As a library

The client is a view, not a controller. It reads the session through a client.Record and the agent's events through a client.Source, and sends what the user asks (a prompt, a steer, an answer, a reply, an abort, a head move) as intents to a client.Controller, which decides what they do. A coding agent embeds it by handing console.Run the three. For an agent driven through agentturn's control contract, the control is the source and client.Direct maps intents onto it; with agentkit, the kit's Control does what a front needs around each run (the recorder on the run's context, the engine's release of held calls, the head move with the skill grants):

kit, err := agentkit.New(ctx,
	agentkit.WithModel(model, "gpt-5"),
	agentkit.WithTools(read, write, bash),
	agentkit.WithPolicy(policy, matchers),
	agentkit.WithSession(store, agentsession.Header{CWD: cwd}),
	// agentkit.WithResumedSession(store, id) to continue a session:
	// a call held for approval before the restart is answered after it.
)
if err != nil {
	return err
}
defer kit.Close()

agent := agentturn.New(kit.Config(), kit.AgentOptions()...)
defer kit.Attach(agent)() // the kit's recorder, ahead of the client
ctl, err := kit.Control(agent)
if err != nil {
	return err
}
rec, err := client.RecordOf(kit.Recorder())
if err != nil {
	return err
}
return console.Run(ctx, rec, ctl, client.Direct(ctl)) // returns when the user quits; the store is then safe to close

Any agentturn.Control will do: a bare *agentturn.Agent with its session.Recorder attached, or a remote agent through agentturn's front/control (control.Dial), whose session a store client reads. Direct moves the head when the control has a ContinueFrom (agentkit's Control has) and refuses it otherwise, which the tree shows. A product with intents of its own to handle (answering some questions by rule, its own commands, recording who answered) writes its own Controller and may pass the rest to Direct. The public packages are console, client, view and toolview; the terminal model and the record panes are internal, and none of them imports agentkit.

A call to a tool shows its name and its arguments as key=value pairs. To draw a tool's calls its own way (a command as a shell line, an edit as a diff), give the client a toolview.Renderer for it:

console.Run(ctx, rec, ctl, client.Direct(ctl), console.WithToolRenderers(toolview.Renderers{"bash": bashRenderer{}}))

A renderer reads what the session records of a call (the arguments, the state, the output, the tool's schema), never the tool, so it draws a live call, a historical one and an MCP tool's alike, and a call it declines is shown the default way.

Usage

go run ./cmd/agentconsole --model qwen3:1.7b

The model comes from an OpenAI-compatible Responses endpoint: --base-url (default http://localhost:11434/v1, Ollama), --model, and the API key from the environment variable named by --api-key-env (default OPENAI_API_KEY). Sessions are recorded under --store-root (--store jsonl or cas; default ~/.local/share/agentconsole/sessions).

  • --session ID resumes a session; --session ref:NAME resumes the one a ref points to.
  • --conversation NAME continues the named conversation, creating it the first time.
  • --tools none|clock, --confirm-tools (ask before every tool call), --instructions, --max-turns.

In the terminal: Enter sends a prompt, or steers while a run is going (the steer is listed as queued over the input until the run takes it); Shift-Enter starts a new line in the prompt (Alt-Enter and Ctrl-J do too, for a terminal that sends Shift-Enter as a plain Enter); Ctrl-C (or SIGINT) aborts a run, and quits when idle; PgUp, PgDn, Ctrl-Up, Ctrl-Down, Ctrl-Home, Ctrl-End and the mouse wheel scroll the conversation, while the prompt wraps over up to five lines, then scrolls, and the arrows, Home and End move the cursor within it; Ctrl-R shows reasoning; Ctrl-O shows tool arguments and output in full. A mouse drag selects text anywhere on the screen — the client has the mouse, so the terminal's own selection cannot reach it — and the selection stays drawn until the next key or press; Ctrl-C copies it to the terminal's clipboard with OSC 52, which works over ssh too (a terminal that does not take it, iTerm2 with "Applications in terminal may access clipboard" off, copies nothing). With a selection drawn the first Ctrl-C is the copy and the second the abort or the quit; with nothing selected, Ctrl-C is the interrupt it always was. The status line keeps the session's time working (its runs' time, summed), a running total of tokens used and, when the host supplies a price source, what the session has cost. The line above the input is the current turn's: how long it has run and the tokens it took in and gave out, and while a run goes, what it is doing (waiting on the model, thinking, writing, calling or running a tool, retrying), in color, its dot a spinner; idle, or waiting on a permission, it says so. A tool call in motion carries the same spinner in its dot and the same color, and its dot goes back to ○ when it ends. When a tool call needs permission, y approves and n refuses, with an optional reason. Ctrl-/ (or F1) lists every key; Esc, q or Ctrl-/ again goes back.

The tree and the record detail:

  • ctrl+t switches between the conversation and the tree of the session's branches, its origin (if it is a fork) and the sessions it linked. In the tree, up/down select, Enter views a branch or opens the origin read-only (Esc returns to the live session; the agent's head does not move), and c continues from the selected branch: the agent's head moves there and the next prompt continues from it. A click selects an item of the tree, and a click on the item already selected opens it, as Enter does.
  • ctrl+p and ctrl+n move a cursor over the conversation's rows, and ctrl+b continues from the selected row. Esc clears the cursor. A left click selects the row under it; a click on the row already selected expands or collapses it. A click on the input clears the cursor, as Esc does, and puts the input's cursor where the click was. With a row selected, Ctrl-R and Ctrl-O show or hide that row's reasoning or tool output alone; with none, every row's.
  • tab opens the detail of the selected row (its entry, whether its request verifies and why not, the response's model and usage, a call's policy decision, who decided, dispatch, output and skill grants, what a compaction folded), then the session summary (header, verification over the line, token usage by model, config, refs, memory manifest, and the cost when a host supplies a price source), then closes the pane.

License

MIT. See LICENSE.

Directories

Path Synopsis
Package client is what a terminal client reads an agent through and what it says to it.
Package client is what a terminal client reads an agent through and what it says to it.
cmd
agentconsole command
Command agentconsole is a terminal client that runs an agent in process: a model behind an OpenAI-compatible Responses endpoint (Ollama's /v1 by default), assembled with agentkit and driven through its Kit.Control, with its session recorded in a store the client follows.
Command agentconsole is a terminal client that runs an agent in process: a model behind an OpenAI-compatible Responses endpoint (Ollama's /v1 by default), assembled with agentkit and driven through its Kit.Control, with its session recorded in a store the client follows.
Package console runs the terminal client: a view of an agent's record and its events, which sends what the user asks as intents to a controller.
Package console runs the terminal client: a view of an agent's record and its events, which sends what the user asks as intents to a controller.
internal
inspect
Package inspect computes the record-detail panes: what the session says about one entry (its response and whether the request checks out, a call's decisions and dispatch, a compaction's fold) and about the session as a whole (its header, its verification, its configuration, its refs, its memory manifest).
Package inspect computes the record-detail panes: what the session says about one entry (its response and whether the request checks out, a call's decisions and dispatch, a compaction's fold) and about the session as a whole (its header, its verification, its configuration, its refs, its memory manifest).
scripted
Package scripted is a scripted model for the tests that run a real agent: a Streamer that answers each request with the next of its steps, built on the emitter, offline and deterministic.
Package scripted is a scripted model for the tests that run a real agent: a Streamer that answers each request with the next of its steps, built on the emitter, offline and deterministic.
termtest
Package termtest is a terminal for tests that run the program over a pipe: it takes what the program writes, as a terminal would, and says what the screen shows.
Package termtest is a terminal for tests that run the program over a pipe: it takes what the program writes, as a terminal would, and says what the screen shows.
tui
Package tui is the terminal client: a Bubble Tea model over the view reconciler.
Package tui is the terminal client: a Bubble Tea model over the view reconciler.
Package toolview is how a client learns to show one tool's calls: a renderer per tool name, which an embedder hands the client, and the lines a renderer returns.
Package toolview is how a client learns to show one tool's calls: a renderer per tool name, which an embedder hands the client, and the lines a renderer returns.
Package view is the reconciler: a pure model that takes the record's changes and the agent's live events, in whatever order they arrive, and produces what a client renders.
Package view is the reconciler: a pure model that takes the record's changes and the agent's live events, in whatever order they arrive, and produces what a client renders.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL