Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Staying in sync

Wisp keeps control and evidence in the same loop as the work. A live client can redirect an active run at a safe boundary, every frontend uses the same approval and cancellation policy, and the append-only session shows what actually happened.

The shared runtime guarantees consistent semantics, but frontend controls differ:

InterfaceLive controls
Rust TUISteer, queue follow-ups, restore the newest queued item, cancel the active command, and answer approvals
JSONL RPCSteer, queue follow-ups, inspect/edit queues, cancel by command id, and answer approvals
Python SDKThe same live queue, cancellation, and approval capabilities exposed as typed methods
Print / JSON (wisp -p)One prompt per process; no channel for new input while it runs

JSON mode changes print mode’s output format, not its interactivity. Use RPC or the SDK when an automation needs to redirect work already in progress.

Steering versus follow-up

Both operations append ordinary user messages at controlled request boundaries; neither edits or reorders the existing transcript.

  • Steering targets the active run. Wisp injects the message after the current assistant/tool batch and before the next provider request, so completed tool work remains visible and the model sees the correction before continuing.
  • Follow-up waits until the run would otherwise stop, then continues with the queued message. In the Rust TUI, press Alt+Enter while a prompt is running to queue one explicitly.

While a prompt runs in the Rust TUI, ordinary Enter submits steering and Alt+Enter submits a follow-up. The queue panel previews both kinds, and the footer keeps separate steer and later counts. Press Alt+Up to remove the newest queued item and restore it ahead of any current composer draft. Queue changes are confirmed by the shared runtime before the TUI treats them as accepted or removed.

Each queue is FIFO. The default one_at_a_time mode injects one message at each eligible boundary; live RPC and SDK clients can switch a queue to all to inject the current batch together. They can also inspect queue counts, remove the newest item, or clear one or both queues before injection. The Rust TUI intentionally offers only newest-item restoration rather than the complete queue API.

The in-process InProcessWisp controller exposes these as steer(), follow_up(), get_queue_state(), set_queue_mode(), pop_queue(), and clear_queue(). Raw JSONL clients use commands with the same names over newline-delimited JSON.

Cancelling cleanly

Cancellation requests a cooperative stop through the command host instead of killing the process. The active provider/tool path unwinds, lifecycle events record the cancelled outcome, and durable JSONL entries already committed remain valid. You can resume the session instead of reconstructing state from a half-written transcript.

  • In the Rust TUI, dismiss any open overlay first, then press Escape or Ctrl-C to cancel the active prompt.
  • In RPC, send {"type":"cancel","target_id":"<running-command-id>"}.
  • In the SDK, call InProcessWisp.cancel(target_id) for the active command.

Cancellation does not pretend that external side effects never happened. A command that already changed the filesystem or a remote service stays represented in the event stream; inspect its tool result before continuing.

Approvals as a sync point

Read tools can run directly. Mutating and command tools pause before execution and emit a typed approval request describing the proposed call. The user or controlling client may deny it, approve that call once, allow the same tool for the session, or allow all unsafe tools for the process.

The approval decision is supplied outside the model conversation. Prompt content cannot forge it or lower a tool’s safety category. Print/JSON mode has no interactive approval channel, so unsafe execution is blocked unless the process started with --yes.

See Tools & safety for tool categories, protected paths, trust, and MCP policy.

Seeing what happened

Wisp represents model output, tool calls and results, queue changes, approvals, cancellation, compaction, usage, and command completion as typed WispEvent values. Interfaces render those events differently, but they do not invent a second lifecycle.

Durable sessions append JSONL entries in order. That record supports resume, branching, audit, and recovery from an interrupted process without silently rewriting earlier history. Read Sessions for persistence behavior and Architecture for the event contract’s place in the runtime.

Tip

Where this is enforced

Steering, follow-up queues, and cooperative cancellation live in AgentHarness, one layer below persistence and one above the provider-neutral loop. CodingSession adds durability and policy; frontends expose the subset of controls their transport can accept.