127 lines
6.8 KiB
Markdown
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) |
|