Commit Graph
28 Commits
Author SHA1 Message Date
Codeman maintainer 6682231d68 feat: give the TUI model a revision signal and picker state
The app layer repaints on state change, so the store has to be able to
say that something changed: `revision` is bumped by every mutating
method, and the repaint test compares it against the last painted frame.
Without it an idle dashboard would either redraw on a timer or go stale.

Three additions come with it, all optional so nothing existing changes
shape: `TuiSessionRow.muxName` (the unified list carries no mux name, so
the app fills it in from the local tmux enumeration and a row without one
cannot be attached), a `new-session` UI mode, and `TuiPickerState`, the
one-column chooser behind `n`.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 14:13:58 +02:00
Codeman maintainer e140132e45 feat: add the TUI's API, SSE and degraded-mode client
Everything the dashboard needs from outside the process, behind one typed
surface, so the app loop stays a loop. It is a client of the running server and
nothing else: rows come from the unified list, blocked states from the
approvals inbox, and answering goes through the endpoint that re-captures the
pane and refuses with a 409 when the dialog has already been answered in tmux.
That refusal is a typed result rather than an exception, because a human
beating you to a prompt is normal operation.

Discovery mirrors the daemon probe (`CODEMAN_API_URL`, else loopback on
`CODEMAN_PORT`, self-signed TLS accepted) and credentials come from where
`codeman attach` already reads them. An explicit port outranks the ambient
`CODEMAN_API_URL`, which every managed session exports: a caller that named a
port must not be redirected at whatever server owns its shell.

Input is single-line and `\r`-terminated at this layer, so no caller can strand
text on an unsubmitted composer, and each send is tagged for the server's
exactly-once path. The event stream defaults to a `?sessions=` filter that
matches nothing, which drops the terminal firehose while lifecycle, hook and
approval events still arrive. A silent-but-open stream is caught by a watchdog
rather than a socket error, since that failure mode reports nothing at all.

With no server answering, sessions are listed from tmux on the instance socket
(argv, never a shell string) and decorated from a read-only peek at state.json,
which keeps the "the server died, get me to my sessions" path alive.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 14:13:58 +02:00
Codeman maintainer 6475c010a6 feat: decode the SSE wire format for the TUI
Node has no EventSource, so the live-update stream is read as raw bytes and
decoded here. Three details are what the parser exists for: a TCP read can end
between the CR and the LF of a CRLF, so a trailing CR is held back rather than
dispatched; the tunnel padding the server appends after a frame is a comment
with no blank line after it and must not split anything; and the keepalive is a
NAMED event, because an SSE comment is invisible to a browser client by spec.

Event classification lives here too, as a set rather than a prefix test:
`session:terminal` is most of the stream and the preview pane pulls its own
tail, so it is deliberately not a resync trigger.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 14:13:57 +02:00
Codeman maintainer 0566ea3453 docs: record why the key parser reads LF as Enter
Ctrl+J is unbindable as a result, which is worth knowing before someone tries
to bind it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 14:13:57 +02:00
Codeman maintainer 6ef3b2ba2e feat: render TUI frames from the model and layout
One absolutely-addressed line per row, each closed with an erase-to-end, so
nothing scrolls and a repaint cannot leave the previous frame's tail behind.
The caller wraps the result in synchronized-output brackets; that is an IO
decision and stays out of the renderer.

Color is passed in rather than detected. chalk's detection is right for the
one-shot CLI but would make a frame non-deterministic, so the palette is raw
SGR in the same semantic roles cli-style uses, and `color: false` emits nothing
but the cursor addressing, the session's own colors in the preview included.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 14:13:57 +02:00
Codeman maintainer 74fe2cad9f feat: add the TUI responsive layout math
Below 72 columns the preview pane is dropped and rows take two lines, the
constraint the `sc` chooser was built around and the reason it is still usable
on a phone; above it a clamped sidebar carries the list and the preview takes
the rest.

Every region is clamped to a non-negative size, so a 5x5 terminal degrades to a
header instead of handing the renderer negative widths.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 14:13:57 +02:00
Codeman maintainer aa2deea73e feat: add the TUI session model, classification and cursor
Rows are the ones GET /api/sessions/unified already returns and blocked states
are the items the approvals inbox already parsed, both imported as types only
so a CLI process pulls in neither the server nor node-pty. Classification
speaks the web UI's language (red blocked, yellow waiting, green working) so a
user with both surfaces open never has to translate between them.

Groups order by how long a session has been in its state, which is why WORKING
anchors on the pane's last Enter: a working pane repaints about once a second,
so its last-activity stamp always says "now".

Selection is tracked by session id, never by row index: rows re-sort under the
cursor whenever a session starts working or an approval lands, and an
index-tracked cursor would quietly move the selection to another session
between two keystrokes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 14:13:57 +02:00
Codeman maintainer 5d7fdb528b feat: add the TUI raw-mode key parser
Decodes printable UTF-8, the control keys, arrows in both CSI and SS3 forms and
SGR mouse reports out of a byte stream that can tear anywhere, so a sequence
split across two reads decodes the same as one that arrives whole.

A lone ESC cannot be told from the start of an arrow key by looking at bytes,
so the parser holds it and the caller resolves it with flush() once its
disambiguation timer fires. Unknown sequences are swallowed: a stray CSI must
never reach a prompt composer as typed text.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 14:13:57 +02:00
Codeman maintainer 64cf8384f2 feat: add the TUI's SGR-aware preview helpers
The preview pane shows a session's raw terminal stream, so it needs the tail
reconstructed rather than emulated: SGR survives, cursor steering and OSC do
not, and a carriage return returns to column 0 so a spinner that repaints its
line 200 times contributes one line instead of 200.

Widths count East Asian Wide characters as two columns, which the clip and pad
helpers rely on to never cut a wide character, a code point or an escape
sequence in half.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 14:13:57 +02:00
arkonandClaude Opus 4.5 db20f4f63d chore: bump version to 0.1427
- Remove TUI from git (moved to .gitignore for local development)
- Remove React/Ink dependencies (unused in published version)
- Remove tui command from CLI

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 12:47:23 +01:00
arkonandClaude Opus 4.5 0d1ca37b6e refactor: rename inner-loop-tracker to ralph-tracker with API improvements
- Rename inner-loop-tracker.ts → ralph-tracker.ts throughout codebase
- Add ralph-config.ts for parsing .claude/ralph-loop.local.md config
- Standardize API error responses using createErrorResponse()
- Add input validation for auto-compact/auto-clear thresholds
- Update UI labels to "Ralph / Todo Tracker" consistently
- Add 46 integration tests for Ralph tracking functionality
- Update test badge to 438 total tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 22:36:45 +01:00
arkonandClaude Opus 4.5 c33d6e0987 refactor: improve code quality with stricter TypeScript and memory leak prevention
- Add stricter TypeScript compiler flags (noUnusedLocals, noUnusedParameters,
  noImplicitReturns, noImplicitOverride, noFallthroughCasesInSwitch,
  allowUnreachableCode, allowUnusedLabels)
- Remove unused variables caught by stricter flags:
  - Remove unused `renameSession` destructuring in App.tsx
  - Remove unused `BG_GRAY` constant in DirectAttach.ts
  - Remove unused `INPUT_BATCH_INTERVAL` constant in useSessionManager.ts
- Add proper EventEmitter cleanup to RalphLoop:
  - Store bound event handlers for cleanup
  - Add cleanupEventHandlers() method
  - Add destroy() method for complete cleanup
  - Add destroyRalphLoop() singleton cleanup function
- Update ralph-loop tests to use destroy() instead of stop() to prevent
  MaxListenersExceededWarning

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 14:01:47 +01:00
arkonandClaude Opus 4.5 e8c30b9880 fix(tui): resolve screen attach ambiguity with multiple sessions
- Add getFullScreenId() to get PID.screenName format for unambiguous attach
- Update DirectAttach.ts and index.tsx to use full screen IDs
- Remove TUI documentation from README (still in development)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 12:52:38 +01:00
arkonandClaude Opus 4.5 e6ba373d12 feat(tui): add Delete All (D) to kill all screens and Claude processes
- Add killAllScreensAndClaude() function to useSessionManager
- Kills all tracked sessions, orphan claudeman screens, and Claude CLI processes
- Press 'D' (Shift+d) in sessions view to trigger
- Update HelpOverlay with new shortcut documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 10:35:35 +01:00
arkonandClaude Opus 4.5 cb4cb202b9 fix: improve reliability and performance across session management
- Add state store flush on shutdown to prevent data loss from debounced saves
- Add error handling in session exit handler to ensure cleanup always runs
- Add 5s timeout to all TUI execSync calls to prevent hangs
- Cache screen -ls output with 100ms TTL (90% reduction in execSync calls)
- Add token pre-check to skip expensive regex when "token" not in data

Based on findings from security, performance, and reliability analysis.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 10:05:39 +01:00
arkonandClaude Opus 4.5 d5ae376e07 feat(tui): add web server auto-start, shell mode, and feature parity
TUI now checks if web server is running on startup and offers to start
it in the background. Added new CLI options: --with-web (auto-start),
--no-web (skip check), -p (port).

TUI feature parity with web interface:
- Shell mode: press 'h' in cases view to start bash instead of Claude
- Multi-start: press 'm' to start 1-20 sessions at once
- Respawn toggle: Ctrl+R to enable/disable respawn on Claude sessions
- Session rename: API support via useSessionManager hook

Security fixes from previous analysis:
- Command injection prevention in screen-manager.ts
- Path traversal protection in server.ts
- Input validation for shell-interpolated values

Also fixes memory leak in session.ts (timer tracking) and flaky test
timeout in session-cleanup.test.ts.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 09:54:42 +01:00
arkonandClaude Opus 4.5 d87711279f feat(tui): add graceful exit handling with terminal restoration
- Handle SIGINT/SIGTERM signals properly
- Unmount Ink app before exit
- Restore cursor visibility and clear screen on exit
- Use try/finally to ensure cleanup runs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:54:32 +01:00
arkonandClaude Opus 4.5 746cfb791c refactor(tui): clean up unused code and consolidate input handling
- Remove unused imports (Text, execSync, writeFileSync, React)
- Move n/r/q key handlers from App.tsx to StartScreen component
- Mark unused onClose prop in HelpOverlay with underscore prefix
- Consolidate keyboard handling in components that display the controls

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:46:11 +01:00
arkonandClaude Opus 4.5 1da51c38d8 docs: add comprehensive JSDoc comments to TUI components
Improves documentation across all TUI files:
- App.tsx: Main component with keyboard shortcuts reference
- index.tsx: Entry point with usage examples
- useSessionManager.ts: Hook with detailed API documentation
- All components: Props, returns, and behavior descriptions
- Helper functions: Parameter and return type documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:44:06 +01:00
arkonandClaude Opus 4.5 bd3bfced96 feat(tui): add respawn status polling and display
- Poll session API every 2 seconds for respawn status
- Display respawn state and cycle count in StatusBar
- Show respawn status in magenta to match web UI
- Format state (underscores to spaces) for readability

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:38:38 +01:00
arkonandClaude Opus 4.5 9c995d204c feat(tui): integrate RalphPanel with live state polling
- Poll inner loop state from state-inner.json every 500ms
- Display RalphPanel when loop is enabled and has data
- Auto-adjust terminal height when panel is shown
- Add innerLoopState and innerTodos to session manager hook

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:33:59 +01:00
arkonandClaude Opus 4.5 c98a86b8f4 feat(tui): add RalphPanel component for loop tracking
- Display Ralph loop status (active/idle)
- Show completion phrase, cycle count, elapsed time
- Display todo list with status icons (pending/in_progress/completed)
- Truncate long todo items, limit to 5 visible
- Use magenta border to match web UI styling

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:30:29 +01:00
arkonandClaude Opus 4.5 4d60cff4f3 feat(tui): improve StatusBar with session name and input mode
- Show session name prominently in status bar
- Add optional inputMode prop for visual feedback
- Update keyboard hints to indicate typing sends input
- Reorganize status bar layout for better readability

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:28:21 +01:00
arkonandClaude Opus 4.5 7bd5260b7d feat(tui): add delete session from start screen
- Press 'd' or 'x' to delete/kill selected session
- Auto-adjust selection index when sessions are removed
- Update footer controls with delete shortcut
- Update help overlay with delete shortcut

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:27:06 +01:00
arkonandClaude Opus 4.5 71373f80d4 docs(tui): update HelpOverlay with all TUI shortcuts
- Add Start Screen section with arrow navigation and attach
- Separate Main View into Navigation and Session Management
- Include all new shortcuts (Enter, a, arrows)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:24:55 +01:00
arkonandClaude Opus 4.5 8da6dcedfa feat(tui): add arrow key navigation and screen attach
- Add arrow key navigation in StartScreen (up/down to move)
- Highlight selected session with blue background
- Press Enter to view session in TUI mode
- Press 'a' to attach directly to GNU screen session
- Attach exits TUI and inherits stdio for full terminal control

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:24:07 +01:00
arkonandClaude Opus 4.5 f6819729aa feat(tui): add real-time terminal output polling
- Poll screen hardcopy every 500ms for live output
- Clean up temp files after reading
- Update CLAUDE.md with TUI documentation
- Add TUI command examples to Commands section

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:21:25 +01:00
arkonandClaude Opus 4.5 84dab25f38 feat(tui): add terminal user interface with Ink
Add a full TUI for Claudeman using Ink (React for CLI):
- StartScreen: Shows existing sessions from screens.json
- TabBar: Session tabs with status indicators
- TerminalView: PTY output display with scrolling
- StatusBar: Session info and keyboard shortcuts
- HelpOverlay: Full keyboard shortcut reference

Features:
- Session discovery from ~/.claudeman/screens.json
- Tab navigation (Ctrl+Tab, Ctrl+1-9)
- Create new sessions (connects to web API)
- Kill sessions via screen commands
- Keyboard-driven navigation

Usage: claudeman tui

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:19:02 +01:00