A terminal that stopped draining the pty parked the writer thread inside its tty write while it held the stderr lock; the next inline stderr write from the event loop (mouse toggle, notification, kitty clear) deadlocked the loop, and /quit hung on the unbounded writer join and the teardown writes. EscapeWriter queues out-of-band escapes on the frame writer: the mouse capture toggle, notifications (title, progress, protocol), the auth cursor, gboom keyboard flags, the wrap clipboard request, and the kitty clears (queued per agent view and merged into the frame's post-flush, nested subagent views included). The $EDITOR/$PAGER handoff aborts when the writer does not drain. WriterThread::join_within and the teardown run under a 2 s grace; after a stall fd 2 is silenced, the exit hints, relaunch and update prints are skipped, and the panic hook keeps only its log report. Ported from upstream 1.0.19 (grok-build EscapeWriter, WriterJoin, run_bounded_teardown), extended to the remaining inline writes. Claude-Session: https://claude.ai/code/session_01RUqV8HVGXcAETyYbZ2tPQ4
kigi-tui
Terminal UI (TUI) for Kigi. Provides the interactive full-screen interface including the scrollback view, prompt input, session management, and all modal dialogs.
Architecture
src/
├── app/ # Application state and event handling
│ ├── app_view.rs # Top-level state (welcome screen, agents, config)
│ ├── agent_view/ # Per-session agent view (struct in mod.rs + per-domain impl modules)
│ ├── dispatch/ # Action → Effect dispatcher (router + per-domain modules)
│ ├── effects.rs # Async side effects (ACP calls, file I/O)
│ └── event_loop.rs # Main event loop (input, ticks, ACP messages)
├── views/ # UI components
│ ├── prompt_widget.rs # Text editor with file search, slash, history
│ ├── welcome/ # Welcome screen (logo, menu, prompt)
│ ├── extensions_modal.rs # Extensions modal (hooks, plugins, marketplace, skills, MCP servers)
│ ├── file_search/ # @-completion dropdown and line viewer
│ ├── slash_dropdown.rs# /command completion dropdown
│ └── ... # Scrollback, status bar, panes, etc.
├── scrollback/ # Message history rendering
├── slash/ # Slash command registry and built-in commands
├── appearance/ # Theme and pager.toml config
├── acp/ # Agent Communication Protocol client state
└── render/ # Low-level rendering helpers (color, wrapping, etc.)
Key Concepts
- AppView — owns the welcome screen, agent sessions, and global config
- AgentView — one per session; owns the prompt, scrollback, tool panes, and modals
- PromptWidget — text editor component with file search (
@), slash commands (/), history search, and paste elements - Action/Effect — Elm-style architecture: input → Action → dispatch → Effect → state update
Keyboard Shortcuts
| Key | Context | Action |
|---|---|---|
Ctrl+P or ? |
Agent screen | Open command palette |
Ctrl+L |
Any (non–VS Code family) | Open plugins/hooks modal; on VS Code / Cursor / Windsurf / Zed use /plugins or /hooks (Ctrl+L is mid-turn interject) |
Tab |
Prompt | Switch to scrollback |
Esc |
Turn running | No-op (does not cancel; use Ctrl+C) |
Esc Esc |
Idle, non-empty prompt | Clear prompt (within 800ms; first press shows hint) |
Esc Esc |
Idle, empty prompt + messages | Open rewind picker (silent first press) |
Ctrl+M |
Prompt | Toggle multiline mode |
Shift+Enter |
Prompt | Insert newline |
/ |
Prompt | Start slash command |
@ |
Prompt | Start file search |
! |
Prompt (empty) | Enter bash mode |
Ctrl+C |
Prompt (with text) | Clear prompt (even while turn running) |
Ctrl+C |
Prompt (empty) + turn running | Cancel running turn |
Docs
- Terminal Support & Troubleshooting — tmux/SSH truecolor, clipboard, mouse, diagnostics, /terminal-setup
- Hooks & Plugins Guide — managing hooks, plugins, and marketplace sources
- Custom Hooks Guide — creating, configuring, and writing your own hooks
- Hook Examples — sample hooks for common workflows
- Hooks Crate (
kigi-hooks) — hook runtime, event types, and execution engine - Plugin Marketplace Crate (
kigi-plugin-marketplace) — marketplace source loading, scanning, and install