MCPcopy Index your code
hub / github.com/arttttt/AnyClaude

github.com/arttttt/AnyClaude @v0.5.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.5.0 ↗ · + Follow
1,442 symbols 5,014 edges 157 files 331 documented · 23% updated 36d agov0.5.0 · 2026-03-13★ 49
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

AnyClaude

TUI wrapper for Claude Code with hot-swappable backend support and transparent API proxying.

Goal: Make switching between API providers effortless. Configure all your backends once, then switch between them with a single hotkey — no config edits, no restarts, no interruptions.

Note: Only Anthropic API-compatible backends are supported.

Why?

Claude Code is great, but sometimes you need a different provider — maybe Anthropic is down, rate-limited, or you want to use another Anthropic-compatible backend. Without AnyClaude, switching means editing config files or environment variables every time.

AnyClaude solves this:

  • Configure all backends once
  • Switch with Ctrl+B mid-session
  • No restarts, no config edits

Features

  • Hot-Swap Backends — Switch between providers without restarting Claude
  • Agent Teams — Route teammate agents to a separate backend (experimental)
  • Thinking Block Filtering — Automatic filtering of previous backend's thinking blocks on switch
  • Adaptive Thinking Conversion — Convert adaptive thinking to enabled format for non-Anthropic backends (thinking_compat)
  • Model Mapping — Remap model names per backend (model_opus, model_sonnet, model_haiku)
  • Transparent Proxy — Routes API requests through active backend
  • Backend History — View switch history with Ctrl+H
  • Debug Logging — Request/response logging with configurable detail levels

Architecture

┌─────────────────────────────┐
│        AnyClaude TUI        │
└──────────────┬──────────────┘
               │
        ┌──────▼──────┐
        │ Claude Code │ (main agent + teammate agents)
        └──────┬──────┘
               │ ANTHROPIC_BASE_URL
        ┌──────▼──────┐
        │ Local Proxy │
        └──┬───────┬──┘
           │       │
      /v1/*│       │/teammate/v1/*
           │       │
     ┌─────▼──┐  ┌─▼──────────┐
     │ Active │  │  Teammate   │
     │Backend │  │  Backend    │
     └────────┘  └─────────────┘

The main agent's requests go through the active backend (switchable via Ctrl+B). Teammate agents are routed to a fixed backend via the /teammate path prefix.

Installation

cargo install --path .

Or build manually:

cargo build --release
# binary at ./target/release/anyclaude

Usage

anyclaude

Override default backend at startup:

anyclaude --backend kimi

Pass arguments through to Claude Code:

anyclaude -- --model claude-sonnet-4-5-20250929

The wrapper automatically: 1. Starts a local proxy (port auto-assigned starting from configured bind_addr) 2. Sets ANTHROPIC_BASE_URL environment variable 3. Spawns Claude Code in an embedded terminal 4. Routes all API requests through the active backend

Hotkeys

Key Action
Ctrl+B Backend switcher popup
Ctrl+S Status/metrics popup
Ctrl+H Backend switch history
Ctrl+E Settings dialog
Ctrl+Q Quit
1-9 Quick-select backend (in switcher)

Configuration

Config location: ~/.config/anyclaude/config.toml

Minimal Example

[defaults]
active = "anthropic"

[[backends]]
name = "anthropic"
display_name = "Anthropic"
base_url = "https://api.anthropic.com"
auth_type = "passthrough"  # Forward Claude Code's auth headers

[[backends]]
name = "alternative"
display_name = "Alternative Provider"
base_url = "https://your-provider.com/api"
auth_type = "bearer"
api_key = "your-api-key"

Full Example

[defaults]
active = "anthropic"              # Default backend at startup
timeout_seconds = 300             # Overall request timeout
connect_timeout_seconds = 5       # TCP connection timeout
idle_timeout_seconds = 60         # Streaming response idle timeout
pool_idle_timeout_seconds = 90    # Connection pool idle timeout
pool_max_idle_per_host = 8        # Max idle connections per host
max_retries = 3                   # Connection retry attempts
retry_backoff_base_ms = 100       # Base backoff for retries (exponential)

[proxy]
bind_addr = "127.0.0.1:8080"      # Local proxy listen address (auto-increments if busy)
base_url = "http://127.0.0.1:8080" # Base URL exposed to Claude Code

[terminal]
scrollback_lines = 10000          # History buffer size

[debug_logging]
level = "verbose"                 # "off", "basic", "verbose", "full"
format = "console"                # "console", "json"
destination = "file"              # "stderr", "file", "both"
file_path = "~/.config/anyclaude/debug.log"
body_preview_bytes = 1024         # Max bytes of request/response body to log
header_preview = true             # Log request/response headers
full_body = false                 # Log full bodies (no size limit)
pretty_print = true               # Pretty-print JSON bodies

[debug_logging.rotation]
mode = "none"                     # "none", "size", "daily"
max_bytes = 10485760              # Max log file size before rotation (10 MB)
max_files = 5                     # Max rotated log files to keep

[[backends]]
name = "anthropic"
display_name = "Anthropic"
base_url = "https://api.anthropic.com"
auth_type = "passthrough"         # Forward Claude Code's auth headers

[[backends]]
name = "alternative"
display_name = "Alternative Provider"
base_url = "https://your-provider.com/api"
auth_type = "bearer"
api_key = "your-api-key"
thinking_compat = true            # Convert adaptive->enabled thinking for this backend
thinking_budget_tokens = 10000    # Budget for conversion (default: 10000)
model_opus = "custom-opus-model"  # Remap opus-family model requests
model_sonnet = "custom-sonnet"    # Remap sonnet-family model requests
model_haiku = "custom-haiku"      # Remap haiku-family model requests

[[backends]]
name = "custom"
display_name = "Custom Provider"
base_url = "https://my-proxy.example.com"
auth_type = "passthrough"         # Forward original auth headers

[backends.pricing]
input_per_million = 3.00          # Cost per million input tokens
output_per_million = 15.00        # Cost per million output tokens

# Route teammate agents to a different backend (experimental)
[agent_teams]
teammate_backend = "alternative"  # Must match a [[backends]] name

Authentication Types

Type Header Use Case
api_key x-api-key: <value> Anthropic API
bearer Authorization: Bearer <value> Most providers
passthrough Forwards original headers OAuth flows, custom auth

Model Mapping

Backends can remap Anthropic model names to provider-specific ones. The proxy matches the request model against family keywords (opus, sonnet, haiku) and substitutes the configured name.

[[backends]]
name = "my-provider"
base_url = "https://api.example.com"
auth_type = "bearer"
api_key = "key"
model_opus = "provider-large"     # claude-opus-4-6 -> provider-large
model_sonnet = "provider-medium"  # claude-sonnet-4-5 -> provider-medium
model_haiku = "provider-small"    # claude-haiku-4-5 -> provider-small

Only configured families are remapped. Omitted families pass through unchanged.

Responses are automatically reverse-mapped: if the backend returns its own model name (e.g. provider-large), the proxy rewrites it back to the original name (e.g. claude-opus-4-6) so Claude Code sees a consistent model identity.

Agent Teams (Experimental)

Route Claude Code's teammate agents to a separate backend. Useful when you want the main agent on one provider and teammates on a cheaper/different one.

Requires Claude Code's experimental agent teams feature. Enable it via Ctrl+E > Settings in the TUI.

[agent_teams]
teammate_backend = "alternative"  # Backend name for teammate requests

How it works: - The main agent's requests go to the active backend (switchable via Ctrl+B) - Teammate agents are intercepted via PATH shims and routed through /teammate/* to the fixed teammate_backend - Thinking block filtering is not applied to teammate requests - Backend switching does not affect teammate routing

Thinking Block Handling

AnyClaude handles two separate problems with thinking blocks when proxying through multiple backends.

1. Thinking block filtering (always active)

Each provider's thinking blocks contain cryptographic signatures tied to that provider. When you switch backends mid-session, the conversation history includes thinking blocks from the previous provider. The new provider rejects these as invalid, causing 400 errors.

AnyClaude tracks all thinking blocks by content hash and automatically filters out blocks from previous sessions on backend switch. This works unconditionally for all backends — no configuration needed.

2. Adaptive thinking conversion (thinking_compat)

Claude Code uses adaptive thinking"thinking": {"type": "adaptive"}, where the model decides when and how much to think. The native Anthropic API supports this, but non-Anthropic backends don't. They require the explicit format: "thinking": {"type": "enabled", "budget_tokens": N}.

Set thinking_compat = true on non-Anthropic backends to enable conversion:

  • Request body: adaptive -> enabled with a configurable token budget
  • Header: anthropic-beta: adaptive-thinking-* -> interleaved-thinking-2025-05-14
[[backends]]
name = "alternative"
base_url = "https://your-provider.com/api"
auth_type = "bearer"
api_key = "your-api-key"
thinking_compat = true            # Convert adaptive->enabled thinking
thinking_budget_tokens = 10000    # Budget for conversion (default: 10000)
Setting Default Description
thinking_compat false Convert adaptive thinking to explicit enabled format
thinking_budget_tokens 10000 Token budget for conversion. If the request has max_tokens, uses max_tokens - 1 instead

Note: Anthropic's own API handles adaptive thinking natively — only enable thinking_compat for third-party backends.

Debug Logging

Enable detailed request/response logging for debugging:

[debug_logging]
level = "verbose"                  # "off" | "basic" | "verbose" | "full"
destination = "file"               # "stderr" | "file" | "both"
file_path = "~/.config/anyclaude/debug.log"
format = "console"                 # "console" | "json"
pretty_print = true                # Pretty-print JSON bodies
full_body = false                  # Log complete bodies (no size limit)
body_preview_bytes = 1024          # Truncate preview if full_body = false
header_preview = true              # Include headers in logs

[debug_logging.rotation]
mode = "size"                      # "none" | "size" | "daily"
max_bytes = 10485760               # 10MB
max_files = 5                      # Keep 5 rotated files
Level Content
off Disabled (default)
basic Request timestamps, status codes, latency
verbose + Token counts, model info, cost estimates
full + Request/response body previews, headers

Development

./build.sh              # Build release binary
./build.sh debug        # Build debug binary
./build.sh test         # Run tests
./build.sh clean        # Clean build artifacts
./build.sh install      # Build and install to ~/.cargo/bin
./build.sh release-tag  # Build release without dev version stamp

License

Apache 2.0

Extension points exported contracts — how you extend this code

Core symbols most depended-on inside this repo

Shape

Function 773
Method 485
Class 134
Enum 45
Interface 5

Languages

Rust100%

Modules by API surface

src/ui/app.rs92 symbols
crates/term_input/src/parser.rs49 symbols
tests/thinking_registry.rs45 symbols
tests/pipeline_stages.rs40 symbols
tests/args_pipeline.rs40 symbols
tests/subagent_session_affinity.rs37 symbols
tests/reverse_model_mapping.rs37 symbols
tests/sse.rs35 symbols
src/metrics/debug_logger.rs33 symbols
tests/thinking_session.rs30 symbols
src/config/types.rs30 symbols
src/error.rs29 symbols

For agents

$ claude mcp add AnyClaude \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page