Files
2026-02-17 17:30:45 -05:00

127 lines
6.8 KiB
Markdown

# CLI & TUI Client
Terminal client for ajet-chat. Provides two modes:
- **CLI Mode** — stateless one-shot commands for scripting and quick interactions
- **TUI Mode** — full interactive terminal application with split panes, markdown rendering, and real-time updates
## Usage
```bash
# CLI commands
ajet login # OAuth login
ajet communities # List communities
ajet channels # List channels
ajet read general # Read messages
ajet send general "hello" # Send a message
ajet tui # Launch interactive TUI
# TUI with options
ajet tui --community my-team # Open to specific community
ajet tui --channel general # Open to specific channel
```
## Dependencies
- `clojure-tui` — local dep at `../../clojure-tui` (Elm architecture TUI framework)
- `babashka.http-client` — HTTP client for API calls
- `clojure.data.json` — JSON parsing
- `clojure.tools.cli` — CLI argument parsing
- Shared modules: `api-client`, `markdown`, `mentions`
## TODO: clojure-tui Gaps
The TUI (`tui.clj`) uses clojure-tui's Elm architecture (init/update/view) for state management and rendering. However, several PRD features require capabilities that clojure-tui does not yet provide. SSE integration is worked around via a shared `LinkedBlockingQueue` polled every 100ms with `delayed-event`. Below is the complete list of gaps between the PRD requirements and clojure-tui's current capabilities.
### 1. Mouse Support (PRD 4.4)
**PRD requires:** Mouse click to select channel/message/button, mouse scroll in message list.
**Gap:** clojure-tui has no mouse tracking escape sequences in `terminal.clj` and no mouse event parsing in `input.clj`. The library only handles keyboard input.
**Workaround:** Keyboard-only navigation (Ctrl+N/P for channels, Tab for focus, arrow keys for scrolling).
**To resolve:** Add SGR mouse tracking (`\033[?1000h\033[?1006h`) to `terminal.clj` and mouse event parsing (button, position, scroll) to `input.clj`.
### 2. Inline Image Rendering (PRD 4.5)
**PRD requires:** Render images inline in message list via timg, sixel, or kitty graphics protocol.
**Gap:** clojure-tui has no image rendering support. Its render pipeline outputs ANSI text only.
**Workaround:** Images display as `[image: filename.png]` text placeholder.
**To resolve:** Add a `:image` render primitive that shells out to `timg` or emits sixel/kitty escape sequences. Requires terminal capability detection.
### 3. Multiline Text Input (PRD 4.4)
**PRD requires:** Shift+Enter or Alt+Enter inserts a newline in the input field.
**Gap:** clojure-tui's `:input` widget is single-line only. It handles backspace and character insertion but has no concept of line breaks within the input buffer.
**Workaround:** Messages are single-line only. No multiline composition.
**To resolve:** Extend `:input` widget to support a multi-line buffer with cursor movement across lines, or create a new `:textarea` widget.
### 4. Autocomplete Dropdowns (PRD 4.4)
**PRD requires:** Typing `@` shows user mention dropdown, `#` shows channel dropdown, `/` shows slash command list. Tab to select.
**Gap:** clojure-tui has no autocomplete or dropdown widget. It has `:modal` and `:scroll` primitives but no composition for filtered-list-as-you-type behavior.
**Workaround:** @mentions, #channels, and /commands are typed manually without autocomplete.
**To resolve:** Build an autocomplete widget by composing `:modal` + `:scroll` + filtered list, with keyboard navigation. This is application-level code that could be contributed back to clojure-tui.
### 5. SSE Client Integration (PRD 4.7)
**PRD requires:** Real-time event stream from TUI session manager via Server-Sent Events.
**Gap:** clojure-tui's event loop (`core.clj`) only processes keyboard input events. It has no mechanism to inject external events (HTTP responses, SSE data) into the Elm update cycle.
**Workaround:** A background thread reads SSE via `HttpURLConnection` and writes parsed events to a shared `LinkedBlockingQueue`. The Elm loop polls this queue every 100ms via `delayed-event`, draining events and processing them in the `:update` function. This works but adds up to 100ms latency.
**To resolve:** Add an external event channel to clojure-tui's `run` function (e.g., accept a `core.async` channel that the event loop merges with stdin input via `alt!`). This would eliminate polling and allow SSE events to flow through `:update` with zero latency.
### 6. Terminal Bell (PRD 4.8)
**PRD requires:** Terminal bell (`\a`) on new @mention or DM.
**Gap:** clojure-tui's render pipeline doesn't include bell output. Trivial to implement but not part of the library's event/render model.
**Workaround:** Not yet implemented. Can be added as `(print "\u0007") (flush)` in the message event handler.
**To resolve:** Either add a `:bell` event type to clojure-tui, or just emit the bell character directly in application code (outside the render cycle).
### 7. OSC 8 Hyperlinks (PRD 4.6)
**PRD requires:** URLs in messages render as clickable hyperlinks using OSC 8 escape sequences (`\033]8;;URL\033\\text\033]8;;\033\\`).
**Gap:** clojure-tui's `ansi.clj` has ANSI color/style codes but no OSC 8 hyperlink support.
**Workaround:** URLs render as plain underlined text without click behavior.
**To resolve:** Add OSC 8 hyperlink escape sequences to `ansi.clj` and integrate into the `:text` render primitive when a `:href` attribute is present.
### 8. Spoiler Text Reveal (PRD 4.6)
**PRD requires:** `||spoiler||` text renders hidden (e.g., as block characters) until user presses Enter on the selected message to reveal.
**Gap:** This is an application-level feature requiring per-message hidden/revealed state and keypress handling. clojure-tui doesn't prevent this but provides no specific support.
**Workaround:** Spoiler text renders as plain text (not hidden).
**To resolve:** Track revealed-spoiler state per message ID in app state. Render spoiler spans as `\u2588` block characters when hidden, original text when revealed. Toggle on Enter keypress when message is selected.
### Summary Table
| Feature | PRD Section | Status | Blocked By |
|---------|------------|--------|------------|
| Mouse support | 4.4 | Not implemented | clojure-tui: no mouse input |
| Inline images | 4.5 | Placeholder only | clojure-tui: no image rendering |
| Multiline input | 4.4 | Single-line only | clojure-tui: :input is single-line |
| Autocomplete | 4.4 | Not implemented | clojure-tui: no dropdown widget |
| SSE integration | 4.7 | Queue polling (100ms) | clojure-tui: no external event injection |
| Terminal bell | 4.8 | Not implemented | Trivial — just needs `\a` output |
| OSC 8 hyperlinks | 4.6 | Not implemented | clojure-tui: no OSC 8 support |
| Spoiler reveal | 4.6 | Plain text | Application-level (not blocked) |