forked niri forked from okami.mom/niri

feat(tui): direct terminal chat client with pwd-mount handshake #61

targeting main
Merged opened by and assigned to callie.on-her.computer
targeting main

A Claude-Code-style terminal chat client that connects directly to the control plane, bypassing Discord, and mounts the operator's working directory so nano runs tools directly against their files — no upload, no catbox, no abstraction step.

what's here #

Server side (niri-runtime)

  • SwitchableToolClient — delegates to the default (local) tool client but can be re-pointed at a remote executor at runtime; reverts on disconnect. One failing/unreachable client can't wedge the default.
  • POST /client/connect { endpoint, workspace?, capabilities? } — mounts a connecting client's executor as the active tool target (does an executor health handshake, 502 if unreachable).
  • POST /client/disconnect — revert to the default client.

Client side (apps/tui, new @niri/tui package)

  • Boots an in-process tool executor bound to $PWD.
  • Performs the /client/connect handshake, then streams /chat/stream (SSE) with ANSI rendering of text / thinking / tool-call / usage events, sends via /trigger/chat, and auto-disconnects on Ctrl-C / /quit.
  • Supports remote control planes via --advertise + --listen-host for the eventual homura split.
  • Zero new heavy dependencies — built on node stdlib (readline + ANSI) + existing workspace packages.

how it fits the "control plane / client" model #

This is the concrete first step toward decoupling nano's continuity from the reef container. The control plane owns the loop/session; the client is a replaceable thing you run from anywhere that lends nano hands in your $PWD.

verification #

  • npm run typecheck green across all 14 workspaces (incl. new @niri/tui)
  • unit tests for switch / revert / unreachable paths (switchable.test.ts)
  • verified end-to-end: real apps/tui executor mounted via the handshake, control plane ran a real shell tool against the mounted pwd and got the file contents back

Refinement to follow in review — this is the first-round PR as requested.

This pull request has no versions submitted yet.