Give the TUI Working Controls
Explore how to design and implement terminal user interface controls that distinctly route user commands apart from model tasks to enhance reliability. Learn to manage task status, command ownership, state checks, and safe cancellation, enabling controlled interactions within an AI agent harness environment.
We'll cover the following...
- What are we building in this lesson?
- What makes a terminal command real?
- How does Wren separate commands from tasks?
- Why does a running harness need its own status?
- How can a terminal accept cancel during a run?
- How do Pi and DeepSeek Harness separate human controls?
- What should happen to controls that are unavailable?
- How do you test a terminal without faking a terminal?
- Can you map one terminal line to its owner?
- What can you add to your own harness today?
- Try it yourself
- What’s next?
Wren was halfway through CLIN-547 when its operator typed /status to find out whether the focused test had started.
The old REPL treated every nonempty line as a model task. The provider received the literal text /status, interpreted it as another instruction, and Wren began a second investigation after the first run had already ended. Nothing was malicious. The terminal had no command boundary, so the operator and the model competed for the same input channel.
That is a Carry failure at the human boundary. A terminal becomes part of the harness when a person uses it to steer a run. If /status becomes model text, the button has no real wire behind it.
This lesson gives Wren a small command language with clear owners and state checks. The model receives tasks. The console receives commands. The agent loop still owns outcomes.
What are we building in this lesson?
Think of a reception desk with two trays:
A task goes to the agent:
check the overlap test.A command goes to the terminal:
/status.
The first character decides which tray receives the line. A normal line starts a model run. A slash starts a console command. The parser performs that split before any provider call can happen.
There is one escape rule. //explain /status removes one slash and sends explain /status to the model. This lets a real task begin with / without turning unknown commands into accidental model instructions.
What makes a terminal command real?
A printed command list is not enough. Each command must answer five questions: what is its name, who owns it, when can it run, what does it change, and does the model see it?
Command | Owner | When Is It Legal? | Effect | Model Sees It? |
| Console | Any time | Prints supported commands | No |
| Console state | Any time | Reports active turn, calls, or last outcome | No |
| Console state | Idle | Reports the local context meter | No |
| Conversation state | Idle | Clears only working history | No |
| Active run | While running | Aborts its controller | No |
| Console lifecycle | Any time | Closes idle console or cancels then closes | No |
Plain text | Agent loop | Idle | Starts one model task | Yes |
Start with the owner column. A command should not call the provider because it was typed into the same terminal. It should go to the smallest component that can perform the action and report the result.
Use the examples below or type your own line. Route /status, a normal task, an escaped task, and a misspelled command. Only task text should reach the agent loop.
The parser gives every line one owner. Known commands change console or harness state. Unknown commands receive a refusal. Tasks become provider messages. Escaped text becomes a task after one slash is removed.
This does not add capability to the model. It makes existing harness state steerable, which is reliability work.