---
task_id: 0
depth: 1
parent: ../manifest.yaml
siblings: [1:OpenAI-Compatible Backend + Settings: Create backends/openai_compat.py for Ollama/vLLM/llama.cpp. Extend ~/.cleave/settings.yaml with backend/backends configuration. Add backend auto-detection., 2:TUI Integration: Refactor SDKSession to use Backend interface. Update ControlPanel for backend/model selection. Add connection status indicator. Update pyproject.toml with optional deps.]
tdd: false
---

# Task 0: Backend Abstraction Layer: Create src/cleave/tui/backends/ with base.py (abstract Backend class), claude.py (wrap existing SDKSession), and registry in __init__.py. Define Message types, BackendConfig, connection lifecycle, and query streaming interface.

## Mission

Create provider-agnostic backend abstraction layer for LLM inference, enabling Cleave TUI to work with multiple model providers.

## Scope

**In:**
- Abstract Backend class with connect/disconnect/query lifecycle
- Message and BackendConfig dataclasses
- BackendState enum for connection state
- ClaudeBackend wrapping existing Claude SDK code
- Backend registry with get_backend/list_backends functions
- Auto-detection of available backends

**Out:**
- OpenAI-compatible backend (Task 1)
- Settings integration (Task 1)
- TUI widget updates (Task 2)

**Depends on:** None (first task)

**Provides:**
- `from cleave.tui.backends import Backend, BackendConfig, Message`
- `from cleave.tui.backends import get_backend, list_backends`
- `from cleave.tui.backends.claude import ClaudeBackend`

## Result

**Status:** SUCCESS

**Summary:**
Created src/cleave/tui/backends/ package with abstract Backend interface and Claude SDK implementation. The abstraction allows different LLM providers to be used interchangeably. Updated tui/__init__.py to use lazy imports so backends can be imported without textual installed.

**Artifacts:**
- `src/cleave/tui/backends/__init__.py` - Backend registry, exports
- `src/cleave/tui/backends/base.py` - Abstract Backend class, Message, BackendConfig, BackendState
- `src/cleave/tui/backends/claude.py` - ClaudeBackend wrapping Claude Agent SDK
- `src/cleave/tui/__init__.py` - Modified for lazy imports

**Decisions:**
- Used ABC for Backend to enforce interface contract
- BackendConfig is a single dataclass used by all backends (each uses relevant fields)
- Message is common format - backends translate their native events to Message
- Registry uses lazy population to avoid import errors
- MODEL_ALIASES in ClaudeBackend maps shortnames (sonnet, opus, haiku) to full names

**Verification:**
- Command: `PYTHONPATH=src python3 -c "from cleave.tui.backends.claude import ClaudeBackend; print(ClaudeBackend().name)"`
- Output: `Claude`
- Edge cases: Works without textual installed (lazy imports)

**Alignment:** SUCCESS - Provides clean abstraction for multi-model support
