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

11 KiB

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

# 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

# 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

# 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

# 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:

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:

<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

# 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