Files
owlen/CLAUDE.md
vikingowl 0728262a9e fix(core,mcp,security)!: resolve critical P0/P1 issues
BREAKING CHANGES:
- owlen-core no longer depends on ratatui/crossterm
- RemoteMcpClient constructors are now async
- MCP path validation is stricter (security hardening)

This commit resolves three critical issues identified in project analysis:

## P0-1: Extract TUI dependencies from owlen-core

Create owlen-ui-common crate to hold UI-agnostic color and theme
abstractions, removing architectural boundary violation.

Changes:
- Create new owlen-ui-common crate with abstract Color enum
- Move theme.rs from owlen-core to owlen-ui-common
- Define Color with Rgb and Named variants (no ratatui dependency)
- Create color conversion layer in owlen-tui (color_convert.rs)
- Update 35+ color usages with conversion wrappers
- Remove ratatui/crossterm from owlen-core dependencies

Benefits:
- owlen-core usable in headless/CLI contexts
- Enables future GUI frontends
- Reduces binary size for core library consumers

## P0-2: Fix blocking WebSocket connections

Convert RemoteMcpClient constructors to async, eliminating runtime
blocking that froze TUI for 30+ seconds on slow connections.

Changes:
- Make new_with_runtime(), new_with_config(), new() async
- Remove block_in_place wrappers for I/O operations
- Add 30-second connection timeout with tokio::time::timeout
- Update 15+ call sites across 10 files to await constructors
- Convert 4 test functions to #[tokio::test]

Benefits:
- TUI remains responsive during WebSocket connections
- Proper async I/O follows Rust best practices
- No more indefinite hangs

## P1-1: Secure path traversal vulnerabilities

Implement comprehensive path validation with 7 defense layers to
prevent file access outside workspace boundaries.

Changes:
- Create validate_safe_path() with multi-layer security:
  * URL decoding (prevents %2E%2E bypasses)
  * Absolute path rejection
  * Null byte protection
  * Windows-specific checks (UNC/device paths)
  * Lexical path cleaning (removes .. components)
  * Symlink resolution via canonicalization
  * Boundary verification with starts_with check
- Update 4 MCP resource functions (get/list/write/delete)
- Add 11 comprehensive security tests

Benefits:
- Blocks URL-encoded, absolute, UNC path attacks
- Prevents null byte injection
- Stops symlink escape attempts
- Cross-platform security (Windows/Linux/macOS)

## Test Results

- owlen-core: 109/109 tests pass (100%)
- owlen-tui: 52/53 tests pass (98%, 1 pre-existing failure)
- owlen-providers: 2/2 tests pass (100%)
- Build: cargo build --all succeeds

## Verification

- ✓ cargo tree -p owlen-core shows no TUI dependencies
- ✓ No block_in_place calls remain in MCP I/O code
- ✓ All 11 security tests pass

Fixes: #P0-1, #P0-2, #P1-1

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 12:31:20 +01:00

310 lines
11 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
OWLEN is a Rust-powered, terminal-first interface for interacting with local and cloud language models. It uses a multi-provider architecture with vim-style navigation and session management.
**Status**: Alpha (v0.2.0) - core features functional but expect occasional bugs and breaking changes.
## Build, Test & Development Commands
### Building
```bash
# Build all crates
cargo build
# Build release binary
cargo build --release
# Run the TUI (requires Ollama running)
./target/release/owlen
# or
cargo run -p owlen-cli
# Build for specific target (cross-compilation)
dev/local_build.sh x86_64-unknown-linux-gnu
```
### Testing
```bash
# Run all tests
cargo test --all
# Test specific crate
cargo test -p owlen-core
cargo test -p owlen-tui
cargo test -p owlen-providers
# Linting and formatting
cargo clippy --all -- -D warnings
cargo fmt --all -- --check
# Pre-commit hooks (install once with `pre-commit install`)
pre-commit run --all-files
```
### Developer Tasks
```bash
# Regenerate screenshots for documentation
cargo xtask screenshots
cargo xtask screenshots --no-png # skip PNG generation
cargo xtask screenshots --output images/
# Regenerate repository map after structural changes
scripts/gen-repo-map.sh
# Platform compatibility checks
scripts/check-windows.sh # Windows GNU toolchain smoke test
```
### Running Individual Tests
```bash
# Run a specific test by name
cargo test test_name
# Run tests with output
cargo test -- --nocapture
# Run tests in a specific file
cargo test --test integration_test_name
```
## Architecture & Key Concepts
### Workspace Structure (Cargo workspace with 13+ crates)
- **owlen-core**: Core abstractions, provider traits, session management, MCP client layer (UI-agnostic)
- **owlen-tui**: Terminal UI built with ratatui (event loop, rendering, vim modes)
- **owlen-cli**: Entry point that parses args, loads config, launches TUI or headless flows
- **owlen-providers**: Concrete provider adapters (Ollama local, Ollama Cloud)
- **owlen-markdown**: Markdown parsing and rendering
- **crates/mcp/**: Model Context Protocol infrastructure
- **llm-server**: Wraps owlen-providers behind MCP boundary (generate_text tools)
- **server**: Generic MCP server for file ops and workspace tools
- **client**: MCP client implementation
- **code-server**: Code execution sandboxing
- **prompt-server**: Template rendering
- **xtask**: Development automation tasks (screenshots, etc.)
### Dependency Boundaries
- **owlen-core is the dependency ceiling**: Must stay free of terminal logic, CLIs, or provider HTTP clients
- **owlen-cli only orchestrates startup/shutdown**: Business logic belongs in owlen-core or library crates
- **owlen-mcp-llm-server is the only crate that directly talks to providers**: UI/CLI communicate through MCP clients
### Multi-Provider Architecture
```
[owlen-tui / owlen-cli]
│ chat + model requests
[owlen-core::ProviderManager] ──> Arc<dyn ModelProvider>
│ ▲
│ │ implements ModelProvider
▼ │
[owlen-core::mcp::RemoteMcpClient] ────────┘
│ (JSON-RPC over stdio)
┌────────────────────────────────────────────────┐
│ MCP Process Boundary (spawned per provider) │
│ │
│ crates/mcp/llm-server ──> owlen-providers::* │
└────────────────────────────────────────────────┘
```
Key points:
- **ProviderManager** tracks health, merges model catalogs, and dispatches requests
- **RemoteMcpClient** bridges MCP protocol to ModelProvider trait
- **MCP servers** isolate provider-specific code in separate processes
- **Health & availability** tracked via background workers and surfaced in TUI picker
### Event Flow & TUI Architecture
1. User input → Event loop → Message handler → Session controller → Provider manager → Provider
2. Non-blocking design: TUI remains responsive during streaming (see `agents.md` for planned improvements)
3. Modal workflow: Normal, Insert, Visual, Command modes (vim-inspired)
4. AppMessage stream carries async events (provider responses, health checks)
### Session & Conversation Management
- **Conversation** (owlen-core): Holds messages and metadata
- **SessionController**: High-level orchestrator managing history, context, model switching
- Conversations stored in platform-specific data directory (can be encrypted with AES-GCM)
### Configuration
Platform-specific locations:
- Linux: `~/.config/owlen/config.toml`
- macOS: `~/Library/Application Support/owlen/config.toml`
- Windows: `%APPDATA%\owlen\config.toml`
Commands:
```bash
owlen config init # Create default config
owlen config init --force # Overwrite existing
owlen config path # Print config location
owlen config doctor # Migrate legacy configs
```
## Coding Conventions
### Commit Messages
Follow [Conventional Commits](https://www.conventionalcommits.org/):
```
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
```
Types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`, `build`, `ci`
Example: `feat(provider): add support for Gemini Pro`
### Pre-commit Hooks
Hooks automatically run on commit (install with `pre-commit install`):
- `cargo fmt`
- `cargo check`
- `cargo clippy --all-features`
- File hygiene (trailing whitespace, EOF newlines)
To bypass (not recommended): `git commit --no-verify`
### Style Guidelines
- Run `cargo fmt` before committing
- Address all `cargo clippy` warnings
- Use `#[cfg(test)]` modules for unit tests in same file
- Place integration tests in `tests/` directory
## Provider Development
### Adding a New Provider
Follow `docs/adding-providers.md`:
1. Implement `ModelProvider` trait in `owlen-providers`
2. Set `ProviderMetadata::provider_type` (Local/Cloud)
3. Register with `ProviderManager` in startup code
4. Optionally expose through MCP server
5. Add integration tests following `crates/owlen-providers/tests` pattern
6. Document config in `docs/configuration.md` and default `config.toml`
7. Update `README.md`, `CHANGELOG.md`, `docs/troubleshooting.md`
See `docs/provider-implementation.md` for trait-level details.
### MCP Tool Naming
Enforce spec-compliant identifiers: `^[A-Za-z0-9_-]{1,64}$`
- Use underscores or hyphens (e.g., `web_search`, `filesystem_read`)
- Avoid dotted names (legacy incompatible)
- Qualify with `{server}__{tool}` when multiple servers overlap (e.g., `filesystem__read`)
## Repository Automation
OWLEN includes Git-aware automation for code review and commit templating:
### CLI Commands
```bash
# Generate commit message from staged diff
owlen repo commit-template
owlen repo commit-template --working-tree # inspect unstaged
# Review branch or PR
owlen repo review
owlen repo review --owner Owlibou --repo owlen --number 42 --token-env GITHUB_TOKEN
```
### TUI Commands
```
:repo template # inject commit template into chat
:repo review [--base BRANCH] [--head REF] # review local changes
```
## Key Files & Entry Points
### Main Entry Points
- `crates/owlen-cli/src/main.rs` - CLI entry point (argument parsing, config loading)
- `crates/owlen-tui/src/app/mod.rs` - Main TUI application and event dispatch
- `crates/owlen-core/src/provider.rs` - ModelProvider trait definition
### Configuration & State
- `crates/owlen-core/src/config.rs` - Configuration loading and parsing
- `crates/owlen-core/src/session.rs` - Session and conversation management
- `crates/owlen-core/src/storage.rs` - Persistence layer
### Provider Infrastructure
- `crates/owlen-providers/src/ollama/` - Ollama local and cloud providers
- `crates/mcp/llm-server/src/main.rs` - MCP LLM server process
- `crates/owlen-core/src/mcp/remote_client.rs` - MCP client implementation
## Testing Strategy
### Unit Tests
Place in `#[cfg(test)]` modules within source files for isolated component testing.
### Integration Tests
Place in `tests/` directories:
- `crates/owlen-providers/tests/` - Provider integration tests
- Test registration, model aggregation, request routing, health transitions
### Focus Areas
- Command palette state machine
- Agent response parsing
- MCP protocol abstractions
- Provider manager health cache
- Session controller lifecycle
## Documentation Structure
- `README.md` - User-facing overview, installation, features
- `CONTRIBUTING.md` - Contribution guidelines, development setup
- `docs/architecture.md` - High-level architecture (read first!)
- `docs/repo-map.md` - Workspace layout snapshot
- `docs/adding-providers.md` - Provider implementation checklist
- `docs/provider-implementation.md` - Trait-level provider details
- `docs/testing.md` - Testing guide
- `docs/troubleshooting.md` - Common issues and solutions
- `docs/configuration.md` - Configuration reference
- `docs/platform-support.md` - OS support matrix
## Important Implementation Notes
### When Working on TUI Code
- Modal state machine is critical: Normal ↔ Insert ↔ Visual ↔ Command
- Status line shows current mode (use as regression check)
- Non-blocking event loop planned (see `agents.md`)
- Command palette state lives in `owlen_tui::state`
- Follow Model-View-Update pattern for new features
### When Working on Providers
- Never import providers directly in owlen-tui or owlen-cli
- All provider communication goes through owlen-core abstractions
- Health checks run on background workers
- Model discovery fans out through ProviderManager
### When Working on MCP Integration
- RemoteMcpClient implements both MCP client traits and ModelProvider
- MCP servers are short-lived, narrowly scoped binaries
- Tool calls travel same transport as chat requests
- Consent prompts surface in UI via session events
## Platform Support
- **Primary**: Linux (Arch AUR: `owlen-git`)
- **Supported**: macOS 12+ (requires Command Line Tools for OpenSSL)
- **Experimental**: Windows (GNU toolchain, some Docker features disabled)
Cross-platform testing: Use `dev/local_build.sh` and `scripts/check-windows.sh`
## Dependencies & Async Runtime
- **Async runtime**: tokio with "full" features
- **TUI framework**: ratatui 0.29 with palette features
- **HTTP client**: reqwest with rustls-tls (no native-tls)
- **Database**: SQLx with sqlite, tokio runtime
- **Serialization**: serde + serde_json
- **Testing**: tokio-test for async test utilities
## Security & Privacy
- Local-first: LLM calls route through local Ollama by default
- Session encryption: Set `privacy.encrypt_local_data = true` for AES-GCM storage
- No telemetry sent
- Outbound requests only when explicitly enabling remote tools/providers
- Config migrations carry schema version and warn on deprecated keys