Documentation
¶
Overview ¶
Package cli holds the application struct that service.MainCmd parses CLI args into, plus the Run entry-point that delegates to the injected server factory. The factory itself lives in pkg/factory; this package is import-free of factory to keep the dependency direction (main -> factory -> ...) intact.
Package config loads and validates the claude-code-router YAML configuration. The config describes:
- listed providers (each: upstream URL, optional token, list of model-name glob patterns)
- which provider to route to when no glob matches (default_provider)
Routing is per-request: the model-router inspects the JSON body's `model` field and forwards to the matching provider's reverse proxy.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func FindConfigDir ¶ added in v0.19.0
FindConfigDir returns the config directory for toolName using XDG conventions with legacy dotfile fallback. Priority:
- ~/.config/<toolName>/ if it exists
- ~/.<toolName>/ if it exists
- ~/.config/<toolName>/ (XDG default when neither exists — new installs land in the XDG location from the start)
Deliberately does NOT use os.UserConfigDir() — on macOS that resolves to ~/Library/Application Support, which is not this project's XDG convention (~/.config/<tool>/ on every platform, matching task-watcher and vault-ui).
Types ¶
type App ¶
type App struct {
Listen string `arg:"listen" default:"127.0.0.1:8788" env:"LISTEN" required:"true" usage:"address to listen to"`
ConfigPath string `` /* 267-byte string literal not displayed */
// contains filtered or unexported fields
}
App is the application wired by main and parsed by service.MainCmd's argument tagger. Exported fields with tags are CLI args; unexported fields are dependencies injected by main.
func NewApp ¶
func NewApp(serverFactory ServerFactory) *App
NewApp constructs the App with the server factory injected.
type AuthConfig ¶ added in v0.21.0
type AuthConfig struct {
// Key is the shared secret a non-loopback caller must present in the
// x-router-key header. Empty means authentication is disabled. A
// whitespace-only or accidentally-quoted value is treated as a literal
// key, never rejected at load time — the symptom is a 401 at request
// time, not a start-up failure.
Key string `yaml:"key"`
}
AuthConfig holds the shared key that gates non-loopback /v1/* requests. It is a pointer on Config so that an absent `auth:` block loads as nil, distinct from an explicitly empty key — both mean disabled.
func (*AuthConfig) IsEnabled ¶ added in v0.21.0
func (a *AuthConfig) IsEnabled() bool
IsEnabled reports whether inbound authentication is active: true iff the receiver is non-nil and Key is non-empty. Nil and empty string both mean disabled. This is the single check the auth middleware uses.
type Config ¶
type Config struct {
Router Router `yaml:"router"`
Providers map[string]Provider `yaml:"providers"`
// Aliases maps a short operator-typed model name to the full
// model string the upstream expects. Resolved single-hop before
// glob-routing: a request body `{"model":"qwen"}` becomes
// `{"model":"qwen3.6:35b-a3b-coding-nvfp4"}` before the router
// walks providers' models globs. Nil / empty map = no-op.
Aliases map[string]string `yaml:"aliases,omitempty"`
// Trace, when true, enables per-request trace logging for /v1/*
// requests: every request writes one JSON file capturing the full
// request and response to ~/.claude-code-router/trace/. When false
// (or absent), no trace files are written and no trace middleware
// is allocated on the request hot path. Read once at Load; a
// restart applies it.
Trace bool `yaml:"trace,omitempty"`
// Auth, when enabled, requires every non-loopback /v1/* request to
// present the shared key in the x-router-key header. Absent, null,
// and an empty key all mean authentication is disabled and the
// router behaves exactly as it does today.
Auth *AuthConfig `yaml:"auth,omitempty"`
}
Config is the parsed YAML root.
type Provider ¶
type Provider struct {
// Upstream is the base URL, e.g. https://api.anthropic.com.
Upstream string `yaml:"upstream"`
// Token, if set, replaces the client's Authorization header with
// "Bearer <Token>". If empty, the client's Authorization is
// forwarded verbatim — used for the subscription-OAuth case.
Token string `yaml:"token,omitempty"`
// Models is the list of glob patterns (filepath.Match syntax) the
// router uses to match request body's `model` field. Examples:
// "claude-opus-*", "MiniMax-*", "qwen*".
Models []string `yaml:"models"`
// RequiresLeadingSystem lists glob patterns (same syntax as
// Models) naming models behind this provider whose chat template
// rejects a system-role message that is not the first entry of
// the conversation. When the resolved model name matches one of
// these patterns, the router lifts every out-of-place system
// message into the top-level system block before forwarding.
//
// Scoped per model, never per provider: ollama's system-position
// restriction lives in each model's chat template, so qwen3.6 and
// qwen3.8 behave differently behind one provider (verified
// 2026-08-15 with identical curl payloads against the same ollama
// instance: qwen3.6 -> 200, qwen3.8 -> 500).
//
// Absent, nil, and empty are equivalent and all mean "never
// transform anything for this provider".
RequiresLeadingSystem []string `yaml:"requiresLeadingSystem,omitempty"`
}
Provider describes one upstream LLM API.