# 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) |