Lab · Local AI
Tap a component to see its step.
- Claude Code · step 5 ANTHROPIC_BASE_URL
- OpenCode · step 6 rebel provider
- Rebel Router · step 4 127.0.0.1:8787
- Budgets · step 3 rebel.yaml
- Providers · step 2 your keys (.env)
- OpenCode Zen · step 2 one key, many
- FinOps ledger · step 4 SQLite + dashboard
Install Rebel Router from GitLab, connect it to Claude Code and OpenCode, set budgets, and check which model answered and what it cost.
What you will build and why
Claude Code and OpenCode send almost everything to the same model: the one you picked when the session started. That includes writing a test, summarising a file or updating a README, jobs a much cheaper model handles just as well. Rebel Router is a local proxy that sits in between: it looks at each request, decides what kind of task it is (orchestration, complex code, bulk code, unit tests, QA or documentation), picks among the three models that fit best on quality, price and speed, and writes the cost to a SQLite ledger with budgets.
In this lab you install it from its GitLab repository, bring your own keys (or a single OpenCode Zen key), connect it to Claude Code and OpenCode, set a daily and a per-project budget, and check which model really answered and what it cost. Everything runs on your machine; the router only listens on 127.0.0.1.
One warning before you start: in our 12-task benchmark, letting the router choose cost 82% less than using Claude Opus 5.5 for everything, but it passed 9 of 12 tasks against 11 of 12. It is a first measurement on a small sample. That is why the lab also shows you how to keep on Opus whatever you do not want to risk.

Requirements
Step by step
Clone and install Rebel Router
You need Node.js 22.13 or later. The package has a single runtime dependency.
npm installbuilds the code andnpm linkputs therebelcommand on your PATH.If
npm linkasks for permissions, your global npm prefix belongs to the system. Use a Node version manager, or run the router from the clone withnpx rebel start.git clone https://gitlab.com/larebelion/rebel-router.git cd rebel-router npm install npm link rebel modelsBring your own keys (or one OpenCode Zen key)
Rebel Router ships with no keys: it uses yours, and only for the provider it picks for each request. Copy the example to
.envand fill in the ones you have. A provider without a key is skipped.If you would rather not have one key per vendor, an OpenCode Zen key in
OPENCODE_API_KEYreaches GPT, Grok, DeepSeek, Kimi, GLM and Qwen. By default Zen is only used for vendors without a key of their own, and never for Claude. Gemini is not on Zen and still needsGEMINI_API_KEY.VENICE_API_KEYis optional: it turns on the JEV classifier (beta); without it the router classifies with local rules.cp .env.example .env chmod 600 .envFile
.envANTHROPIC_API_KEY=CHANGE_ME_ANTHROPIC_API_KEY OPENAI_API_KEY= XAI_API_KEY= GEMINI_API_KEY=CHANGE_ME_GEMINI_API_KEY DEEPSEEK_API_KEY= OPENCODE_API_KEY=CHANGE_ME_OPENCODE_ZEN_KEY VENICE_API_KEY=Replace every CHANGE_ME_… value with your own before starting: never keep example passwords or keys.
Set budgets and rules
The configuration lives in
~/.rebel-router/rebel.yaml(or in./rebel.yamlin the directory you start the router from). This file caps spend at 10 dollars a day and 3 for theshopproject, prefers cheaper models from 80% of a budget, and at 100% drops to the cheapest acceptable model (downgrade) instead of cutting you off.Two rules worth knowing from day one:
aliases.opus: passthroughsends whatever you ask Opus for to Opus unchanged, andlocalOnlykeeps a project on your machine (Ollama models only). If you would rather have a hard stop, setonLimittoblockand the router answers HTTP 402.mkdir -p ~/.rebel-routerFile
~/.rebel-router/rebel.yamlserver: host: 127.0.0.1 port: 8787 routing: excludeProviders: [] aliases: opus: passthrough haiku: hint budgets: daily: 10 projects: shop: 3 onLimit: downgrade downgradeAt: 0.8 projects: secret-client: localOnly: true opencode: gateway: autoStart the router
Load
.envinto the environment and start it. The router listens onhttp://127.0.0.1:8787, serves its dashboard on/dashboardand writes every request to~/.rebel-router/ledger.db. Leave it in a terminal of its own or run it as a service.The
providersline of the start-up banner says which vendors have a key and which go through Zen. Read it: if one you expected is missing,.envwas not loaded.set -a; . ./.env; set +a rebel startExpected output
Rebel Router 0.1.0 listening on http://127.0.0.1:8787 classifier: local rules (set VENICE_API_KEY to enable JEV) dashboard: http://127.0.0.1:8787/dashboard Claude Code: ANTHROPIC_BASE_URL=http://127.0.0.1:8787 OpenCode: baseURL http://127.0.0.1:8787/v1Connect Claude Code
rebel init claude --globalmerges its settings into~/.claude/settings.json(after saving asettings.json.rebel-backupcopy, and touching nothing else). It pointsANTHROPIC_BASE_URLat the router, turns on the headers that say whether a call comes from the main session, a subagent or a compaction, and adds the hooks, the status line and the/rebel-spendand/rebel-topcommands.With
--globalthe CLI,claude -p, subagents, IDE extensions and the Agent SDK with user settings all go through the router. For per-project budgets, also install it in each project with--project, so every request carries thex-rebel-projectheader. Restart Claude Code afterwards.Mind what you will see: Claude Code keeps showing the model it asked for (Opus, say); the one that really answered is on the status line. No hook can change the session model, which is why the proxy does the switching.
rebel init claude --globalcd ~/code/shop rebel init claude --project shopConnect OpenCode
In OpenCode the router is declared as one more provider.
rebel init opencodewritesopencode.jsonwith therebelprovider and a plugin under.opencode/plugins/. Then pick the modelrebel/autowith/models, orrebel/auto:unit_teststo pin the task class.The integration targets OpenCode 1.19, the stable release. The 2.0 preview builds changed the plugin format and did not load the provider.
cd ~/code/shop rebel init opencode --project shopThe two cases you configure by hand
Claude desktop app (Code tab). It does not read
ANTHROPIC_BASE_URLfrom the settings files. Go to Developer → Configure Third-Party Inference and set the base URL tohttp://127.0.0.1:8787.VS Code extension. The Claude Code it spawns does read the settings files, but the extension's own login check does not. Add the variable to your VS Code user settings.
File
settings.json (VS Code user){ "claudeCode.environmentVariables": [ { "name": "ANTHROPIC_BASE_URL", "value": "http://127.0.0.1:8787" } ] }
Check that it works
See how it classifies and what it would pick
rebel classifyshows the class and complexity it gives an instruction, without calling any model.rebel toplists the three models the Broker would pick for that class, with the reason. You can pin a class by writing#rebel:tests,#rebel:docsor#rebel:complexin a prompt.rebel classify "Write vitest unit tests for the slugify function" rebel top --task testsExpected output
{ "taskClass": "unit_tests", "complexity": 0.15, "confidence": 1, "source": "rules",Check that it routes and that the spend adds up
Work for a while in Claude Code or OpenCode, then read the ledger.
rebel spendgroups spend by model, task class, project or day;rebel exportwrites a CSV with every request (requested model, model used, tokens, cost, latency and the reason for the pick). The dashboard athttp://127.0.0.1:8787/dashboardshows the same as charts.To reconcile, compare one day's total with your provider's billing console. Cost is the token usage each provider reports times the official price in the catalogue, so it should match unless there are discounts or surcharges the catalogue does not know about.
rebel status rebel spend --today --by model rebel spend --today --project shop --by task_class rebel export --days 1 > spend.csv
If something fails
Claude Code does not go through the router
Check that the variable is in the settings and that the router is running. Inside Claude Code, /status shows the base URL in use: a launcher or a variable exported in your shell can win over the user settings. The desktop app and VS Code need the manual change from step 7.
grep ANTHROPIC_BASE_URL ~/.claude/settings.json
rebel statusRequests fail with HTTP 402
You hit a budget with onLimit: block. See which project spent it, raise the limit in rebel.yaml, or switch to downgrade so the router drops to a cheaper model instead of refusing.
rebel spend --today --by projectHTTP 508 when chained with another gateway
The router detected a loop: a provider URL points back at the router itself. If you use a corporate gateway, put its URL in providers.anthropic.baseUrl in rebel.yaml and keep Claude Code pointed at the router.
OpenCode says the model rebel/auto is unavailable
This is usually an OpenCode 2.0 preview build. Go back to the stable 1.19 and repeat step 6.
Harden the setup
Keep the router local
Leave server.host at 127.0.0.1: the router holds your keys and refuses requests with a non-local Host, a browser Origin from another site or a non-JSON body, so no web page can spend your credit. Do not expose it on the network.
Critical work on the model you choose
The benchmark showed where cheap routing fails: unit tests and QA. Use aliases.opus: passthrough so Opus requests are left alone, classModels to pin a model per task class, and localOnly for projects whose code must not leave your machine.
What JEV sees
If you turn JEV on, Venice only receives a summary: the first 600 characters of your latest instruction, the approximate context size, tool names and file extensions. Never the code. With classifier.jev.summary.maxChars: 0 no text is sent, and without VENICE_API_KEY it is not used at all.
Clean-up: undo the lab
Remove the router and go back to where you were
--uninstall removes only what Rebel Router added and puts back the values it replaced. Then uninstall the command and, if you do not want to keep your spend history, delete ~/.rebel-router (the ledger and your rebel.yaml live there). In OpenCode, remove the rebel provider from opencode.json.
rebel init claude --global --uninstall
npm rm -g rebel-router
rm -r ~/.rebel-routerWhat is verified
- .env: no automatic validator, review it by hand
- ~/.rebel-router/rebel.yaml syntax (YAML parser)
- settings.json (VS Code user) syntax (JSON parser)
- Syntax of 12 command block(s) (bash -n in an isolated container, not executed)
- Versions (4), options (7) and config keys (28) checked against 8 official documentation pages
- Install from GitLab (git clone, npm install, npm link) and the repository's 90 tests passing
- Router against a fake provider (scripts/mock-provider.mjs): Anthropic API requests classified and routed, rebel spend, rebel status, rebel export and the /dashboard page
- Budget with onLimit: block: the request past the limit gets HTTP 402
- rebel init claude --global and --uninstall on an existing settings.json (what was there is kept) and rebel init opencode
- Real Claude Code 2.1.295 (claude -p with a subagent) through the router against the fake provider (npm run smoke:claude)
- 12-task benchmark with 10 models and real keys through a gateway (results in bench/results/latest.json)
- With your own provider keys, the desktop app and the VS Code extension: not run here, check them on your machine
Automatic checks run on 11 October 2026. Items marked "·" were not executed: check them in your own environment.
Sources
- Rebel Router: README and install gitlab.com
- Rebel Router with Claude Code gitlab.com
- Rebel Router with OpenCode gitlab.com
- Example configuration (rebel.example.yaml) gitlab.com
- Rebel Router benchmark gitlab.com
- OpenCode Zen opencode.ai
Did this lab work for you?
Rate it from 1 to 5 stars. One vote per person; you can change it any time.
Article generated with AI.larebelion



Comentarios
Publicar un comentario