# claif_cla - Claude Provider for Claif
A Claif provider for Anthropic's Claude with full OpenAI client API compatibility. This package wraps the `claude-code-sdk` to provide a consistent interface following the `client.chat.completions.create()` pattern.
## Features
- **OpenAI Client API Compatible**: Use the familiar `client.chat.completions.create()` pattern
- **Full Type Safety**: Returns standard `ChatCompletion` and `ChatCompletionChunk` objects
- **Streaming Support**: Real-time streaming with proper chunk handling
- **Session Management**: Persistent conversation history with atomic operations
- **Tool Approval**: Fine-grained control over MCP tool usage
- **Response Caching**: Intelligent caching to reduce API costs
- **Fire-based CLI**: Rich terminal interface with multiple output formats
## Quickstart
```bash
# Install
pip install claif_cla
# Basic usage - OpenAI compatible
python -c "
from claif_cla import ClaudeClient
client = ClaudeClient()
response = client.chat.completions.create(
messages=[{'role': 'user', 'content': 'Hello Claude!'}],
model='claude-3-5-sonnet-20241022'
)
print(response.choices[0].message.content)
"
# CLI usage
claif-cla query "Explain quantum computing"
claif-cla chat --model claude-3-opus-20240229
```
## What is claif_cla?
`claif_cla` is a Python wrapper that integrates Anthropic's Claude into the Claif framework with full OpenAI client API compatibility. It provides a thin layer over the [`claude_code_sdk`](https://github.com/anthropics/claude-code-sdk-python) package, adding session management, tool approval strategies, and response caching while maintaining full compatibility with Claude's capabilities.
**Key Features:**
- **Session persistence** - Save and restore conversations across sessions
- **Tool approval strategies** - Fine-grained control over MCP tool usage
- **Response caching** - Reduce API costs with intelligent caching
- **Rich CLI** - Beautiful terminal interface with Fire framework
- **Async support** - Full async/await for efficient operations
- **Type safety** - Comprehensive type hints throughout
## Installation
### Basic Installation
```bash
# Core package only
pip install claif_cla
# With Claif framework
pip install claif claif_cla
```
### Installing Claude CLI
The Claude CLI can be installed automatically:
```bash
# Using claif_cla installer
python -m claif_cla.install
# Or manually via npm
npm install -g @anthropic-ai/claude-code
# Or using Claif's installer
pip install claif && claif install claude
```
### Development Installation
```bash
git clone https://github.com/twardoch/claif_cla.git
cd claif_cla
pip install -e ".[dev,test]"
```
## Usage
### Basic Usage (OpenAI-Compatible)
```python
from claif_cla import ClaudeClient
# Initialize the client
client = ClaudeClient(
api_key="your-api-key" # Optional, uses ANTHROPIC_API_KEY env var
)
# Create a chat completion - exactly like OpenAI
response = client.chat.completions.create(
model="claude-3-5-sonnet-20241022",
messages=[
{"role": "system", "content": "You are a helpful assistant"},
{"role": "user", "content": "Explain machine learning"}
],
temperature=0.7,
max_tokens=1000
)
# Access the response
print(response.choices[0].message.content)
print(f"Model: {response.model}")
print(f"Usage: {response.usage}")
```
### Streaming Responses
```python
from claif_cla import ClaudeClient
client = ClaudeClient()
# Stream responses in real-time
stream = client.chat.completions.create(
model="claude-3-5-sonnet-20241022",
messages=[
{"role": "user", "content": "Write a haiku about programming"}
],
stream=True
)
# Process streaming chunks
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
```
## CLI Usage
```bash
# Basic query
claif-cla query "What is the theory of relativity?"
# With specific model
claif-cla query "Explain Python decorators" --model claude-3-opus-20240229
# Interactive chat mode
claif-cla chat --model claude-3-5-sonnet-20241022
# List available models
claif-cla models
# JSON output
claif-cla query "Hello" --json-output
```
### Session Management
```bash
# List all sessions
python -m claif_cla.cli session list
# Create new session with optional metadata
python -m claif_cla.cli session create --metadata '{"project": "my-app"}'
# Show session messages
python -m claif_cla.cli session show SESSION_ID
# Continue existing session
python -m claif_cla.cli ask "Continue our discussion" --session SESSION_ID
# Export session to file
python -m claif_cla.cli session export SESSION_ID --format markdown --output chat.md
python -m claif_cla.cli session export SESSION_ID --format json --output chat.json
# Delete session
python -m claif_cla.cli session delete SESSION_ID
```
### Advanced Features
```bash
# Benchmark response time
python -m claif_cla.cli benchmark "Complex analysis task" --iterations 5
# Set approval strategy for tools
python -m claif_cla.cli ask "Analyze this file" --approval allow_list --allowed-tools "read_file,search"
# Use with caching
python -m claif_cla.cli ask "Expensive computation" --cache --cache-ttl 3600
# Verbose mode for debugging
python -m claif_cla.cli ask "Debug this" --verbose
```
## API Compatibility
This package is fully compatible with the OpenAI Python client API:
```python
# You can use it as a drop-in replacement
from claif_cla import ClaudeClient as OpenAI
client = OpenAI()
# Now use exactly like the OpenAI client
response = client.chat.completions.create(
model="claude-3-5-sonnet-20241022",
messages=[{"role": "user", "content": "Hello!"}]
)
```
## Migration from Old Async API
If you were using the old async-based Claif API:
```python
# Old API (deprecated)
import asyncio
from claif_cla import query
from claif.common import ClaifOptions
async def old_way():
async for message in query("Hello, Claude!"):
print(f"{message.role}: {message.content}")
# New API (OpenAI-compatible)
from claif_cla import ClaudeClient
def new_way():
client = ClaudeClient()
response = client.chat.completions.create(
messages=[{"role": "user", "content": "Hello, Claude!"}],
model="claude-3-5-sonnet-20241022"
)
print(response.choices[0].message.content)
```
### Key Changes
1. **Synchronous by default**: No more `async/await` for basic usage
2. **OpenAI-compatible structure**: `client.chat.completions.create()` pattern
3. **Standard message format**: `[{"role": "user", "content": "..."}]`
4. **Streaming support**: Use `stream=True` for real-time responses
5. **Type-safe responses**: Returns `ChatCompletion` objects from OpenAI types
### Session Management
```python
from claif_cla.session import SessionManager, Session
from claif.common import Message, MessageRole
# Initialize session manager
session_mgr = SessionManager()
# Create new session
session_id = session_mgr.create_session(
metadata={"project": "my-app", "user": "john"}
)
# Add messages to session
user_msg = Message(
role=MessageRole.USER,
content="What is machine learning?"
)
session_mgr.add_message(session_id, user_msg)
# Get session history
session = session_mgr.get_session(session_id)
for msg in session.messages:
print(f"{msg.role}: {msg.content}")
# Export session
markdown_export = session_mgr.export_session(session_id, export_format="markdown")
print(markdown_export)
# Save session to disk
session_mgr.save_session(session_id)
```
### Tool Approval Strategies
```python
from claif_cla.approval import create_approval_strategy
# Strategy 1: Allow specific tools only
safe_tools = create_approval_strategy("allow_list", {
"allowed_tools": ["read_file", "list_files", "search"]
})
# Strategy 2: Deny dangerous tools
deny_dangerous = create_approval_strategy("deny_list", {
"denied_tools": ["delete_file", "execute_command", "write_file"]
})
# Strategy 3: Pattern-based approval
patterns = create_approval_strategy("pattern", {
"patterns": ["read_.*", "list_.*", "search_.*"],
"deny": False # Allow matching patterns
})
# Strategy 4: Threshold-based (by risk score)
threshold = create_approval_strategy("threshold", {
"max_risk": 3 # Only allow tools with risk <= 3
})
# Use strategy in query
from claif_cla import ClaudeCodeOptions
options = ClaudeCodeOptions(
tool_approval_strategy=safe_tools,
model="claude-3-opus-20240229"
)
```
### Response Caching
```python
from claif_cla.wrapper import ClaudeWrapper, ResponseCache
# Create wrapper with caching
wrapper = ClaudeWrapper(
cache_ttl=3600, # 1 hour cache
enable_cache=True
)
# First call - hits API
response1 = await wrapper.query("Expensive analysis", options)
# Second call - returns from cache
response2 = await wrapper.query("Expensive analysis", options)
# Clear cache if needed
wrapper.cache.clear()
```
### Using with Claif Framework
```python
from claif import query as claif_query, Provider, ClaifOptions
# Query through Claif framework
options = ClaifOptions(
provider=Provider.CLAUDE,
model="claude-3-opus-20240229",
temperature=0.5
)
async for message in claif_query("Hello from Claif!", options):
print(message.content)
```
## How It Works
### Architecture Overview
```
┌─────────────────────────────┐
│ User Application │
├─────────────────────────────┤
│ claif_cla CLI │ ← Fire-based CLI with rich output
├─────────────────────────────┤
│ claif_cla Core │ ← Main query function & types
├─────────────────────────────┤
│ Session Manager │ ← Conversation persistence
├─────────────────────────────┤
│ Approval Strategies │ ← Tool usage control
├─────────────────────────────┤
│ Response Cache │ ← Cost optimization
├─────────────────────────────┤
│ claude_code_sdk │ ← Anthropic's SDK
└─────────────────────────────┘
```
### Core Components
#### Main Module (`__init__.py`)
The entry point that provides the `query` function:
```python
async def query(
prompt: str,
options: ClaifOptions | None = None
) -> AsyncIterator[Message]:
"""Query Claude with Claif-compatible interface."""
# Convert Claif options to Claude options
claude_options = _convert_options(options)
# Delegate to claude_code_sdk
async for message in claude_query(prompt, claude_options):
yield message
```
Key features:
- Thin wrapper design for minimal overhead
- Option conversion between Claif and Claude formats
- Direct message passthrough
- Loguru-based debug logging
#### CLI Module (`cli.py`)
Fire-based command-line interface with rich formatting:
```python
class ClaudeCLI:
def ask(self, prompt: str, **kwargs):
"""Ask Claude a question."""
def stream(self, prompt: str, **kwargs):
"""Stream responses in real-time."""
def interactive(self):
"""Start interactive chat session."""
def session(self, action: str, **kwargs):
"""Manage conversation sessions."""
```
Commands:
- `ask` - Single query with options
- `stream` - Real-time streaming responses
- `interactive` - Chat mode with history
- `session` - CRUD operations for conversations
- `health` - Check Claude availability
- `benchmark` - Performance testing
#### Session Module (`session.py`)
Persistent conversation management:
```python
@dataclass
class Session:
id: str
messages: list[Message]
metadata: dict[str, Any]
created_at: datetime
updated_at: datetime
class SessionManager:
def __init__(self, session_dir: Path | None = None):
self.session_dir = session_dir or Path.home() / ".claif" / "sessions"
```
Features:
- JSON-based session storage
- Atomic file operations
- Session templates (coding, analysis, creative)
- Export to Markdown/JSON formats
- Metadata for organization
#### Approval Module (`approval.py`)
Fine-grained control over MCP tool usage:
```python
class ApprovalStrategy(ABC):
@abstractmethod
def should_approve(self, tool_name: str, tool_metadata: dict) -> bool:
"""Decide if tool should be approved."""
# Eight concrete strategies:
1. AllowAllStrategy - Approve everything
2. DenyAllStrategy - Deny everything
3. AllowListStrategy - Only allow specific tools
4. DenyListStrategy - Deny specific tools
5. PatternStrategy - Regex-based approval
6. ThresholdStrategy - Risk score based
7. CategoryStrategy - Approve by category
8. CompositeStrategy - Combine multiple strategies
```
Factory function for easy creation:
```python
strategy = create_approval_strategy("allow_list", {
"allowed_tools": ["read_file", "search"]
})
```
#### Wrapper Module (`wrapper.py`)
Enhanced functionality around claude_code_sdk:
```python
class ResponseCache:
"""SHA256-based response caching."""
def get_cache_key(self, prompt: str, options: dict) -> str:
data = json.dumps({"prompt": prompt, "options": options})
return hashlib.sha256(data.encode()).hexdigest()
class ClaudeWrapper:
"""Adds retry logic and caching."""
async def query_with_retry(self, prompt: str, options, max_retries=3):
for attempt in range(max_retries):
try:
return await self._query(prompt, options)
except Exception as e:
if attempt == max_retries - 1:
raise
await asyncio.sleep(2 ** attempt)
```
Features:
- SHA256-based cache keys
- TTL support for cache entries
- Exponential backoff retry logic
- Graceful error handling
### Code Structure
```
claif_cla/
├── src/claif_cla/
│ ├── __init__.py # Main query function and exports
│ ├── cli.py # Fire-based CLI interface
│ ├── wrapper.py # Caching and retry logic
│ ├── session.py # Session management
│ ├── approval.py # Tool approval strategies
│ └── install.py # CLI installation helper
├── tests/
│ ├── test_session.py # Session tests
│ ├── test_approval.py # Strategy tests
│ └── test_wrapper.py # Cache tests
├── pyproject.toml # Package configuration
├── README.md # This file
└── CLAUDE.md # Development guide
```
### Message Flow
1. **User Input** → CLI command or API call
2. **Option Conversion** → ClaifOptions → ClaudeCodeOptions
3. **Session Check** → Load existing session if specified
4. **Cache Lookup** → Check for cached response
5. **SDK Call** → Forward to claude_code_sdk
6. **Tool Approval** → Apply strategy if tools requested
7. **Response Stream** → Yield messages as they arrive
8. **Cache Storage** → Store response if caching enabled
9. **Session Update** → Save messages to session
10. **Output Format** → Display with rich formatting
### Configuration
Environment variables:
- `ANTHROPIC_API_KEY` - Required for Claude API
- `CLAIF_SESSION_DIR` - Custom session directory
- `CLAIF_CACHE_TTL` - Default cache duration
- `CLAIF_DEFAULT_MODEL` - Default Claude model
Config file (`~/.claif/config.json`):
```json
{
"providers": {
"claude": {
"model": "claude-3-opus-20240229",
"api_key_env": "ANTHROPIC_API_KEY",
"cache_ttl": 3600,
"enable_cache": true
}
}
}
```
## Installation with Bun
`claif_cla` includes an installer that uses Bun for fast installation:
```python
# install.py
def install_claude():
"""Install Claude Code CLI using bun."""
# 1. Ensure bun is installed
# 2. Install @anthropic-ai/claude-code globally
# 3. Bundle with bun compile
# 4. Copy to ~/.local/bin
```
Benefits:
- 10x faster than npm
- Creates standalone executables
- No Node.js conflicts
- Cross-platform support
## Why Use claif_cla?
### 1. **Minimal Overhead**
- Thin wrapper adds < 100ms latency
- Direct SDK passthrough
- No unnecessary abstractions
### 2. **Session Persistence**
- Continue conversations across runs
- Export chat history
- Organize with metadata
### 3. **Tool Control**
- Eight approval strategies
- Combine strategies
- Custom implementations
### 4. **Cost Optimization**
- Response caching
- Retry logic
- Request deduplication
### 5. **Developer Experience**
- Type hints everywhere
- Rich CLI output
- Comprehensive logging
- Easy integration
## Contributing
See [CLAUDE.md](CLAUDE.md) for development guidelines.
### Development Setup
```bash
# Clone repository
git clone https://github.com/twardoch/claif_cla.git
cd claif_cla
# Install with dev dependencies
pip install -e ".[dev,test]"
# Run tests
pytest
# Code quality
ruff format src/claif_cla tests
ruff check src/claif_cla tests
mypy src/claif_cla
```
### Testing
```bash
# Unit tests
pytest tests/test_session.py -v
pytest tests/test_approval.py -v
# Integration tests
pytest tests/test_integration.py -v
# Coverage report
pytest --cov=src/claif_cla --cov-report=html
```
## License
MIT License - see [LICENSE](LICENSE) file for details.
Copyright (c) 2025 Adam Twardoch
## Links
### claif_cla Resources
- [GitHub Repository](https://github.com/twardoch/claif_cla) - Source code
- [PyPI Package](https://pypi.org/project/claif_cla/) - Latest release
- [Issue Tracker](https://github.com/twardoch/claif_cla/issues) - Bug reports
- [Discussions](https://github.com/twardoch/claif_cla/discussions) - Q&A
### Related Projects
**Claif Ecosystem:**
- [Claif](https://github.com/twardoch/claif) - Main framework
- [claif_gem](https://github.com/twardoch/claif_gem) - Gemini provider
- [claif_cod](https://github.com/twardoch/claif_cod) - Codex provider
**Upstream Projects:**
- [Claude Code](https://github.com/anthropics/claude-code) - Anthropic's CLI
- [claude-code-sdk](https://github.com/anthropics/claude-code-sdk-python) - Python SDK
- [Anthropic API](https://docs.anthropic.com/) - API documentation
**Tools & Libraries:**
- [Fire](https://github.com/google/python-fire) - CLI framework
- [Rich](https://github.com/Textualize/rich) - Terminal formatting
- [Loguru](https://github.com/Delgan/loguru) - Logging library
- [Bun](https://bun.sh) - Fast JavaScript runtime
Raw data
{
"_id": null,
"home_page": null,
"name": "claif_cla",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "ai, anthropic, artificial-intelligence, claif, claude, cli, command-line, llm, openai, responses-api",
"author": null,
"author_email": "Adam Twardoch <adam+github@twardoch.com>",
"download_url": "https://files.pythonhosted.org/packages/3c/83/0490b981845b2a877a69da09eb6de160abb12240de28cc617fdf99be8414/claif_cla-1.0.30.tar.gz",
"platform": null,
"description": "# claif_cla - Claude Provider for Claif\n\nA Claif provider for Anthropic's Claude with full OpenAI client API compatibility. This package wraps the `claude-code-sdk` to provide a consistent interface following the `client.chat.completions.create()` pattern.\n\n## Features\n\n- **OpenAI Client API Compatible**: Use the familiar `client.chat.completions.create()` pattern\n- **Full Type Safety**: Returns standard `ChatCompletion` and `ChatCompletionChunk` objects\n- **Streaming Support**: Real-time streaming with proper chunk handling\n- **Session Management**: Persistent conversation history with atomic operations\n- **Tool Approval**: Fine-grained control over MCP tool usage\n- **Response Caching**: Intelligent caching to reduce API costs\n- **Fire-based CLI**: Rich terminal interface with multiple output formats\n\n## Quickstart\n\n```bash\n# Install\npip install claif_cla\n\n# Basic usage - OpenAI compatible\npython -c \"\nfrom claif_cla import ClaudeClient\nclient = ClaudeClient()\nresponse = client.chat.completions.create(\n messages=[{'role': 'user', 'content': 'Hello Claude!'}],\n model='claude-3-5-sonnet-20241022'\n)\nprint(response.choices[0].message.content)\n\"\n\n# CLI usage\nclaif-cla query \"Explain quantum computing\"\nclaif-cla chat --model claude-3-opus-20240229\n```\n\n## What is claif_cla?\n\n`claif_cla` is a Python wrapper that integrates Anthropic's Claude into the Claif framework with full OpenAI client API compatibility. It provides a thin layer over the [`claude_code_sdk`](https://github.com/anthropics/claude-code-sdk-python) package, adding session management, tool approval strategies, and response caching while maintaining full compatibility with Claude's capabilities.\n\n**Key Features:**\n- **Session persistence** - Save and restore conversations across sessions\n- **Tool approval strategies** - Fine-grained control over MCP tool usage\n- **Response caching** - Reduce API costs with intelligent caching\n- **Rich CLI** - Beautiful terminal interface with Fire framework\n- **Async support** - Full async/await for efficient operations\n- **Type safety** - Comprehensive type hints throughout\n\n## Installation\n\n### Basic Installation\n\n```bash\n# Core package only\npip install claif_cla\n\n# With Claif framework\npip install claif claif_cla\n```\n\n### Installing Claude CLI\n\nThe Claude CLI can be installed automatically:\n\n```bash\n# Using claif_cla installer\npython -m claif_cla.install\n\n# Or manually via npm\nnpm install -g @anthropic-ai/claude-code\n\n# Or using Claif's installer\npip install claif && claif install claude\n```\n\n### Development Installation\n\n```bash\ngit clone https://github.com/twardoch/claif_cla.git\ncd claif_cla\npip install -e \".[dev,test]\"\n```\n\n## Usage\n\n### Basic Usage (OpenAI-Compatible)\n\n```python\nfrom claif_cla import ClaudeClient\n\n# Initialize the client\nclient = ClaudeClient(\n api_key=\"your-api-key\" # Optional, uses ANTHROPIC_API_KEY env var\n)\n\n# Create a chat completion - exactly like OpenAI\nresponse = client.chat.completions.create(\n model=\"claude-3-5-sonnet-20241022\",\n messages=[\n {\"role\": \"system\", \"content\": \"You are a helpful assistant\"},\n {\"role\": \"user\", \"content\": \"Explain machine learning\"}\n ],\n temperature=0.7,\n max_tokens=1000\n)\n\n# Access the response\nprint(response.choices[0].message.content)\nprint(f\"Model: {response.model}\")\nprint(f\"Usage: {response.usage}\")\n```\n\n### Streaming Responses\n\n```python\nfrom claif_cla import ClaudeClient\n\nclient = ClaudeClient()\n\n# Stream responses in real-time\nstream = client.chat.completions.create(\n model=\"claude-3-5-sonnet-20241022\",\n messages=[\n {\"role\": \"user\", \"content\": \"Write a haiku about programming\"}\n ],\n stream=True\n)\n\n# Process streaming chunks\nfor chunk in stream:\n if chunk.choices[0].delta.content:\n print(chunk.choices[0].delta.content, end=\"\", flush=True)\n```\n\n## CLI Usage\n\n```bash\n# Basic query\nclaif-cla query \"What is the theory of relativity?\"\n\n# With specific model\nclaif-cla query \"Explain Python decorators\" --model claude-3-opus-20240229\n\n# Interactive chat mode\nclaif-cla chat --model claude-3-5-sonnet-20241022\n\n# List available models\nclaif-cla models\n\n# JSON output\nclaif-cla query \"Hello\" --json-output\n```\n\n### Session Management\n\n```bash\n# List all sessions\npython -m claif_cla.cli session list\n\n# Create new session with optional metadata\npython -m claif_cla.cli session create --metadata '{\"project\": \"my-app\"}'\n\n# Show session messages\npython -m claif_cla.cli session show SESSION_ID\n\n# Continue existing session\npython -m claif_cla.cli ask \"Continue our discussion\" --session SESSION_ID\n\n# Export session to file\npython -m claif_cla.cli session export SESSION_ID --format markdown --output chat.md\npython -m claif_cla.cli session export SESSION_ID --format json --output chat.json\n\n# Delete session\npython -m claif_cla.cli session delete SESSION_ID\n```\n\n### Advanced Features\n\n```bash\n# Benchmark response time\npython -m claif_cla.cli benchmark \"Complex analysis task\" --iterations 5\n\n# Set approval strategy for tools\npython -m claif_cla.cli ask \"Analyze this file\" --approval allow_list --allowed-tools \"read_file,search\"\n\n# Use with caching\npython -m claif_cla.cli ask \"Expensive computation\" --cache --cache-ttl 3600\n\n# Verbose mode for debugging\npython -m claif_cla.cli ask \"Debug this\" --verbose\n```\n\n## API Compatibility\n\nThis package is fully compatible with the OpenAI Python client API:\n\n```python\n# You can use it as a drop-in replacement\nfrom claif_cla import ClaudeClient as OpenAI\n\nclient = OpenAI()\n# Now use exactly like the OpenAI client\nresponse = client.chat.completions.create(\n model=\"claude-3-5-sonnet-20241022\",\n messages=[{\"role\": \"user\", \"content\": \"Hello!\"}]\n)\n```\n\n## Migration from Old Async API\n\nIf you were using the old async-based Claif API:\n\n```python\n# Old API (deprecated)\nimport asyncio\nfrom claif_cla import query\nfrom claif.common import ClaifOptions\n\nasync def old_way():\n async for message in query(\"Hello, Claude!\"):\n print(f\"{message.role}: {message.content}\")\n \n# New API (OpenAI-compatible)\nfrom claif_cla import ClaudeClient\n\ndef new_way():\n client = ClaudeClient()\n response = client.chat.completions.create(\n messages=[{\"role\": \"user\", \"content\": \"Hello, Claude!\"}],\n model=\"claude-3-5-sonnet-20241022\"\n )\n print(response.choices[0].message.content)\n```\n\n### Key Changes\n\n1. **Synchronous by default**: No more `async/await` for basic usage\n2. **OpenAI-compatible structure**: `client.chat.completions.create()` pattern\n3. **Standard message format**: `[{\"role\": \"user\", \"content\": \"...\"}]`\n4. **Streaming support**: Use `stream=True` for real-time responses\n5. **Type-safe responses**: Returns `ChatCompletion` objects from OpenAI types\n\n### Session Management\n\n```python\nfrom claif_cla.session import SessionManager, Session\nfrom claif.common import Message, MessageRole\n\n# Initialize session manager\nsession_mgr = SessionManager()\n\n# Create new session\nsession_id = session_mgr.create_session(\n metadata={\"project\": \"my-app\", \"user\": \"john\"}\n)\n\n# Add messages to session\nuser_msg = Message(\n role=MessageRole.USER,\n content=\"What is machine learning?\"\n)\nsession_mgr.add_message(session_id, user_msg)\n\n# Get session history\nsession = session_mgr.get_session(session_id)\nfor msg in session.messages:\n print(f\"{msg.role}: {msg.content}\")\n\n# Export session\nmarkdown_export = session_mgr.export_session(session_id, export_format=\"markdown\")\nprint(markdown_export)\n\n# Save session to disk\nsession_mgr.save_session(session_id)\n```\n\n### Tool Approval Strategies\n\n```python\nfrom claif_cla.approval import create_approval_strategy\n\n# Strategy 1: Allow specific tools only\nsafe_tools = create_approval_strategy(\"allow_list\", {\n \"allowed_tools\": [\"read_file\", \"list_files\", \"search\"]\n})\n\n# Strategy 2: Deny dangerous tools\ndeny_dangerous = create_approval_strategy(\"deny_list\", {\n \"denied_tools\": [\"delete_file\", \"execute_command\", \"write_file\"]\n})\n\n# Strategy 3: Pattern-based approval\npatterns = create_approval_strategy(\"pattern\", {\n \"patterns\": [\"read_.*\", \"list_.*\", \"search_.*\"],\n \"deny\": False # Allow matching patterns\n})\n\n# Strategy 4: Threshold-based (by risk score)\nthreshold = create_approval_strategy(\"threshold\", {\n \"max_risk\": 3 # Only allow tools with risk <= 3\n})\n\n# Use strategy in query\nfrom claif_cla import ClaudeCodeOptions\n\noptions = ClaudeCodeOptions(\n tool_approval_strategy=safe_tools,\n model=\"claude-3-opus-20240229\"\n)\n```\n\n### Response Caching\n\n```python\nfrom claif_cla.wrapper import ClaudeWrapper, ResponseCache\n\n# Create wrapper with caching\nwrapper = ClaudeWrapper(\n cache_ttl=3600, # 1 hour cache\n enable_cache=True\n)\n\n# First call - hits API\nresponse1 = await wrapper.query(\"Expensive analysis\", options)\n\n# Second call - returns from cache\nresponse2 = await wrapper.query(\"Expensive analysis\", options)\n\n# Clear cache if needed\nwrapper.cache.clear()\n```\n\n### Using with Claif Framework\n\n```python\nfrom claif import query as claif_query, Provider, ClaifOptions\n\n# Query through Claif framework\noptions = ClaifOptions(\n provider=Provider.CLAUDE,\n model=\"claude-3-opus-20240229\",\n temperature=0.5\n)\n\nasync for message in claif_query(\"Hello from Claif!\", options):\n print(message.content)\n```\n\n## How It Works\n\n### Architecture Overview\n\n```\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 User Application \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 claif_cla CLI \u2502 \u2190 Fire-based CLI with rich output\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 claif_cla Core \u2502 \u2190 Main query function & types\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Session Manager \u2502 \u2190 Conversation persistence\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Approval Strategies \u2502 \u2190 Tool usage control\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Response Cache \u2502 \u2190 Cost optimization\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 claude_code_sdk \u2502 \u2190 Anthropic's SDK\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n### Core Components\n\n#### Main Module (`__init__.py`)\n\nThe entry point that provides the `query` function:\n\n```python\nasync def query(\n prompt: str,\n options: ClaifOptions | None = None\n) -> AsyncIterator[Message]:\n \"\"\"Query Claude with Claif-compatible interface.\"\"\"\n # Convert Claif options to Claude options\n claude_options = _convert_options(options)\n \n # Delegate to claude_code_sdk\n async for message in claude_query(prompt, claude_options):\n yield message\n```\n\nKey features:\n- Thin wrapper design for minimal overhead\n- Option conversion between Claif and Claude formats\n- Direct message passthrough\n- Loguru-based debug logging\n\n#### CLI Module (`cli.py`)\n\nFire-based command-line interface with rich formatting:\n\n```python\nclass ClaudeCLI:\n def ask(self, prompt: str, **kwargs):\n \"\"\"Ask Claude a question.\"\"\"\n \n def stream(self, prompt: str, **kwargs):\n \"\"\"Stream responses in real-time.\"\"\"\n \n def interactive(self):\n \"\"\"Start interactive chat session.\"\"\"\n \n def session(self, action: str, **kwargs):\n \"\"\"Manage conversation sessions.\"\"\"\n```\n\nCommands:\n- `ask` - Single query with options\n- `stream` - Real-time streaming responses\n- `interactive` - Chat mode with history\n- `session` - CRUD operations for conversations\n- `health` - Check Claude availability\n- `benchmark` - Performance testing\n\n#### Session Module (`session.py`)\n\nPersistent conversation management:\n\n```python\n@dataclass\nclass Session:\n id: str\n messages: list[Message]\n metadata: dict[str, Any]\n created_at: datetime\n updated_at: datetime\n \nclass SessionManager:\n def __init__(self, session_dir: Path | None = None):\n self.session_dir = session_dir or Path.home() / \".claif\" / \"sessions\"\n```\n\nFeatures:\n- JSON-based session storage\n- Atomic file operations\n- Session templates (coding, analysis, creative)\n- Export to Markdown/JSON formats\n- Metadata for organization\n\n#### Approval Module (`approval.py`)\n\nFine-grained control over MCP tool usage:\n\n```python\nclass ApprovalStrategy(ABC):\n @abstractmethod\n def should_approve(self, tool_name: str, tool_metadata: dict) -> bool:\n \"\"\"Decide if tool should be approved.\"\"\"\n\n# Eight concrete strategies:\n1. AllowAllStrategy - Approve everything\n2. DenyAllStrategy - Deny everything \n3. AllowListStrategy - Only allow specific tools\n4. DenyListStrategy - Deny specific tools\n5. PatternStrategy - Regex-based approval\n6. ThresholdStrategy - Risk score based\n7. CategoryStrategy - Approve by category\n8. CompositeStrategy - Combine multiple strategies\n```\n\nFactory function for easy creation:\n```python\nstrategy = create_approval_strategy(\"allow_list\", {\n \"allowed_tools\": [\"read_file\", \"search\"]\n})\n```\n\n#### Wrapper Module (`wrapper.py`)\n\nEnhanced functionality around claude_code_sdk:\n\n```python\nclass ResponseCache:\n \"\"\"SHA256-based response caching.\"\"\"\n def get_cache_key(self, prompt: str, options: dict) -> str:\n data = json.dumps({\"prompt\": prompt, \"options\": options})\n return hashlib.sha256(data.encode()).hexdigest()\n\nclass ClaudeWrapper:\n \"\"\"Adds retry logic and caching.\"\"\"\n async def query_with_retry(self, prompt: str, options, max_retries=3):\n for attempt in range(max_retries):\n try:\n return await self._query(prompt, options)\n except Exception as e:\n if attempt == max_retries - 1:\n raise\n await asyncio.sleep(2 ** attempt)\n```\n\nFeatures:\n- SHA256-based cache keys\n- TTL support for cache entries\n- Exponential backoff retry logic\n- Graceful error handling\n\n### Code Structure\n\n```\nclaif_cla/\n\u251c\u2500\u2500 src/claif_cla/\n\u2502 \u251c\u2500\u2500 __init__.py # Main query function and exports\n\u2502 \u251c\u2500\u2500 cli.py # Fire-based CLI interface\n\u2502 \u251c\u2500\u2500 wrapper.py # Caching and retry logic\n\u2502 \u251c\u2500\u2500 session.py # Session management\n\u2502 \u251c\u2500\u2500 approval.py # Tool approval strategies\n\u2502 \u2514\u2500\u2500 install.py # CLI installation helper\n\u251c\u2500\u2500 tests/\n\u2502 \u251c\u2500\u2500 test_session.py # Session tests\n\u2502 \u251c\u2500\u2500 test_approval.py # Strategy tests\n\u2502 \u2514\u2500\u2500 test_wrapper.py # Cache tests\n\u251c\u2500\u2500 pyproject.toml # Package configuration\n\u251c\u2500\u2500 README.md # This file\n\u2514\u2500\u2500 CLAUDE.md # Development guide\n```\n\n### Message Flow\n\n1. **User Input** \u2192 CLI command or API call\n2. **Option Conversion** \u2192 ClaifOptions \u2192 ClaudeCodeOptions\n3. **Session Check** \u2192 Load existing session if specified\n4. **Cache Lookup** \u2192 Check for cached response\n5. **SDK Call** \u2192 Forward to claude_code_sdk\n6. **Tool Approval** \u2192 Apply strategy if tools requested\n7. **Response Stream** \u2192 Yield messages as they arrive\n8. **Cache Storage** \u2192 Store response if caching enabled\n9. **Session Update** \u2192 Save messages to session\n10. **Output Format** \u2192 Display with rich formatting\n\n### Configuration\n\nEnvironment variables:\n- `ANTHROPIC_API_KEY` - Required for Claude API\n- `CLAIF_SESSION_DIR` - Custom session directory\n- `CLAIF_CACHE_TTL` - Default cache duration\n- `CLAIF_DEFAULT_MODEL` - Default Claude model\n\nConfig file (`~/.claif/config.json`):\n```json\n{\n \"providers\": {\n \"claude\": {\n \"model\": \"claude-3-opus-20240229\",\n \"api_key_env\": \"ANTHROPIC_API_KEY\",\n \"cache_ttl\": 3600,\n \"enable_cache\": true\n }\n }\n}\n```\n\n## Installation with Bun\n\n`claif_cla` includes an installer that uses Bun for fast installation:\n\n```python\n# install.py\ndef install_claude():\n \"\"\"Install Claude Code CLI using bun.\"\"\"\n # 1. Ensure bun is installed\n # 2. Install @anthropic-ai/claude-code globally\n # 3. Bundle with bun compile\n # 4. Copy to ~/.local/bin\n```\n\nBenefits:\n- 10x faster than npm\n- Creates standalone executables\n- No Node.js conflicts\n- Cross-platform support\n\n## Why Use claif_cla?\n\n### 1. **Minimal Overhead**\n- Thin wrapper adds < 100ms latency\n- Direct SDK passthrough\n- No unnecessary abstractions\n\n### 2. **Session Persistence**\n- Continue conversations across runs\n- Export chat history\n- Organize with metadata\n\n### 3. **Tool Control**\n- Eight approval strategies\n- Combine strategies\n- Custom implementations\n\n### 4. **Cost Optimization**\n- Response caching\n- Retry logic\n- Request deduplication\n\n### 5. **Developer Experience**\n- Type hints everywhere\n- Rich CLI output\n- Comprehensive logging\n- Easy integration\n\n## Contributing\n\nSee [CLAUDE.md](CLAUDE.md) for development guidelines.\n\n### Development Setup\n\n```bash\n# Clone repository\ngit clone https://github.com/twardoch/claif_cla.git\ncd claif_cla\n\n# Install with dev dependencies\npip install -e \".[dev,test]\"\n\n# Run tests\npytest\n\n# Code quality\nruff format src/claif_cla tests\nruff check src/claif_cla tests\nmypy src/claif_cla\n```\n\n### Testing\n\n```bash\n# Unit tests\npytest tests/test_session.py -v\npytest tests/test_approval.py -v\n\n# Integration tests\npytest tests/test_integration.py -v\n\n# Coverage report\npytest --cov=src/claif_cla --cov-report=html\n```\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\nCopyright (c) 2025 Adam Twardoch\n\n## Links\n\n### claif_cla Resources\n\n- [GitHub Repository](https://github.com/twardoch/claif_cla) - Source code\n- [PyPI Package](https://pypi.org/project/claif_cla/) - Latest release\n- [Issue Tracker](https://github.com/twardoch/claif_cla/issues) - Bug reports\n- [Discussions](https://github.com/twardoch/claif_cla/discussions) - Q&A\n\n### Related Projects\n\n**Claif Ecosystem:**\n- [Claif](https://github.com/twardoch/claif) - Main framework\n- [claif_gem](https://github.com/twardoch/claif_gem) - Gemini provider\n- [claif_cod](https://github.com/twardoch/claif_cod) - Codex provider\n\n**Upstream Projects:**\n- [Claude Code](https://github.com/anthropics/claude-code) - Anthropic's CLI\n- [claude-code-sdk](https://github.com/anthropics/claude-code-sdk-python) - Python SDK\n- [Anthropic API](https://docs.anthropic.com/) - API documentation\n\n**Tools & Libraries:**\n- [Fire](https://github.com/google/python-fire) - CLI framework\n- [Rich](https://github.com/Textualize/rich) - Terminal formatting\n- [Loguru](https://github.com/Delgan/loguru) - Logging library\n- [Bun](https://bun.sh) - Fast JavaScript runtime",
"bugtrack_url": null,
"license": "MIT",
"summary": "A Claif provider for Anthropic Claude, compatible with the OpenAI Responses API.",
"version": "1.0.30",
"project_urls": {
"Documentation": "https://github.com/twardoch/claif_cla#readme",
"Issues": "https://github.com/twardoch/claif_cla/issues",
"Source": "https://github.com/twardoch/claif_cla"
},
"split_keywords": [
"ai",
" anthropic",
" artificial-intelligence",
" claif",
" claude",
" cli",
" command-line",
" llm",
" openai",
" responses-api"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "924d48d0f1281546b8edc0eb7787774503a49600754634f4618d759fdbffec0b",
"md5": "0f92380f8a6df909412e6453baaeea7b",
"sha256": "9a97425521425a680d46723c85728ef2b73035d23f1b80f56339e0c805b6db84"
},
"downloads": -1,
"filename": "claif_cla-1.0.30-py3-none-any.whl",
"has_sig": false,
"md5_digest": "0f92380f8a6df909412e6453baaeea7b",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 14606,
"upload_time": "2025-07-29T01:49:30",
"upload_time_iso_8601": "2025-07-29T01:49:30.988420Z",
"url": "https://files.pythonhosted.org/packages/92/4d/48d0f1281546b8edc0eb7787774503a49600754634f4618d759fdbffec0b/claif_cla-1.0.30-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "3c830490b981845b2a877a69da09eb6de160abb12240de28cc617fdf99be8414",
"md5": "014e77887fcd5f4a33e708fd842468d2",
"sha256": "22ee2ce0d5f583e8ca939928ac53d2fe0920cfd3eff51bd2ead4deac785c38a1"
},
"downloads": -1,
"filename": "claif_cla-1.0.30.tar.gz",
"has_sig": false,
"md5_digest": "014e77887fcd5f4a33e708fd842468d2",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 53897,
"upload_time": "2025-07-29T01:49:29",
"upload_time_iso_8601": "2025-07-29T01:49:29.387273Z",
"url": "https://files.pythonhosted.org/packages/3c/83/0490b981845b2a877a69da09eb6de160abb12240de28cc617fdf99be8414/claif_cla-1.0.30.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-29 01:49:29",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "twardoch",
"github_project": "claif_cla#readme",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"lcname": "claif_cla"
}