Skip to main content

Local-first, free-first, fallback-built-in LLM router. Claude Code / OpenAI compatible.

Project description

CodeRouter

Claude Code でローカル LLM を使うと tool calling が壊れる問題、
ルーター側で直します。

qwen2.5-coder:7B、phi-4、mistral-nemo など小型・量子化モデルがしばしばやる
{"name":..., "arguments":...} を plain text として吐いてしまう」現象を、
CodeRouter の tool-call 修復パスが Claude Code に届く前に
有効な tool_use ブロックへ復元します。

「ローカル LLM にしたら agentic coding ができない」と諦めていた人へ。
これで本気で使える local-first agent が組めます。

CI status version python deps license

English · 日本語 · 利用ガイド · Security

10 分で動かす → Quickstart詳しく → 利用ガイド無料で回す → 無料枠ガイド要るか判定 → 要否判定

CodeRouter が他に何をやってくれるか

  • coderouter doctor --check-model <provider> でそのモデルが tool call / streaming / thinking に対応しているかを実プローブで即診断し、足りない宣言をコピペ可能な YAML パッチで教えてくれる
  • reasoning leak(<think>...</think> タグや <|turn|> など 6 種の stop マーカー漏れ)を SSE チャンク境界を跨いで自動スクラブ
  • ローカル → 無料クラウド(OpenRouter free / NVIDIA NIM 40 req/min 無料枠)→ 有料 API の自動フォールバック。既定で ALLOW_PAID=false なので課金はオプトイン制
  • ランタイム依存 5 個(fastapi / uvicorn / httpx / pydantic / pyyaml)— 純 Python、MIT、テスト 651 本緑

Claude Code / gemini-cli / codex + Ollama / llama.cpp / NVIDIA NIM で、破綻しない local-first agent が組める

ドキュメント

目的 ドキュメント 内容
動かす Quickstart Claude Code / codex を local Ollama で 10〜15 分で動かす最短手順
使いこなす 利用ガイド HW 別モデル選定・チューニング既定値・OS ごとの起動フロー・doctor / verify の読み方
無料で回す 無料枠ガイド NVIDIA NIM 40 req/min × OpenRouter 無料枠の使い分け・live 検証済みモデル表・地雷 5 点
要るか判断する 要否判定ガイド エージェント × モデルの詳細マトリクスで「そもそも自分に必要か」を決める
詰まったとき トラブルシューティング doctor の使い方、.env の export 必須、Ollama サイレント失敗 5 症状、Claude Code 連携の罠
安全に使う セキュリティ方針 脅威モデル・秘密情報の扱い・脆弱性報告経路
履歴 CHANGELOG 全リリース履歴(最新: v1.6.3 — --env-file + doctor --check-env
設計を追う plan.md 設計不変項・マイルストーン・今後のロードマップ

English versions: Quickstart · Usage guide · Free-tier guide · When you need it · Troubleshooting · Security

CodeRouter で何が楽になるか

CodeRouter は、コーディングエージェント(Claude Code / gemini-cli / codex / 素の OpenAI SDK)と、その裏の LLM の間に挟まる小さなルーターです。ツールの向き先を 1 本のエンドポイントにまとめておけば、CodeRouter がプロバイダを順に選びます — まずローカル Ollama / llama.cpp、次に無料クラウド (OpenRouter free)、有料 API は明示的に opt-in したときだけ。

初心者が普通に使うとぶつかる「地雷」を、CodeRouter がまとめて面倒見てくれます:

  • API キー無し・Anthropic 課金無しのまま Claude Code を回せる。 ローカルモデル(または OpenRouter 無料枠)が答えます。有料プロバイダは ALLOW_PAID=true を明示したときだけ呼ばれます。
  • 返答が途中で消えない。 1 プロバイダが途中で落ちてもクライアントには綺麗な event: error が 1 本届くだけ — 2 モデルを継ぎ接ぎしたフランケン応答にはなりません。
  • うっかり課金しない。 ALLOW_PAID=false が既定。有料プロバイダをチェーンから外したときは理由を 1 行ログに出すので、なぜ使われなかったかが後で grep できます。
  • ローカル Ollama の上で Claude Code / gemini-cli / codex が動く。 Claude Code は Anthropic のワイアフォーマット、Ollama / llama.cpp / LM Studio は OpenAI。CodeRouter が双方向に変換し、小さいローカルモデルがテキストで吐いてしまう {"name":..., "arguments":...} を tool_use ブロックへ復元してからエージェントに渡します。
  • 「なぜか動かない」の原因を教えてくれる。 coderouter doctor --check-model <provider> が 6 種類の典型的な失敗モード(コンテキスト切り詰め / ストリーム早期終了 / ツール呼び出し欠落 / reasoning フィールド漏れ / 認証 / Anthropic thinking)を実地プローブし、コピペ可能な YAML パッチを出します。
  • 監査しやすい。 ランタイム依存 5 個(LiteLLM は 100+)。Pure Python、MIT、テスト 651 本緑。
クライアント (Claude Code / OpenAI SDK / gemini-cli / codex / curl)
        │
        ▼
  CodeRouter  ──►  ① ローカルモデル (Ollama / llama.cpp — 無料・最優先)
                   ② 無料クラウド (OpenRouter qwen3-coder:free, gpt-oss-120b:free, …)
                   ③ 有料クラウド (Claude / GPT — ALLOW_PAID=true のときだけ)

ライブダッシュボード

coderouter dashboard は、障害調査中に実際に知りたい「いま何が起きているか」に、ログを grep せずに即答するための画面です:

  • どのプロバイダが生きていて、いま応答しているのは誰か
  • フォールバックは直近で発火したか、発火したなら何が理由か
  • 有料ゲートは閉じたままか(= まだ無料経路で走っているか)
  • 直近数分のリクエスト流量はどうか
  • ついさっき何が起きたか — 直近 N 件のイベントが時系列で

CodeRouter ダッシュボード — プロバイダ状態 / フォールバック & ゲート / requests/min スパークライン / 直近イベント / usage mix

上のスクリーンショットは scripts/demo_traffic.sh で混合トラフィック(normal / stream / burst / fallback / paid-gate)をローカルのモックに流している最中のものです。左上から: プロバイダ状態、フォールバック & ゲート状態、requests/min スパークライン、直近イベント(新しい順)、usage mix。

CodeRouter は自分に必要か?

CodeRouter は wire 翻訳 + 絆創膏の層です。エージェントが既に OpenAI を喋り、モデルがお行儀良く動くなら、多くの場合不要です。下の 2 つの表が短縮版で、フルの判断ガイドは docs/when-do-i-need-coderouter.md にあります。

エージェント別 — Ollama に直接向けられるか:

エージェント wire Ollama 直続き CodeRouter 必要?
Claude Code Anthropic 必須 — wire 翻訳
Codex CLI / 素の OpenAI SDK OpenAI ◯(OPENAI_BASE_URL オプション
gemini-cli Gemini 必要(アダプタ)
GitHub Copilot CLI GitHub 独自 ✕(バックエンド固定) 無力 — 差し替え不可

モデル別 — 直続きで崩れるか:

モデル 出力綺麗? 効く CodeRouter フィルタ
llama3.1 / mistral-nemo / phi-4 / qwen2.5-coder でない)
qwen2.5-coder ✕ — <think> 漏れ strip_thinking
gpt-oss / deepseek-r1 / qwq ✕ — 推論過程漏れ strip_thinking
小さい量子化(Q2 / Q3)、テンプレ不整合 Modelfile ✕ — tool JSON 壊れ / stop marker 漏れ repair_tool_call / strip_stop_markers

OpenAI 互換エージェント + お行儀の良いモデル + フォールバック不要、の構成なら OPENAI_BASE_URL=http://localhost:11434/v1 の一行で済みます。それ以外 — 特に Claude Code、reasoning 系モデル、mid-stream ガード付きの多段フォールバック — が CodeRouter の仕事どころです。

直接つなげばいいのでは?

  • Ollama / llama.cpp / LM Studio を直接叩く。 確かに速くて無料ですが、Claude Code(および /v1/messages を前提にした多くのエージェント)は Anthropic 形式で話します — 上記サーバは OpenAI 形式だけ。結果、"unsupported endpoint" で弾かれるか、モデルが tool 呼び出しを素のテキストで吐いて tool-use が静かに壊れるかのどちらかです。CodeRouter は双方向に変換し、エージェントに渡る前に JSON を修復します。
  • LiteLLM。 良いプロダクトですが依存が重く(推移的依存 100+)、/v1/messages をネイティブに出しません。
  • OpenRouter 単独。 無料枠はレート制限があり、たまに落ちます。有料オンリーは新規ユーザーや CI には敷居が高い。

設計不変項と今後のロードマップは plan.md を参照。初心者向けに「同じローカルモデルでも、なぜ人によって動く/動かないが分かれるのか」を解説する記事は Zenn / Note で別途公開しています。

クイックスタート(3 コマンド)

# 1. インストール (uv を利用 — 高速・lockfile フレンドリー)
uv sync

# 2. サンプル設定を置く
mkdir -p ~/.coderouter
cp examples/providers.yaml ~/.coderouter/providers.yaml

# 3. 起動
uv run coderouter serve

あとは任意の OpenAI クライアントを http://127.0.0.1:4000 に向けるだけです:

curl http://127.0.0.1:4000/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "ignored",
    "messages": [{"role": "user", "content": "Hello"}]
  }'

model フィールドは現状プレースホルダです — ルーティングは profile フィールド(providers.yamldefault がデフォルト)で決まります。

はじめての方は 利用ガイド を参照してください。ハードウェア別のモデル選定、チューニング既定値、OS ごとの起動フロー、OpenRouter 無料枠とのペア方針を一通り解説しています。(English: usage guide)

NVIDIA NIM 無料枠(40 req/min)と OpenRouter 無料枠をどう重ねるか無料枠ガイド にまとめてあります。live 検証済みのモデル一覧、claude-code-nim プロファイルの設計意図、よくあるハマり所 5 点 込み。(English: free-tier guide)

API キーの管理が気になる方 (1Password / direnv + sops / OS Keychain 連携 + .env の安全運用) は v1.6.3 で coderouter serve --env-filecoderouter doctor --check-env を入れています。詳細は トラブルシューティング §5

OS 対応

CodeRouter 自体は純 Python 3.12+ で、実質的な OS 対応範囲は min(coderouter, ollama, claude-code) です。

OS サーバー ローカル推論 メモ
macOS — Apple Silicon (M1–M5) ✅ Metal ネイティブ 主要開発ターゲット
macOS — Intel ⚠️ CPU のみ 実用はクラウドフォールバックのみ
Linux — x86_64 (Ubuntu / Debian / Fedora) ✅ CUDA または CPU フル対応
Linux — ARM64 (Pi 5 / Graviton) ⚠️ Pi では CPU クラウド中継プロキシとして使える
Windows — WSL2 (Ubuntu) Windows ではこの経路を推奨
Windows — native ⚠️ 一部 ✅ CUDA scripts/verify_*.sh は bash 必須 (Git Bash/WSL2)

注意点や「ローカル GPU なし」向けレシピを含むフル版マトリクス: 利用ガイド §1

ステータス — v1.0 安定版 (2026-04)

テスト 651 本通過。ランタイム依存 5 個。macOS / Linux / Windows WSL2 で動作。 ルーターは日常的な Claude Code 用途で安定しています。v1.0 の総まとめは docs/retrospectives/v1.0.md

今日の CodeRouter が届ける価値:

  • どのクライアントもどのプロバイダに橋渡し。 OpenAI 互換クライアントからのリクエストと Claude Code(/v1/messages 経由)両方を受け入れ、ストリーミング/非ストリーミングを問わず、ローカル Ollama / OpenRouter 無料 / Anthropic / それらの混在にルーティングします。
  • 部分レスポンスを垂れ流さず安全にフォールバック。 最初のバイト前にプロバイダが失敗したら次を試す。最初のバイト以降に失敗したら、クライアントには綺麗な event: error が 1 本届くだけ — 2 つのプロバイダを継ぎ接ぎしたフランケン応答は起きません。
  • 明示的にオプトインしたときだけ課金。 ALLOW_PAID=false(既定)がチェーンから有料プロバイダを外し、ブロック時は 1 行の明確なログを出します。
  • 小さいローカルモデルが壊すものを修復。 Qwen / DeepSeek 系がテキストとして吐いた {"name":..., "arguments":...} は、Claude Code に届く前に有効な tool_use ブロックへ復元されます。
  • 何がおかしいかを教えてくれる。 coderouter doctor --check-model <provider> が 6 プローブ(認証 / コンテキスト切り詰め / ストリーム中断 / ツール呼び出し能力 / reasoning フィールド漏れ / Anthropic thinking 対応)を回し、宣言と実挙動が食い違えばコピペ可能な YAML パッチを出します。
  • reasoning 漏れをスクラブ。 プロバイダに output_filters: [strip_thinking, strip_stop_markers] を付ければ <think>…</think> と 6 種の stop マーカー variants が SSE チャンク境界を跨いでも安定して剥がれます。
  • Anthropic ネイティブ機能は Anthropic に届いたら保持。 cache_control / thinking / anthropic-beta ヘッダでゲートされる body フィールドは kind: anthropic プロバイダでそのまま通り、OpenAI 形状へ落ちる場合のロッシー変換は(沈黙ではなく)ログで可視化されます。

リリース単位の詳細が欲しい? v0.x と v1.0-A/B/C の各スライス — 何が入り、何本のテストが増え、なぜ必要だったのか — は CHANGELOG.md に揃っています。設計の不変項と今後のロードマップは plan.md

次の予定(v1.0 は plan.md §10、v1.0+ は §18): v1.5 ✅ — メトリクス / /dashboard / coderouter stats TUI / scripts/demo_traffic.sh (出荷済み)。v1.6 — CI 向け coderouter doctor --network とランチャースクリプト(当初は v1.1 に予定されていたが、v1.5 が先行出荷されたため v1.6 に繰り下げ)。

Claude Code と一緒に使う

# ターミナル 1: Claude Code 向けにチューニングしたプロファイルで CodeRouter を起動
uv run coderouter serve --port 8088

# ターミナル 2: Claude Code を CodeRouter に向け、ヘッダでチューニング済みプロファイルを選ぶ
ANTHROPIC_BASE_URL=http://localhost:8088 \
ANTHROPIC_AUTH_TOKEN=dummy \
claude

examples/providers.yamlclaude-code プロファイル(7b を先頭、14b を品質フォールバック、14b のタイムアウトを 300s に拡大)を使うには、設定で既定にします:

# ~/.coderouter/providers.yaml
default_profile: claude-code

もしくは起動時に --mode フラグで選択 (v0.6-A):

uv run coderouter serve --port 8088 --mode claude-code
# 同等: CODEROUTER_MODE=claude-code uv run coderouter serve --port 8088

--mode はこのプロセス限定で YAML の default_profile を上書きします。リクエスト単位の上書き (X-CodeRouter-Profile ヘッダ、または body の profile フィールド) は依然勝つので、--mode は「設定ファイルを編集せずに別のチェーンを試したい」ときのつまみです。未知のプロファイル名は初回リクエストではなく起動時 fast-fail です。

examples/providers.yaml 側のプロファイルはこのような形です — そのままコピーし、各 providers: エントリの base_url / model をあなたのローカルスタックに合わせて書き換えてください:

# ANTHROPIC_BASE_URL=http://localhost:8088 claude 用にチューニング。
# Claude Code は毎ターン全ツール (Bash/Glob/Read/Write/...) を宣言するので、
# ルーターは常に v0.3-D の tool-downgrade 経路を使う。ユーザー体感レイテンシ
# ≒ 上流のトータル応答時間。先頭に最速の tool 対応モデル、2 番手に 14b を品質
# フォールバックに、レート制限脱出に無料クラウド 2 種、最後の砦に Claude。
profiles:
  - name: claude-code
    providers:
      - ollama-qwen-coder-7b         # M 系で ~30–60s/ターン、tool 対応
      - ollama-qwen-coder-14b        # 品質フォールバック (timeout_s: 300)
      - openrouter-free              # qwen/qwen3-coder:free (262K コンテキスト)
      - openrouter-gpt-oss-free      # openai/gpt-oss-120b:free (別ベンダー = レート制限脱出)
      - openrouter-claude            # 有料、ALLOW_PAID=true が必要

有料ティアを Anthropic のネイティブ API にしたい場合(Anthropic ingress 経由での cache_control / thinking ブロック生存が目的なら)、openrouter-claudeanthropic-direct に差し替えます — examples/providers.yamlclaude-code-direct プロファイルがまさにそれです。

プロファイル単位のパラメータ上書き (v0.6-B)

プロファイルはチェーン中の全試行に対し 2 つのパラメータを上書き可能で、同じプロバイダ一覧を別プロファイルで違った挙動にしたいとき(例: 長文 /no_think モード vs 短文チャットモード)に便利です:

profiles:
  - name: claude-code-long
    timeout_s: 600             # このプロファイルでは ProviderConfig.timeout_s を置換
    append_system_prompt: ""   # 空文字 = プロバイダ指示を明示的にクリア
    providers:
      - ollama-qwen-coder-14b
      - openrouter-free

セマンティクス: プロファイル値は設定されていればプロバイダ値を置き換えます(append ではない)。timeout_s のようなスカラでの素直な挙動と一致。append_system_prompt: "" はこのプロファイル限定でプロバイダ指示を明示消去します(「未設定」= プロバイダ既定にフォールバック、と区別)。未設定フィールドはプロバイダ既定をそのまま残します。retry_max はアダプタレイヤのリトライが未実装のため後続マイナーに持ち越し — 現状はフォールバックチェーン自体がリトライ機構です。

Mode エイリアス — X-CodeRouter-Mode (v0.6-D)

具体プロファイル名ではなく意図を表現したいクライアントは X-CodeRouter-Mode ヘッダを送れます。CodeRouter は YAML mode_aliases: ブロックで解決します:

# providers.yaml
mode_aliases:
  coding: claude-code          # クライアントが Mode: coding → プロファイル claude-code
  long:   claude-code-long
  fast:   ollama-only
curl http://localhost:8088/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -H 'X-CodeRouter-Mode: coding' \
  -d '{ "messages": [{"role":"user","content":"hi"}] }'

優先度(先着勝ち): body profile > X-CodeRouter-Profile ヘッダ > X-CodeRouter-Mode ヘッダ > default_profile。Mode が Profile より下なのは Profile は実装、Mode は意図 であるため — 呼び出し側が具体プロファイルを指定したときはそのまま尊重します。CodeRouter の前段プロキシが Mode を自動付与する構成でも、呼び出し側の明示 body/ヘッダ profile が勝つ、これが大事な理由です。

ガードレール: 壊れたエイリアス対象は起動時 fast-fail(default_profile バリデーションと同じ哲学)、未知 Mode は宣言済エイリアス一覧付き 400、解決ごとに mode-alias-resolved INFO を出すので運用者はマッピングを後で grep できます。

モデルケイパビリティレジストリ — model-capabilities.yaml (v0.7-A)

「どの Anthropic ファミリが thinking: {type: enabled} を受け付けるか」の知識は、以前は coderouter/routing/capability.py 内の正規表現リテラルでした。v0.7-A からは coderouter/data/model-capabilities.yaml(パッケージ同梱)に移行し、任意で ~/.coderouter/model-capabilities.yaml によるユーザー上書きが可能です。Anthropic が新ファミリを出したら YAML 1 行で追加 — コード変更もリリースサイクルも不要。

# ~/.coderouter/model-capabilities.yaml — 任意のユーザー上書き
version: 1
rules:
  # 仮に Anthropic が新ファミリを出し、CodeRouter の同梱既定更新前に使いたい場合。
  - match: "claude-sonnet-5-*"
    kind: anthropic
    capabilities:
      thinking: true

  # このタグのローカル Ollama では確実にツール呼び出しできるので宣言。
  # v0.7-B doctor の判定と合わせ、将来の glob 消費者からも
  # 方針のある既定として参照されるようにする。
  - match: "qwen3-coder:*"
    kind: openai_compat
    capabilities:
      tools: true

スキーマ: 各ルールは match (provider.model に対する fnmatch glob、大小区別)、任意の kind フィルタ ("anthropic" / "openai_compat" / "any"、既定 "any")、capabilities: マップ(thinking / reasoning_passthrough / tools / max_context_tokens を宣言可能)。ルールは上から順に評価され、各フラグごとに最初に宣言したルールが勝ちます。ルールは 1 つのケイパビリティだけ上書きし、他はフォールスルーさせる使い方も可能。

レイヤ間の優先度は providers.yaml capabilities.*(プロバイダ単位の明示 opt-in)> ユーザー model-capabilities.yaml > 同梱 model-capabilities.yaml > 未設定(False 扱い)。ユーザーは常に上書き権限を失いません — providers.yaml のプロバイダで明示的に capabilities.thinking: true を付ければレジストリに勝つ点は v0.5-A から変わりません。

タイポはロード時に検出: 未知のトップレベルフィールド、未知のフラグ名、不正な kind はいずれも ValidationError を上げてサーバーがトラフィックを受け付ける前に停止します。default_profile / mode_aliases バリデーションと同じ fast-fail 姿勢です。

Doctor — coderouter doctor --check-model <provider> (v0.7-B)

「Ollama を立ててルーターを向けたけど、どうも何かがおかしい」は最多の onboarding 失敗です。v0.7-B の doctor サブコマンドはこれを一行診断に変えます:

coderouter doctor --check-model ollama-qwen-coder-14b

フォールバックチェーン全体ではなく、指定したプロバイダ単体に対し小さな 4 プローブ(各 ≤100 トークン)を走らせ、観測挙動が providers.yaml + model-capabilities.yaml の現宣言と食い違えば判定表とコピペ可能な YAML パッチを出力します:

provider: ollama-qwen-coder-14b  (kind=openai_compat, model=qwen2.5-coder:14b)

probe                     verdict        detail
auth+basic-chat           OK             200 in 1.4s, 18 tokens in / 6 tokens out
tool_calls                NEEDS_TUNING   model emitted a tool_use block but registry says tools=false
thinking                  N/A            kind=openai_compat; thinking probe is anthropic-only
reasoning-leak            OK             no stray `reasoning` field on choice.message

suggested patch for ~/.coderouter/providers.yaml:
  providers:
    - name: ollama-qwen-coder-14b
      capabilities:
        tools: true        # observed: model returned a well-formed tool_use block

4 プローブとその存在意義:

  • auth+basic-chat — 些細な 1 ターン。「API キー未設定」「base_url 違い」「プロバイダ到達不能」のクラスを先に捕まえる。失敗した場合、残り 3 プローブは SKIP となり症状追いで時間(とトークン)を浪費しない。
  • tool_calls — ダミー echo(text: string) ツール仕様と、それを発火させるはずのプロンプトを送る。意図的に非破壊(上流への副作用なし)。モデルが有効な tool_use を吐いたがレジストリが tools: false と言っている(あるいは逆)とき NEEDS_TUNING
  • thinking — Anthropic 限定。thinking: {type: enabled, budget_tokens: 16} をネイティブ送出(OpenAI 形状アダプタをバイパス)し、上流がフィールドを受け付けるか確認。ファミリが model-capabilities.yaml に未登録ならレジストリパッチ(providers.yaml パッチではない)を出す。
  • reasoning-leak — chat ターンを発行し、v0.5-C strip が走るの上流生ボディを検査。「モデルが reasoning を返した」と「アダプタが既に除去済」を区別できる。OpenRouter 無料モデル(openai/gpt-oss-120b:free など)で意味がある。

終了コード(CI 投入想定で設計):

コード 意味
0 全プローブが宣言ケイパビリティと一致、パッチ不要
2 1 つ以上の NEEDS_TUNING、YAML パッチは出力内
1 プローブ実行不能 — auth 失敗、プロバイダ到達不能、または未知プロバイダ名。前提条件を直して再実行

複数シグナル同時発火時の優先度は 1(ブロッカ)> 2(チューニング)> 0(クリーン)。Unix lint 規約(2 = 自動修復可、1 = 諦め)と揃えています。1 プローブの失敗で他が抑制されることはなく、auth 短絡時でもスキップされたプローブは SKIP: upstream auth failed と明記して透明性を維持します。

このサブコマンドはプロバイダ 1 つを対象とする設計です: doctor のプローブが、同ファミリを共有する他プロバイダに波及するレジストリ glob 変更を提案すべきではないからです。チェーン内の各プロバイダについて --check-model を変えて再実行してください。

体感の目安

  • 初バイトレイテンシ: Claude Code は毎ターン全ツール (Bash/Glob/Read/Write/…) を宣言するので、CodeRouter は常に v0.3-D の tool-downgrade 経路(内部非ストリーミング + SSE リプレイ)を使います。体感レイテンシ ≒ 上流のトータル応答時間。
  • M 系 macOS では qwen2.5-coder:7b が ~30–60s/ターン、14b が ~2 分。主因は Claude Code が毎ターン送る 15–20K トークンのシステムプロンプト prefill で、CodeRouter のオーバーヘッドではありません
  • ツール選択の品質はモデル側の限界で、ワイア層の問題ではありません。CodeRouter はワイア(テキスト JSON → tool_use ブロック)を修復しますが、モデルが正しいツールを選んだかは別問題。qwen2.5-coder:14b は Bash が正解の場面で Glob を選ぶことがあり — 対策はより強いローカルモデル、あるいは ALLOW_PAID=true で Claude にフォールスルーさせることです。
  • ミッドストリーム失敗(Ollama が最初のチャンク後に落ちる等)は単発の event: error としてクライアントに届き、リトライはありません — 部分レスポンスは保持され、ストリームはクリーンに閉じます。

予定(v1.0 は plan.md §10、v1.0+ は §18):

  • v1.0 — 14 ケースのリグレッションスイート、Code Mode (スリム版 Claude Code ハーネス); 出力クリーニングは v1.0-Aoutput_filters チェーンとして完了
  • v1.5 — メトリクスダッシュボード(出荷済み)MetricsCollector + GET /metrics.json + GET /metrics (Prometheus) + GET /dashboard (HTML 1 ページ) + coderouter stats curses TUI + scripts/demo_traffic.sh トラフィックジェネレータ + display_timezone 設定
  • v1.6 — coderouter doctor --network (CI 用の明示的ネット許可ラン)、ランチャー(当初 v1.1 に予定されていたが、v1.5 が先行出荷されたため v1.6 に繰り下げ)

kind: openai_compatkind: anthropic の選び方

providers.yaml の各プロバイダに kind があります。2 択です。どちらを選ぶかでホップを超えて生存するワイアレベル機能と、到達可能なクライアントが変わります。

観点 kind: openai_compat kind: anthropic
/v1/chat/completions から到達 ✅ 変換不要 ✅ v0.4-A 逆変換経由
/v1/messages から到達 ✅ 変換 + tool-call 修復経由 ✅ ネイティブパススルー
対象 llama.cpp, Ollama, OpenRouter, LM Studio, Together, Groq, ... api.anthropic.com、Bedrock の Anthropic シム、Messages ワイアを話す任意サーバー
cache_control ブロック ❌ ロスト(OpenAI 側に等価物なし) /v1/messages 経由で end-to-end 保持
thinking ブロック ❌ ロスト /v1/messages 経由で保持
構造化 tool_use SSE イベント 修復から合成 (v0.3-D downgrade) 上流からパススルー
tool-call 修復 (素テキスト JSON → tool_use) ✅ 壊れた JSON を吐くローカルモデル向けに必要 n/a (Anthropic は壊れた JSON を出さない)
anthropic-beta ヘッダ転送 (v0.4-D) n/a ✅ そのまま

判断の目安:

  • ローカルモデルまたは OpenRouter 無料枠kind: openai_compat。逆経路は存在しますが、OpenAI ワイアをネイティブに話すプロバイダに対し変換コストを払う理由はありません。
  • 公式 API 経由の Claude で、cache_control / thinking を効かせたいkind: anthropic/v1/messages 経由(= Claude Code から ANTHROPIC_BASE_URL=http://localhost:8088)。examples/providers.yamlclaude-code-direct プロファイルがこのケース用に事前配線されています。
  • OpenAI クライアントから Claude に到達openai SDK / curl → /v1/chat/completions)→ kind: anthropic は引き続き動きます — 基本 chat / tools / vision は v0.4-A 逆経路で生き残ります。ただし OpenAI に等価形状が無いため cache_control / thinking は送れません。
  • 混在チェーン(ローカル先頭、Claude を有料最終砦に)→ 同プロファイルに両 kind を並べます。エンジンの多態ディスパッチが各境界のホップを扱います。

トラブルシューティング

詳細は独立ドキュメント docs/troubleshooting.md (v1.6.2 で分離) を参照してください。 本節は 30 秒で済む早見表。

まず第一に: 失敗中のプロバイダに対して coderouter doctor --check-model <provider> を走らせてください。6 probe を回し、宣言と観測の不一致があればコピペ YAML パッチを出します。

症状別の入口 (詳細はリンク先):

  • 起動して上流に 401: Header of type authorization was missing§1 起動・設定の罠 (.envexport 必須、coderouter serve --mode <profile> の正しい使い方)
  • ログに provider-failed / capability-degraded / chain-uniform-auth-failure§2 ログの読み方
  • Ollama に向けたら無音 / <think> タグ漏れ / 「ファイルが読めません」 → §3 Ollama 5 症状
  • Claude Code 上で挨拶がツール呼び出しに化ける / UserPromptSubmit hook error§4 Claude Code 連携の罠

ダッシュボード http://localhost:8088/dashboard を別タブで開いておくと、ほとんどの罠が目で見て 10 秒で特定できます。

ミッドストリーム失敗は SSE ストリーム内で単発の event: error / type: api_error として出ます (ヘッダは既送出なので 5xx HTTP ステータスは返らない)。これは「どのプロバイダも開始できなかった」 (type: overloaded_error) とは区別されます。

Ollama 初心者 — サイレント失敗 5 症状

詳細は docs/troubleshooting.md §3 に移動しました。

  • 症状 1: 200 が返るのに返信が空/意味不明 → num_ctx 既定 2048 に切り詰められた
  • 症状 2: 「ファイルが読めません」を繰り返す → 小さなモデルが tools 仕様を扱えていない (tools: false 宣言)
  • 症状 3: <think>...</think> が漏れる → output_filters: [strip_thinking]
  • 症状 4: 初回リクエストが毎回失敗 → ollama pull <tag> 忘れ / model: タイポ
  • 症状 5: 全プロバイダが一様に失敗 → クラウド API キー未 export (§1-2 / §1-3)

各症状の coderouter doctor 出力例とコピペ可能 YAML パッチは docs/troubleshooting.md に。HF-on-Ollama 構成 / lunacode との関係も同じドキュメントに集約。

依存ポリシー

厳密 — plan.md §5.4 参照。ランタイム依存:

パッケージ 目的
fastapi HTTP ingress
uvicorn ASGI サーバー
httpx アウトバウンド HTTP(あえて Anthropic/OpenAI SDK を使わない)
pydantic スキーマ検証
pyyaml 設定パース

以上。litellm なし、langchain なし、openai/anthropic SDK なし。

プログラムから例外をキャッチする (v1.0.1)

CodeRouter を組み込んで使う場合 (engine を直接呼ぶ / coderouter serve を harness でラップする等)、CodeRouter が内部で raise する全例外は CodeRouterError を継承しています。1 つの except で全部拾えます:

from coderouter import CodeRouterError

try:
    response = await engine.generate(chat_request)
except CodeRouterError as exc:
    # AdapterError / NoProvidersAvailableError / MidStreamError の全てに該当
    logger.error("coderouter-failed", extra={"reason": str(exc)})

leaf 例外は従来の場所 (AdapterErrorcoderouter.adapters.baseNoProvidersAvailableErrorMidStreamErrorcoderouter.routing.fallback) に残っているので、既存の except AdapterError: のような catch はそのまま動きます。root class は downstream が leaf を個別 import して enumerate しなくて済むよう public API surface を固定するためだけに存在し、今後 leaf が増えても呼び出し側のコードを触る必要がありません。

Security

シークレットは設定ファイルではなく環境変数に置きます。CI はシークレット スキャン (gitleaks)、多重ソースの依存 CVE 監査 (pip-audit + OSV-Scanner)、lockfile 固定インストールを強制します — docs/security.md に完全な方針と 報告手順があります。

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

coderouter_cli-1.7.0.tar.gz (668.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

coderouter_cli-1.7.0-py3-none-any.whl (161.5 kB view details)

Uploaded Python 3

File details

Details for the file coderouter_cli-1.7.0.tar.gz.

File metadata

  • Download URL: coderouter_cli-1.7.0.tar.gz
  • Upload date:
  • Size: 668.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.6.14

File hashes

Hashes for coderouter_cli-1.7.0.tar.gz
Algorithm Hash digest
SHA256 faa2faedace6e034f3ab00a9fc88bac085a67e654cfab66012aa960ea5eec63d
MD5 b17060119c6a3bdee6774e231d0d3687
BLAKE2b-256 eaaabf6fa3ff317a6f21bf816a278b55b4a54620c7c145f5d7897128e0449646

See more details on using hashes here.

File details

Details for the file coderouter_cli-1.7.0-py3-none-any.whl.

File metadata

File hashes

Hashes for coderouter_cli-1.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7ce0de15119e7c5219ac0413cde710ccc7be8be51225bbf59d6963f0a90f4541
MD5 c060ed970ff326d8de23d5b5ea967024
BLAKE2b-256 aa281ece11366512430d171e1e21ea5f665128e1090c480186fccbf93c412cb4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page