llm-mux
Multiplexer for LLMs. Route prompts to multiple backends, run them in parallel, and orchestrate multi-step workflows.
Quick Start
1. Install
# From crates.io
# Or from source
2. Configure Backends
Create ~/.config/llm-mux/config.toml:
# CLI backends (any command that accepts a prompt)
[]
= "claude"
= ["-p"]
[]
= "codex"
= ["exec", "-q"]
[]
= "ollama"
= ["run", "llama3"]
# HTTP backends (OpenAI-compatible APIs)
[]
= "https://api.openai.com/v1"
= "gpt-4"
= "${OPENAI_API_KEY}" # from environment
[]
= "http://localhost:11434/v1"
= "llama3"
3. Define Roles
Roles map task types to backends:
[]
= "Code analysis tasks"
= ["claude", "codex"]
= "parallel" # first | parallel | fallback
[]
= "Fast responses"
= ["ollama"]
= "first"
4. Create a Workflow
Create .llm-mux/workflows/review.toml in your project:
= "review"
= "Review code changes"
[[]]
= "diff"
= "shell"
= "git diff HEAD~1"
[[]]
= "analyze"
= "query"
= "analyzer"
= """
Review these changes for bugs and improvements:
{{ steps.diff.output }}
"""
= ["diff"]
5. Run It
Configuration
Config Locations
~/.config/llm-mux/config.toml(user defaults).llm-mux/config.toml(project overrides)
Later files override earlier ones.
Backend Options
[]
= "claude" # CLI command or HTTP URL
= ["-p"] # arguments for CLI backends
= "gpt-4" # model name for HTTP backends
= "${ENV_VAR}" # API key (supports env vars)
= true # enable/disable
= 300 # seconds
= 3 # retry attempts
= 1000 # base delay in ms (exponential backoff)
= true # auto-retry on rate limits
= false # auto-retry on timeouts
Role Execution Modes
first: Use first available backend (default)parallel: Run all backends, collect resultsfallback: Try each backend until one succeeds
Teams
Auto-detect project type and apply team-specific settings:
[]
= "Rust projects"
= ["Cargo.toml"]
= "cargo clippy && cargo test"
[]
= ["claude", "codex"] # override for Rust projects
Ecosystems
Track relationships between projects and store ecosystem knowledge:
[]
= "MyApp web application and services"
= [
"API uses JWT tokens with 1 hour expiration",
"Database migrations run automatically on deploy",
"Redis cache invalidation happens via pub/sub"
]
[]
= "~/projects/myapp-frontend"
= "javascript"
= ["api"]
= ["production", "web"]
[]
= "REST API backend"
= "~/projects/myapp-api"
= "rust"
= ["database"]
= ["production", "backend"]
[]
= "PostgreSQL database with migrations"
= "~/projects/myapp-db"
= "sql"
= ["infrastructure", "database"]
[]
= "Background job processor"
= "~/projects/myapp-worker"
= "rust"
= ["database", "api"]
= ["production", "background"]
Workflows automatically detect which ecosystem you're in and can access:
{{ ecosystem.name }} - Ecosystem name
{{ ecosystem.description }} - Description
{{ ecosystem.knowledge }} - Array of facts
{{ ecosystem.projects }} - All projects
{{ ecosystem.current_project.name }} - Current project name
{{ ecosystem.current_project.type }} - Project type
{{ ecosystem.current_project.depends_on }} - Dependencies
{{ ecosystem.current_project.tags }} - Project tags
Workflows
Step Types
# Shell: run a command
[[]]
= "fetch"
= "shell"
= "gh issue view {{ args.issue }}"
# Query: call LLM backend(s)
[[]]
= "analyze"
= "query"
= "analyzer"
= "Analyze: {{ steps.fetch.output }}"
= ["fetch"]
# Apply: apply edits from LLM output
[[]]
= "fix"
= "apply"
= "steps.analyze"
= "cargo test"
= 2
= true
= ["analyze"]
# Store: persist data to SQLite memory database
[[]]
= "save_facts"
= "store"
= "{{ steps.analyze.output }}"
= ["analyze"]
Template Variables
{{ args.name }}: workflow arguments{{ steps.name.output }}: previous step output{{ env.VAR }}: environment variables{{ team }}: detected team name{{ ecosystem.name }}: detected ecosystem{{ ecosystem.knowledge }}: ecosystem facts{{ ecosystem.current_project }}: current project info
Filters
{{ value | shell_escape }} # escape for shell
{{ value | json }} # JSON encode
{{ list | join(", ") }} # join array
{{ text | lines }} # split into lines
{{ text | trim }} # trim whitespace
{{ value | default("x") }} # default if empty
Conditionals
[[]]
= "rust-only"
= "shell"
= "cargo clippy"
= "team == 'rust'"
Iteration
[[]]
= "check-files"
= "shell"
= "wc -l {{ item }}"
= "steps.list.output | lines"
Store Steps and Ecosystem Memory
Store steps persist LLM analysis results to a SQLite database for later querying.
Database Location:
~/.config/llm-mux/memory/<ecosystem-name>.db
Data Format: Store steps parse JSON from previous steps and save to the memory database.
Facts require:
Relationships require:
Usage:
[[]]
= "analyze"
= "query"
= "analyzer"
= """
Analyze the codebase and return facts.
IMPORTANT: Return JSON with this exact structure:
{
"facts": [
{"project": "myapp", "fact": "Uses PostgreSQL", "source": "config.yml", "confidence": 1.0}
]
}
"""
[[]]
= "store"
= "store"
= "{{ steps.analyze.output }}"
= ["analyze"]
See examples/workflows/discover-ecosystem.toml for a complete example.
CLI Reference
llm-mux run <workflow> [args...] Run a workflow
llm-mux validate <workflow> Validate workflow syntax
llm-mux doctor Check backend availability
llm-mux backends List configured backends
llm-mux teams List configured teams
llm-mux roles List configured roles
llm-mux ecosystems List configured ecosystems
Options:
--team <name> Override team detection
--output <mode> Output format: console, json, quiet
--debug Enable debug output
--quiet Suppress progress output
Examples
Simple Review
# .llm-mux/workflows/review.toml
= "review"
[[]]
= "diff"
= "shell"
= "git diff"
[[]]
= "review"
= "query"
= "analyzer"
= "Review this diff:\n{{ steps.diff.output }}"
= ["diff"]
Parallel Analysis
= "analyze"
[]
= ["claude", "codex", "gemini"]
= "parallel"
[[]]
= "analyze"
= "query"
= "multi"
= "Find bugs in: {{ args.file }}"
Fix with Verification
= "fix"
[[]]
= "identify"
= "query"
= "analyzer"
= "Find the bug in {{ args.file }}"
[[]]
= "fix"
= "query"
= "coder"
= """
Fix this bug: {{ steps.identify.output }}
Return edits as JSON: {"path": "...", "old": "...", "new": "..."}
"""
= ["identify"]
[[]]
= "apply"
= "apply"
= "steps.fix"
= "cargo test"
= 2
= ["fix"]
Ecosystem-Aware Bug Hunt
= "bug-hunt"
= "Search for bugs across ecosystem"
[[]]
= "analyze"
= "query"
= "analyzer"
= """
Search for potential bugs in {{ ecosystem.current_project.name }}.
Project type: {{ ecosystem.current_project.type }}
Known ecosystem facts:
{% for fact in ecosystem.knowledge %}
- {{ fact }}
{% endfor %}
Dependencies to consider:
{% for dep in ecosystem.current_project.depends_on %}
- {{ dep }}
{% endfor %}
Focus on common issues for {{ ecosystem.current_project.type }} projects.
"""
Ecosystem Discovery
Analyze projects and store findings in the memory database:
= "discover"
= "Discover and store ecosystem facts"
[[]]
= "analyze"
= "query"
= "analyzer"
= 180
= """
Analyze the {{ ecosystem.current_project.name }} project structure.
IMPORTANT: Return JSON with this exact structure:
{
"facts": [
{
"project": "project-name",
"fact": "brief fact description",
"source": "where you found this (e.g., Cargo.toml)",
"confidence": 1.0
}
]
}
Each fact MUST have all four fields: project, fact, source, confidence.
"""
[]
= "object"
= ["facts"]
[]
= "array"
[[]]
= "store"
= "store"
= "{{ steps.analyze.output }}"
= ["analyze"]
See examples/workflows/discover-ecosystem.toml for a complete implementation with multiple analysis steps and relationship discovery.
Contributing
llm-mux is built with Rust. To contribute:
Publishing
Published to crates.io and GitHub.
License
MIT