pkg

package
v0.30.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 17, 2026 License: BSD-2-Clause Imports: 10 Imported by: 0

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

func FindConfigDir(toolName string) string

FindConfigDir returns the config directory for toolName using XDG conventions with legacy dotfile fallback. Priority:

  1. ~/.config/<toolName>/ if it exists
  2. ~/.<toolName>/ if it exists
  3. ~/.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.

func (*App) Run

func (a *App) Run(ctx context.Context) error

Run is invoked by service.MainCmd after argument parsing.

type AuthConfig added in v0.21.0

type AuthConfig struct {
	// Key is the legacy shared secret field. Kept solely so a legacy `auth:`
	// block still parses and is rejected at load; a non-nil AuthConfig makes
	// Config.Validate fail the config (fail-closed migration guard).
	Key string `yaml:"key"`
}

AuthConfig parses the legacy spec-009 `auth:` block shape. It is a pointer on Config and exists only so yaml.Unmarshal can recognise a legacy block and trip the Config.Validate rejection — the parsed Key is never read for authentication.

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 is the legacy spec-009 auth block. It is retained ONLY as a
	// load-failing detection probe: yaml.Unmarshal populates it from a
	// legacy `auth:` block, and Config.Validate rejects any non-nil value so
	// a config still carrying the removed auth path fails closed instead of
	// silently degrading to unauthenticated. Configure allowedApiKeys
	// instead. Absent and null both leave it nil and pass validation.
	Auth *AuthConfig `yaml:"auth,omitempty"`
	// AllowedApiKeys is the top-level registry of API keys that authenticate
	// non-loopback /v1/* requests. It is also the single rotation point: a
	// key that appears here (or in any provider's list) authenticates the
	// caller, and a per-provider claim pins routing. Absent, null, and empty
	// are equivalent and all mean: no key enforcement and no key routing —
	// the /v1/* path behaves exactly as it does today. Keys are literal
	// strings, like provider token: fields.
	AllowedApiKeys []string `yaml:"allowedApiKeys,omitempty"`
}

Config is the parsed YAML root.

func Load

func Load(ctx context.Context, rawPath string) (*Config, error)

Load reads, parses, and validates the config at path. Tilde-prefix (~/) is expanded to the user's home directory.

func (*Config) AllowedApiKeySet added in v0.27.0

func (c *Config) AllowedApiKeySet() map[string]struct{}

AllowedApiKeySet returns the set of keys that authenticate non-loopback /v1/* requests: the top-level registry when non-empty, else the union of every provider's allowedApiKeys. The empty set means auth is disabled and no key routing applies. This is the single definition the auth middleware (prompt 2) and the key router (prompt 3) consume — do not recompute the union elsewhere.

func (*Config) Validate

func (c *Config) Validate(ctx context.Context) error

Validate checks that the parsed config is internally consistent.

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"`
	// AllowedApiKeys is this provider's routing pin: a request whose
	// presented x-api-key is in this list is dispatched to this provider
	// (its outbound token), overriding model-glob selection. A key may
	// appear in both the top-level registry and a provider's list — the
	// registry is the auth superset, the provider claim is the routing pin.
	// A key must NOT be claimed by more than one provider (validation
	// error, see Config.Validate). Absent, null, and empty all mean: this
	// provider claims no keys, so it is only reachable via glob routing.
	AllowedApiKeys []string `yaml:"allowedApiKeys,omitempty"`
}

Provider describes one upstream LLM API.

type Router

type Router struct {
	// DefaultProvider is the provider key used when no model glob matches.
	// Must reference a key in Providers; validated on Load.
	DefaultProvider string `yaml:"default_provider"`
}

Router holds router-wide settings.

type ServerFactory

type ServerFactory func(ctx context.Context, listen, configPath string) (librun.Func, error)

ServerFactory is the dep cli requires to start the HTTP listener. Satisfied by factory.CreateServer. Returns the run.Func + any startup error (config load, validation, etc.).

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL