crabcode 0.0.1

(WIP) Rust AI CLI Coding Agent with a beautiful terminal UI
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
# Crabcode - Rust AI CLI Coding Agent

## Overview

Crabcode is a Rust-based AI coding CLI tool inspired by [anomalyco/opencode](https://github.com/anomalyco/opencode). It provides a terminal UI (TUI) for interacting with AI coding agents, featuring auto-suggestions, multiple model support, agent switching, and streaming chat interface.

## MVP Scope

The MVP focuses on core features with minimal complexity:
- Native terminal UI using ratatui and tui-textarea
- Commands: `/sessions`, `/new`, `/connect`, `/models`, `/exit`
- Agent system with TAB switching (PLAN and BUILD agents only)
- Model support prioritizing nano-gpt and z.ai coding plan
- Auto-suggestions on `/` press for commands and `@` press for files
- Models.dev API integration for model discovery
- Chat-like streaming interface
- Logo display on landing page
- Select-to-copy functionality
- Status bar with version (bottom-right) and directory + git branch (bottom-left)

## Tech Stack

### Key Design Decision
**AI Abstraction Strategy**: crabcode uses [lazy-hq/aisdk](https://github.com/lazy-hq/aisdk) as the primary AI abstraction layer. This provides:
- Provider-agnostic LLM access (OpenAI, Anthropic, Google, Groq, etc.)
- Built-in streaming support
- Agent and tool system
- Structured output capabilities
- Avoids reinventing the wheel for AI interactions

### Core Dependencies
- **ratatui** - Terminal UI framework (Rust equivalent to React/SolidJS for TUI)
  - Popup example: https://ratatui.rs/examples/apps/popup/
- **tui-textarea** - Multi-line text input component
  - Repository: https://github.com/rhysd/tui-textarea
- **tokio** - Async runtime for streaming and HTTP requests
- **reqwest** - HTTP client for API calls
- **serde/serde_json** - Serialization/deserialization
- **anyhow** - Error handling
- **clap** - CLI argument parsing (optional, can use built-in command parsing)
- **ignore** - .gitignore file filtering
- **aisdk** - AI SDK for provider-agnostic LLM interactions
  - Repository: https://github.com/lazy-hq/aisdk
  - Documentation: https://aisdk.rs

### AI Integration
- **lazy-hq/aisdk** - Rust AI SDK (primary AI abstraction layer)
  - Documentation: https://aisdk.rs
  - Features: streaming, tools, agents, structured output
  - Provider support: OpenAI, Anthropic, Google, Groq, OpenRouter, etc.
- Provider-agnostic model interface through aisdk
- Streaming via aisdk's built-in streaming capabilities

## Architecture

### Project Structure

```
crabcode/
├── Cargo.toml              # Dependencies
├── src/
│   ├── main.rs             # Entry point
│   ├── app.rs              # Application state and lifecycle
│   ├── ui/
│   │   ├── mod.rs
│   │   ├── components/
│   │   │   ├── mod.rs
│   │   │   ├── landing.rs       # Logo landing page
│   │   │   ├── chat.rs         # Chat message display
│   │   │   ├── input.rs        # Text input with auto-suggestions
│   │   │   ├── popup.rs        # Auto-suggestion popup
│   │   │   └── status_bar.rs   # Bottom status bar
│   │   └── layout.rs          # Main layout composition
│   ├── agent/
│   │   ├── mod.rs
│   │   ├── types.rs           # Agent definitions
│   │   ├── manager.rs         # Agent switching logic
│   │   └── plan.rs            # PLAN agent
│   │   └── build.rs           # BUILD agent
│   ├── model/
│   │   ├── mod.rs
│   │   ├── types.rs           # Model configuration
│   │   ├── discovery.rs       # Models.dev API integration
│   │   ├── aisdk_adapter.rs   # aisdk provider adapter
│   │   └── config.rs           # aisdk configuration
│   ├── session/
│   │   ├── mod.rs
│   │   ├── types.rs           # Session state
│   │   └── manager.rs         # Session CRUD
│   ├── command/
│   │   ├── mod.rs
│   │   ├── parser.rs          # Command parsing (/)
│   │   ├── registry.rs        # Command registration
│   │   └── handlers.rs        # Command implementations
│   ├── autocomplete/
│   │   ├── mod.rs
│   │   ├── command.rs         # / command suggestions
│   │   └── file.rs            # @ file suggestions
│   ├── streaming/
│   │   ├── mod.rs
│   │   ├── adapter.rs         # aisdk stream adapter
│   │   └── events.rs          # UI event mapping from aisdk
│   └── utils/
│       ├── mod.rs
│       ├── git.rs             # Git branch detection
│       ├── ignore.rs          # .gitignore parsing
│       └── frecency.rs        # File usage scoring
└── assets/
    └── logo.txt            # ASCII logo from crabcode-logo.txt
```

### Core Components

#### 1. Landing Page (`src/ui/components/landing.rs`)
- Display centered ASCII logo from `assets/logo.txt`
- Initial state when no session is active
- Transition to chat view on first user action

#### 2. Chat Interface (`src/ui/components/chat.rs`)
- Scrollable message display area
- Support for markdown rendering (basic: code blocks, bold, lists)
- User messages and AI responses styled differently
- Streaming text updates (append chunks as they arrive)
- Auto-scroll to latest message

#### 3. Input Component (`src/ui/components/input.rs`)
- Based on tui-textarea for multi-line editing
- Event handling:
  - `/` press → Show command suggestions
  - `@` press → Show file suggestions
  - Arrow keys → Navigate suggestions
  - Enter → Submit (or select suggestion if popup open)
  - TAB → Switch agent
  - Ctrl+C → Copy selected text
- History: Up/Down arrows navigate past inputs

#### 4. Auto-Suggestion Popup (`src/ui/components/popup.rs`)
- Dynamic positioning near cursor (inspired by ratatui popup example)
- Two modes: `/` (commands) and `@` (files)
- Fuzzy filtering as user types
- Keyboard navigation (Arrow Up/Down, Enter to select)
- Close on Escape or when suggestion doesn't match

#### 5. Status Bar (`src/ui/components/status_bar.rs`)
- Bottom-left: `crabcode {version} | {cwd} ({branch})`
- Bottom-right: Agent and Model display: `<PLAN> <nano-gpt>`

## Features

### Command System (`/commands`)

Commands are registered in a registry and triggered by typing `/`:

| Command | Description | Parameters |
|---------|-------------|-------------|
| `/sessions` | List all sessions | None |
| `/new` | Create new session | Optional: name |
| `/connect` | Connect/configure model | Optional: provider, model |
| `/models` | List available models | Optional: provider filter |
| `/exit` | Quit crabcode | None |

#### Command Registry Pattern
```rust
pub struct Command {
    pub name: String,
    pub description: String,
    pub handler: fn(&mut App, args: Vec<String>) -> Result<()>,
}

pub struct CommandRegistry {
    commands: HashMap<String, Command>,
}
```

### Agent System

#### Agent Types
Two primary agents for MVP (mode = "primary"):

| Agent | Description | Permissions |
|-------|-------------|-------------|
| PLAN | Read-only analysis and planning | No file writes, bash = ask |
| BUILD | Full access for implementation | All tools enabled |

#### Agent Switching (TAB)
- Circular navigation through agent list
- Filter: Only agents with `mode != "subagent"` and `!hidden`
- When switching, update:
  - Current agent name in status bar
  - Agent-specific model (if configured)
  - Agent color theme

#### Agent Configuration
```rust
pub struct Agent {
    pub name: String,
    pub mode: AgentMode,  // "primary" or "subagent"
    pub description: Option<String>,
    pub native: bool,           // Built-in vs custom
    pub hidden: bool,            // Show in TAB cycle
    pub model: Option<ModelConfig>,
    pub temperature: Option<f32>,
    pub top_p: Option<f32>,
}

pub enum AgentMode {
    Primary,
    Subagent,
}
```

#### Tool Integration (via aisdk)
- Use aisdk's `#[tool]` macro to expose Rust functions
- Example tools for MVP:
  - File read/write operations
  - Git operations (with user confirmation)
  - Shell command execution (ask mode for PLAN, execute for BUILD)
- Tool permissions based on agent type
- Tools registered with aisdk agent system

### Model System

#### Models.dev Integration
- Fetch from `https://models.dev/api.json`
- Parse model list with provider information
- Cache locally (TTL: 24 hours)
- Provide `/models` command to list available models
- Cross-reference with aisdk-supported providers

#### Provider Support (via aisdk)
Priority models for MVP:
1. **OpenAI** (via aisdk)
   - Models: gpt-4, gpt-3.5-turbo, etc.
   - Streaming: Built-in to aisdk
   - Auth: API key via `OPENAI_API_KEY` env var

2. **Anthropic** (via aisdk)
   - Models: claude-3-opus, claude-3-sonnet, etc.
   - Streaming: Built-in to aisdk
   - Auth: API key via `ANTHROPIC_API_KEY` env var

3. **Additional aisdk providers** (as needed)
   - Google (Gemini)
   - Groq
   - OpenRouter
   - xAI (Grok)

#### Model Configuration
```rust
pub struct Model {
    pub id: String,
    pub name: String,
    pub provider_id: String,
    pub provider_name: String,
    pub capabilities: Vec<String>,
}

pub struct ModelConfig {
    pub provider_id: String,
    pub model_id: String,
    pub api_key: Option<String>,
    pub temperature: Option<f32>,
    pub max_tokens: Option<u32>,
}

// aisdk provider adapter
pub fn create_provider(config: &ModelConfig) -> Result<Box<dyn aisdk::core::LanguageModel>> {
    match config.provider_id.as_str() {
        "openai" => Ok(Box::new(aisdk::providers::openai::OpenAI::new(config.model_id.clone())?)),
        "anthropic" => Ok(Box::new(aisdk::providers::anthropic::Anthropic::new(config.model_id.clone())?)),
        _ => Err(anyhow::anyhow!("Unsupported provider: {}", config.provider_id)),
    }
}
```

### Auto-Suggestions

#### Command Suggestions (`/` trigger)
Trigger: User types `/` at start of input or `/command` pattern

- Parse: `/(\w*)` regex match
- Filter: Registered commands matching query
- Display: Popup with `Command - Description` format
- On select: Insert command name with space

#### File Suggestions (`@` trigger)
Trigger: User types `@` anywhere in input

- Parse: `@(\S*)$` regex match at cursor position
- Filter: Files in current CWD (excluding .gitignore)
- Scoring: Use frecency (frequency + recency)
- Display: Popup with file paths
- On select: Insert file path with syntax highlighting

#### File Discovery
```rust
pub fn discover_files(cwd: &Path) -> Result<Vec<PathBuf>> {
    let gitignore = load_gitignore(cwd)?;
    walkdir(cwd)?
        .filter(|entry| {
            !gitignore.is_excluded(entry.path())
                && entry.file_type().is_file()
        })
        .collect()
}
```

### Streaming Chat

#### Stream Events
Inspired by opencode's stream event types, mapped from aisdk:

| Event | Meaning | UI Action |
|--------|----------|------------|
| `start` | Generation started | Show busy indicator |
| `text-delta` | Text chunk received | Append to current message |
| `tool-call` | AI calling a tool (via aisdk agent) | Display tool invocation |
| `tool-result` | Tool execution result | Show tool output |
| `done` | Stream complete | Mark message as finished |
| `error` | Stream failed | Show error state |

#### Streaming Implementation
```rust
use aisdk::core::LanguageModelRequest;
use aisdk::providers::openai::OpenAI;

pub async fn stream_request(
    model: &ModelConfig,
    prompt: &str,
) -> Result<impl Stream<Item = StreamEvent>> {
    let provider = aisdk_adapter::create_provider(model)?;
    
    let stream = LanguageModelRequest::builder()
        .model(provider)
        .prompt(prompt)
        .build()
        .stream_text()
        .await?;

    Ok(stream.map(|chunk| {
        match chunk {
            Ok(text) => StreamEvent::TextDelta(text),
            Err(e) => StreamEvent::Error(e.to_string()),
        }
    }))
}

pub enum StreamEvent {
    TextDelta(String),
    Done,
    Error(String),
}
```

### Select-to-Copy

- User selects text with mouse
- On release, copy to system clipboard
- Visual feedback: brief flash of selected text
- Use `copypasta` crate for clipboard operations

### Status Bar

#### Left Side
Format: `crabcode v{version} | {cwd} ({branch})`

```rust
pub struct StatusInfo {
    pub version: String,
    pub cwd: String,
    pub branch: Option<String>,
}
```

#### Right Side
Format: `<{agent}> <{model}>`

Color-coded by agent:
- PLAN: Green
- BUILD: Blue
- Custom: Yellow

## Implementation Phases

### Phase 1: Foundation (Week 1)
- [x] Project setup (Cargo.toml, basic structure)
- [x] Main loop with ratatui Terminal
- [x] Landing page with logo display
- [x] Basic text input using tui-textarea
- [x] Command parsing (`/` trigger)
- [x] `/exit` command implementation

### Phase 2: UI Components (Week 2)
- [x] Chat message display component
- [x] Auto-suggestion popup (ratatui popup example)
- [x] Status bar implementation
- [x] Git branch detection
- [x] CWD display
- [x] `/sessions` and `/new` commands

### Phase 3: Model Integration (Week 3)
- [x] Model configuration types
- [x] Provider trait definition
- [x] Models.dev API client
- [x] `/models` command
- [x] `/connect` command for API keys
- [ ] Add aisdk to Cargo.toml with provider features
- [ ] Implement aisdk provider adapter
- [ ] Configure OpenAI provider via aisdk
- [ ] Configure Anthropic provider via aisdk
- [ ] Test streaming with aisdk

### Phase 4: Agent System (Week 4)
- [ ] Agent type definitions
- [ ] Agent manager (TAB switching)
- [ ] PLAN agent configuration
- [ ] BUILD agent configuration
- [ ] Agent display in status bar
- [ ] Model switching with agent

### Phase 5: Auto-Suggestions (Week 5)
- [ ] Command suggestion registry
- [ ] File discovery (.gitignore filtering)
- [ ] Frecency scoring for files
- [ ] `@` trigger and popup
- [ ] `/` trigger and popup
- [ ] Keyboard navigation in popups

### Phase 6: Streaming (Week 6)
- [ ] Implement aisdk stream adapter
- [ ] Map aisdk stream events to UI events
- [ ] Chat message streaming (text-delta via aisdk)
- [ ] Tool call display (via aisdk agent system)
- [ ] Auto-scroll to latest message

### Phase 7: Polish (Week 7-8)
- [ ] Select-to-copy functionality
- [ ] Markdown rendering (basic)
- [ ] Error handling and user feedback
- [ ] Configuration file support
- [ ] Documentation
- [ ] Testing

## Configuration

### Config File Location
`~/.config/crabcode/config.toml`

### Config Structure
```toml
[general]
version = "0.1.0"

[models]
api_keys_dir = "~/.config/crabcode/keys/"
# Supported providers via aisdk: openai, anthropic, google, groq, openrouter, etc.

[agent.plan]
name = "plan"
model_provider = "openai"
model_id = "gpt-4"
temperature = 0.5

[agent.build]
name = "build"
model_provider = "anthropic"
model_id = "claude-3-5-sonnet"
temperature = 0.7

[aisdk]
# aisdk-specific configuration
enable_streaming = true
enable_tools = true
max_retries = 3

[ui]
theme = "default"  # dark, light
max_history = 100
```

## Testing Strategy

### Unit Tests
- Command parsing logic
- File discovery and .gitignore filtering
- Frecency scoring algorithm
- Model configuration parsing
- Stream event parsing

### Integration Tests
- Models.dev API client
- aisdk provider adapter
- aisdk streaming (with mock API keys)
- Agent switching logic
- Session persistence

### E2E Tests
- Full chat flow with streaming
- Command execution
- Agent switching
- File suggestion workflow

## Future Enhancements (Post-MVP)

### Additional Commands
- `/help` - Show command help
- `/clear` - Clear current session
- `/export` - Export session to file
- `/import` - Import session from file

### More Agents
- EXPLORE - Fast codebase search (like opencode's explore)
- REVIEW - Code review agent
- REFACTOR - Refactoring specialist

### Tool Support
- File read/write operations (via aisdk `#[tool]` macro)
- Git operations (commit, branch, diff)
- Shell command execution (with confirmation)
- Code execution (sandboxed)
- Leverage aisdk's tool execution engine

### Advanced Features
- Multi-session support
- Session persistence
- Collaboration mode (share sessions)
- Custom agent definitions
- Plugin system
- Leverage aisdk's advanced features:
  - Multi-agent orchestration
  - Structured output with JSON Schema
  - Prompt templating (via aisdk prompt feature)
  - Embedding support for semantic search

## References

### Inspiration
- [anomalyco/opencode]https://github.com/anomalyco/opencode - Primary inspiration for UX and architecture
- [lazy-hq/aisdk]https://github.com/lazy-hq/aisdk - **Primary AI SDK for provider abstraction, streaming, agents, and tools**
  - Documentation: https://aisdk.rs
- [anomalyco/models.dev]https://github.com/anomalyco/models.dev - Model discovery API
- [ratatui]https://github.com/ratatui-org/ratatui - TUI framework
- [rhysd/tui-textarea]https://github.com/rhysd/tui-textarea - Text input component

### Resources
- [ratatui popup example]https://ratatui.rs/examples/apps/popup/ - Popup implementation reference
- [models.dev API]https://models.dev/api.json - Model catalog
- [aisdk documentation]https://aisdk.rs - AI SDK usage guide
- [aisdk API reference]https://docs.rs/aisdk/latest - aisdk Rust API docs

## License

TBD (likely MIT or Apache-2.0)

## Contributing

After MVP completion, contribution guidelines will be established focusing on:
- Code style (rustfmt)
- Testing requirements
- Documentation standards
- Feature proposal process