feat: native TUI REPL + responsive layout for all terminal sizes#103
Merged
feat: native TUI REPL + responsive layout for all terminal sizes#103
Conversation
- `lacp` (no args) now launches the native Textual TUI REPL instead of delegating to claude/codex. `lacp stream` remains available for launching external agents. TUI features: - Multi-provider agent session (Anthropic, OpenAI, Ollama) - 17 built-in tools (file, search, shell, memory, tasks, skills, delegate) - MCP server integration - Session persistence and resume - Hermes-style tool call display with timing - Claude Code-style thinking spinner with token count - Dev panel for live CSS tweaking + theme presets - Idle agent for autoresearch self-improvement - Slash commands with ghost text autocomplete Responsive layout: - on_resize handler applies compact CSS class for <80 col terminals - StatusBar drops segments progressively: <60 model only, <80 +tokens, <120 +cost/mcp, ≥120 full including cwd - Banner skips ASCII logo on narrow terminals, compacts tool/provider lines - Separator width adapts to terminal width - All padding/margins collapse in compact mode
- Removed immediate fallback to Ollama on rate limit (was skipping all Anthropic models because provider name filter excluded haiku too) - Now waits 15s and retries SAME provider on 429 (transient rate limits) - On auth errors (401/missing_scope): refreshes OAuth token from keychain before retrying (Claude Code auto-refreshes tokens in keychain) - Increased Anthropic SDK timeout 15s→60s, retries 0→2 - Removed aggressive fallback chain entirely — stay on chosen provider
Root cause: OAuth tokens via oauth-2025-04-20 beta share rate limits with the active Claude Code CLI session. When Claude Code is running on Opus, Sonnet/Opus requests from LACP TUI hit 429 immediately. Haiku has separate/higher limits and works reliably alongside Claude Code. Users can switch to Opus/Sonnet with /model opus when Claude Code isn't active. Verified: Haiku returns successfully, Sonnet/Opus return 429 when Claude Code is concurrently active on Opus.
Root cause identified: 7 concurrent Claude Code sessions exhaust the per-account OAuth rate limit for Sonnet/Opus. Known issue (anthropics/ claude-code#31637) — retry-after:0 with no rate limit headers. New behavior: - On 429: show how many Claude Code sessions are active (pgrep) - Exponential backoff: 5s → 10s → 20s (3 retries) - After 3 retries: fall back to Haiku with explanation - Clear message: "Sonnet/Opus quota exhausted by N concurrent sessions" - User can /model sonnet when sessions free up
…ies, User-Agent Root cause investigation: analyzed free-code (Claude Code TypeScript source). Discovered Claude Code sends: - x-anthropic-billing-header with CCH attestation (xxHash64) - User-Agent: claude-cli/<version> (undefined, cli) - max_retries=10 with 500ms base delay - All beta headers including interleaved-thinking - 600s timeout (10 minutes) The 429 rate limit is per-account concurrent session capacity. With 5+ active Claude Code sessions, new OAuth requests from any client get rejected at the gateway (35ms response time, no rate limit headers). Established Claude Code sessions keep working because they hold connection-level session state. Changes: - Added x-anthropic-billing-header with CCH placeholder - Matched User-Agent to claude-cli format - Increased retries 2→10 (matches Claude Code DEFAULT_MAX_RETRIES) - Added interleaved-thinking beta header - Default back to Sonnet (was temporarily Haiku) - Exponential backoff on 429 with concurrent session count display
Consolidates all Obsidian brain operations into a single coherent CLI: Status & Health: lacp brain status — vault stats, REST API, health, SMS episodes, inbox lacp brain doctor — full ecosystem health (delegates to brain-doctor) lacp brain gaps — knowledge graph gap analysis Content: lacp brain search — full-text search (REST API with ripgrep fallback) lacp brain read — read any note lacp brain write — write to inbox (enforces write zones) lacp brain ingest — ingest URLs/files lacp brain promote — promote inbox to permanent Knowledge Graph: lacp brain graph — topology summary lacp brain orphans — disconnected notes lacp brain hubs — most connected notes lacp brain links — backlinks + outlinks for a note Memory: lacp brain expand — brain expansion pipeline lacp brain episodes — SMS episodes lacp brain sync — sync sessions to vault lacp brain review — FSRS review queue
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
lacp(no args) now launches the native Textual TUI REPL — its own interactive agent session, not a wrapper around claude/codexlacp streamremains for launching external agents (claude, codex, hermes, etc.)Responsive behavior
TUI capabilities (14 files, 5,536 lines)
Test plan
python3 -c "from tui.repl import LACPRepl"imports cleanlacp helpshows updated usagelacp stream --dry-runstill workslacp doctor --jsonsubcommands unchanged