You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: Add CLI argument parsing for agent selection and initial messages (#44)
## Summary
This PR adds command-line argument parsing to nori-cli, allowing users
to specify the agent and initial message from the command line.
### Changes
- **Add clap dependency**: Added clap v4 with derive feature for CLI
argument parsing
- **New CLI module**: Created `src/cli.rs` with `Cli` struct and agent
name mapping functions
- **Main function updates**: Modified `main.rs` to parse CLI args,
validate agent names, and read from stdin when piped
- **Run app updates**: Updated `run_app` to accept optional
`agent_index` and `initial_message` parameters
- **Comprehensive tests**: Added `tests/cli_args_test.rs` with tests for
all CLI parsing scenarios
- **Documentation updates**: Updated docs in both `src/docs.md` and
`tests/docs.md`
### Usage Examples
```bash
# Use specific agent
nori-cli --agent claude
# Use specific agent with initial message
nori-cli --agent codex "Hello world"
# Pipe input as initial message
echo "Hello from stdin" | nori-cli
# Short flag for agent
nori-cli -a mock "Test message"
```
### Features
- Agent selection via `--agent` or `-a` flag (claude, codex, claudecode,
mock)
- Initial message as positional argument or via stdin piping
- Case-insensitive agent name matching
- Input validation with helpful error messages
- CLI arguments take precedence over stdin when both provided
Copy file name to clipboardExpand all lines: src/docs.md
+21-3Lines changed: 21 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -20,13 +20,14 @@ Core application modules implementing the TUI's architecture: application state
20
20
```rust
21
21
pubmodapp; // Model, Message, and update logic
22
22
pubmodbackends; // AgentBackend trait and implementations
23
+
pubmodcli; // CLI argument parsing and agent name mapping
23
24
pubmodconversation; // JSONL parsing and event rendering
24
25
pubmodui; // Rendering functions for each mode
25
26
```
26
27
27
28
**Entry Point** (@/src/main.rs):
28
-
-`main()`: Sets up terminal (raw mode, Viewport::Inline(8)), runs async event loop, restores terminal on exit with cursor positioning to next line before disabling raw mode to ensure shell prompt appears cleanly below TUI content
29
-
-`run_app()`: Core event loop using tokio::select! to handle messages and render at ~30 fps interval - includes mpsc channel for syncing `last_ctrl_c_time` to event handler task, conditionally increments `loading_frame` counter during streaming when using legacy spinner (only when `use_codex_components = false`)
29
+
-`main()`: Parses CLI arguments via clap::Parser, validates agent name (exits with error if invalid), reads from stdin if piped, then sets up terminal (raw mode, Viewport::Inline(8)), runs async event loop, restores terminal on exit with cursor positioning to next line before disabling raw mode to ensure shell prompt appears cleanly below TUI content
30
+
-`run_app(agent_index, initial_message)`: Core event loop using tokio::select! to handle messages and render at ~30 fps interval - accepts optional agent_index to skip agent selection screen and optional initial_message to pre-fill textarea - includes mpsc channel for syncing `last_ctrl_c_time` to event handler task, conditionally increments `loading_frame` counter during streaming when using legacy spinner (only when `use_codex_components = false`)
30
31
-`handle_event_simple()` / `handle_key_simple()`: Convert crossterm key events to Message based on current mode - Ctrl-C detection happens FIRST before overlay/install prompt checks to ensure double Ctrl-C always works
31
32
-`get_backend()`: Factory function that returns appropriate backend (Claude or Codex) based on selected_agent_index
32
33
-`spawn_and_stream()`: Consumes backend stream using tokio::select! to multiplex stream consumption with cancellation signal - when cancelled, stream is dropped and child process cleanup happens via Drop semantics
@@ -57,6 +58,14 @@ pub mod ui; // Rendering functions for each mode
57
58
-`render_event()`: Converts ConversationEvent into styled ratatui Lines - UserMessage renders with cyan `[user]` prefix, StatusMessage renders with green `[status]` prefix, StreamCancelled renders "Interrupted" in red, other events render with type-specific prefixes and colors
58
59
-`should_render_event()`: Filters events based on debug mode - SystemEvent and UnknownEvent are considered debug events (hidden when `show_debug: false`), all other events (UserMessage, AssistantMessage, ResultSummary, StderrOutput, StreamCancelled, StatusMessage) are always visible
59
60
61
+
**CLI Argument Parsing** (@/src/cli.rs):
62
+
-`Cli` struct: Derives clap::Parser for command-line argument parsing with two optional fields - `agent: Option<String>` for agent selection and `message: Option<String>` for initial message
63
+
-`agent_name_to_index(name)`: Maps agent name strings to backend array indices - supports "claude" (0), "codex" (1), "claudecode" (2), "mock" (3) - case-insensitive matching via .to_lowercase(), returns None for invalid names
64
+
-`valid_agent_names()`: Returns Vec of valid agent names for error messages
65
+
- Agent selection via CLI bypasses TUI selection screen by setting `model.selected_agent_index` directly in run_app()
66
+
- Stdin detection via `io::stdin().is_terminal()` from std::io::IsTerminal trait - reads piped input with `read_to_string()` before TUI initialization
67
+
- CLI message argument takes precedence over stdin when both provided
@@ -208,6 +231,8 @@ Test suite for the agent-router-tui application, covering state machine transiti
208
231
- No integration test for actual stream cancellation with long-running process - test_cancel_stream_during_streaming only tests state machine
209
232
- No integration test for Ctrl-C priority over overlays/install prompts - tests only verify Model state transitions, not actual key event routing in handle_key_simple
210
233
- No test for main loop quit detection (Some → None timestamp transition) - would require full event loop integration
234
+
- No integration tests for CLI argument flow - stdin reading, agent validation with exit code, agent selection bypass, textarea pre-fill - only unit tests for clap parsing and agent name mapping
235
+
- No test for CLI message precedence (CLI arg vs stdin) - would require mocking stdin and command-line args together
211
236
212
237
**CI Integration**:
213
238
- Tests run on every PR via @/.github/workflows/pr-ci.yml
0 commit comments