routing · larcane97 — скилл для Claude Code: выбор аккаунта и установка
Скилл помогает запускать Claude Code или Codex через маршруты clausona, выбирая аккаунт по использованной квоте. Пригодится, когда один аккаунт достиг лимита или нужно распределить запуски.
npx skills add larcane97/clausona --skill routing -a claude-codeЧто делает routing
Скилл объясняет, как создавать и менять маршруты clausona, разбирать выбор аккаунта и настраивать правила для папок и значения по умолчанию. Маршрут объединяет аккаунты и задаёт способ выбора по использованию квоты; запуск выполняется через clausona run --route <name>. Для проверки предусмотрены команды clausona route list --json и clausona route explain <name> --json.
При выборе учитываются окна квоты 5H и 7D, а при явно заданной модели — также её лимит. Можно использовать стратегии round-robin, headroom и expiring; если все аккаунты достигли 100% или пропущены, запуск завершается с кодом 75. Для ожидания сброса квоты у команды есть флаг --wait. Скилл рассчитан на работу с clausona: без настроенных аккаунтов и маршрутов выбирать будет не из чего.
Какие задачи решает
- запустить Claude Code через аккаунт с доступной квотой
- распределить несколько запусков между аккаунтами
- разобраться, почему маршрут выбрал конкретный аккаунт
- дождаться сброса квоты перед запуском
Примеры запросов агенту
- Запусти Claude Code через маршрут
work, выбрав аккаунт с меньшим использованием квоты. - Объясни, почему маршрут
workвыбрал этот аккаунт для моделиopus. - Настрой маршрут для аккаунтов этой рабочей папки и покажи правила выбора.
Как установить routing
1Через Skills CLI (Vercel)
npx skills add larcane97/clausona --skill routing -a claude-code2Вручную: положить файлы
~/.claude/skills/routing/SKILL.mdПапка скилла целиком; для одного проекта — .claude/skills/routing/
1Через Skills CLI (Vercel)
npx skills add larcane97/clausona --skill routing -a codex2Вручную: положить файлы
.agents/skills/routing/SKILL.mdДля всех проектов — ~/.agents/skills/
1Через Skills CLI (Vercel)
npx skills add larcane97/clausona --skill routing -a cursor2Вручную: положить файлы
.cursor/skills/routing/SKILL.mdCursor читает и .agents/skills/, и .claude/skills/
1GitHub CLI
gh skill install larcane97/clausona routing2Вручную: положить файлы
.github/skills/routing/SKILL.md1Через Skills CLI (Vercel)
npx skills add larcane97/clausona --skill routing -a gemini-cli2Командой платформы
gemini skills install https://github.com/larcane97/clausona --path plugins/routing/skills/routingВручную: положить файлы
.devin/skills/routing/SKILL.mdСтарый путь .windsurf/skills/ тоже читается
Через Skills CLI (Vercel)
npx skills add larcane97/clausona --skill routing -a opencodeClaude.ai
Упакуйте папку в zip и загрузите в Settings → Capabilities → Skills
По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов
Вопросы о routing
Как установить routing в Claude Code?
Выполните npx skills add larcane97/clausona --skill routing -a claude-code. Файл скилла будет доступен по пути ~/.claude/skills/routing/SKILL.md.
Что делает routing?
Скилл помогает управлять маршрутами clausona и запускать Claude Code или Codex через аккаунт, выбранный по квоте. Он также разбирает правила папок и настройки по умолчанию.
Как routing выбирает аккаунт для модели opus?
Если модель указана в аргументах запуска, к квотам аккаунта добавляется лимит этой модели. Проверить предполагаемый выбор можно командой clausona route explain <name> --model opus --json.
Исходный текст
SKILL.md · MIT
---
name: routing
description: Run Claude Code or Codex on whichever clausona account has quota left, using clausona routes, and create, change or explain those routes, and the dir rules and defaults that pick one for a plain `clausona run claude`, for the user. Use when the user says "run this on an account with room", "spread these across my accounts", "make a route of my work accounts", "use my work accounts in this repo", "why did it pick that account", "wait until an account frees up", when a run stops on a usage limit (of the plan or of one model, such as Opus), when writing a script or cron job that runs on a route, or when starting several workers that should not all land on one account.
---
# Routing runs across clausona accounts
clausona keeps several Claude Code and Codex accounts on one machine. A **route** is a named
group of those accounts and a rule for picking one of them by how much of its plan quota is
used. `clausona run --route <name>` starts the tool on the account the rule picks right now.
(`csn` is an alias for `clausona` that only the user's interactive shell has. Run `clausona`.)
Run `clausona route --help` once before anything else. It lists every command, option and exit
code of the installed version. Where it differs from this skill, it wins.
`clausona route` with no arguments opens the Routes screen, a TUI meant for a person at a
terminal. Do not run it; use the subcommands below. (In a shell without a terminal it only prints
the help.) A user who would rather look through routes on that screen can run it themselves.
## What decides the pick
- An account's **usage** is the higher of its 5H and 7D windows: 0% 5H with 99% 7D is 99%.
That number, and nothing else, is ranked and shown.
- When the tool's arguments name a model (`claude --model opus`, `codex -m gpt-5.3-codex-spark`,
also after `exec`), the account's limit on that model joins the max: Claude's is weekly, and a
Codex one can have a 5-hour and a weekly window, of which the higher counts (named in the note
and `usage.window` as `GPT-5.3-Codex-Spark 5H` or `… 7D`). A model falls under
a limit when the limit's name (`Opus`, `GPT-5.3-Codex-Spark`) is a word of the model's name,
in any case: `opus`, `claude-opus-4-5`, `opus[1m]` fall under `Opus`; `gpt-5.3-codex` does not
fall under `GPT-5.3-Codex-Spark`. A run that names no model counts no model's limit, even if
the account's default model has one: pass `--model` when the work needs a model with its own
limit. `-c model=…`, a Codex config profile and `opusplan` are not read.
- clausona stops at the first stage that finds someone:
1. **pool**: `from` members under `maxUsage` (default 80), chosen by the strategy.
2. **fallback**: the first `fallback` member, in listed order, under `maxUsage`.
3. **overflow**: every member is at `maxUsage` or over it, so the one with the most left
(lowest usage) is taken, pool or fallback, at 90% or 99% alike.
4. **nobody**: every member is at 100% or skipped. Nothing is launched, exit code **75**.
With `--wait`, it waits for the soonest reset instead and starts again at 1 (see
[Waiting](#waiting-for-a-free-account)).
- Strategies: `round-robin` (default; the account picked longest ago, a never-picked one
first), `headroom` (lowest usage), `expiring` (lowest usage among accounts whose weekly limit
resets within 24 hours; with none, as `headroom`).
- Signed-out, expired and unreadable accounts are skipped at every stage, and so is one whose
stored sign-in is another account's.
- An API profile in a route (named exactly; no pattern matches one) is ranked by its spend as a
share of its limit: a clausona budget (`clausona route budget`), else the limit set on its
provider key. One with no limit, whose provider reports no spend, or whose spend could not be
read is skipped. It is billed per use.
- Resumed runs (`-c`/`--continue`, `-r`/`--resume`, `--from-pr`, `codex resume` or `fork`) use
only accounts that share sessions: the primary account and profiles with merged sessions. If
none of them can take it, the account that holds the session has to be run by name.
## Looking before acting
```bash
clausona route list --json # routes, their settings with defaults, their members, dir rules
clausona route explain <name> --json # every member's usage and status; launches and records nothing
clausona route explain <name> --model opus --json # as a run of that model would rank it
clausona route explain --json # what clausona run claude and codex would take in this directory
clausona list --json # every profile, with its email and quota
clausona route budget --json # every API profile: its limit, whose limit, spend and usage
```
`explain --json` gives:
- `settings`: the route with its defaults. `settings.tool` is `claude`, `codex` or `all` (a route
over the accounts of both tools).
- `outcome`: `{"kind": "picked", "id", "stage", "reason"}`, or `{"kind": "none"}` with
`soonest` (`{"id", "at"}`) when a reset time is known. `explain` exits 0 even when nobody could
be picked, so read `outcome.kind`.
- `members`, one per account: `status` is `picked`, `eligible` (under the cut, not picked),
`over-limit` (at or above `maxUsage`) or `skipped`. A skipped one has `skipReason`:
`signed-out`, `expired`, `other-account` (its stored sign-in is another account's),
`no-reading`, `not-registered`, `keeps-own-sessions`, or for an API profile `no-spend-limit`,
`spend-not-reported` or `spend-unread`. Each also has `usage`,
`fiveHour`, `sevenDay` and `lastPickedAt`, `scoped` (`{"label", "usedPercent", "resetsAt"}`,
its limit on the `--model` model, of a Codex limit with two windows the higher, or null) and
`budget` (an API profile's `{"usedPercent", "spentUsd", "limitUsd", "source", "per",
"resetsAt"}`, or null). `usage.window` is `5H`, `7D`, the name of that limit (its label for
Claude, `Opus`; its label and window for Codex, `GPT-5.3-Codex-Spark 7D`), or `budget`. The top
level has `model`.
`route list --json` gives each route's `members`, `freeNow` (`{"free", "members"}`) and `next`
(as `outcome`), and `problems`: what is wrong with each route in `routes.json` that cannot be
used, and with each dir rule or default that cannot be read. Such a route is left out, and only
commands that use it fail; tell the user, and point them to `clausona route edit` rather than
editing the file yourself. It also gives `dirs` (`{"~/work": {"claude": "work"}}`), `defaults`
(`{"claude": "main"}`) and `ruleWarnings`: rules that name a route that is gone or is for the
other tool, which a run skips.
With `--json`, a failing `route` command prints `{"version": 1, "error", "message"}` on stdout.
`error` is `usage`, `not-found` (no such route) or `failed`; a `routes.json`, or a route named,
that cannot be used adds `file` (its path) and `problems`.
Answer "why did it pick X" from `explain`: `outcome.stage` and `outcome.reason` for the pick, and
each other member's `status`, `skipReason` and usage. `explain` takes the same field options as a
run (`--strategy`, `--max-usage`, …) and `--resume`, to show what a run like that would get.
## Creating or changing a route for the user
`route add` and `route set` never ask, in a terminal or not. They write at once, and `route add`
then prints the route it made. So the asking is yours to do, before you write:
1. Show the user which accounts the route would hold. Rank it unsaved and show them the result:
`clausona route explain --tool <claude|codex|all> --from '<patterns>' [--exclude '<patterns>']`.
For a change, show the route as it is (`route explain <name>`) and as it would be.
2. Ask before including accounts that look like someone else's or shared: another person's name
or email, `*-share`. Leave them out until the user says yes.
3. `*` takes every subscription account of the tool, including ones added later. When the user
described a subset ("my work accounts"), use names (`work,work2`) or an email pattern
(`*@example.com`) instead.
4. Never put an API profile in a route unless the user names it: it is billed per use. A
pattern never matches one, so `*` is safe; it joins only by its exact name (`claude:glm`).
It also needs a spend limit: `route add` and `route set` refuse one without, naming
`clausona route budget <profile> --usd 20 --per month`. Set a budget only with the amount and
period the user gives. A budget stops new routed sessions, not a running one. Run an API
profile by name (`clausona run claude:glm`) only when the user asks for it.
5. Wait for the user's OK, then write with the CLI. Never edit `~/.clausona/routes.json`
yourself, and do not use `route edit`: it opens an editor for a person.
```bash
clausona route add <name> [--tool claude|codex|all] --from '<patterns>' [--exclude '<patterns>'] [--fallback '<patterns>'] [--strategy <s>] [--max-usage <n>]
clausona route set <name> [--from …] [--exclude …] [--fallback …] [--strategy …] [--max-usage …] [--add …] [--drop …] [--no-fallback]
clausona route rename <old> <new>
clausona route remove <name>
```
- `--tool` is the route's tool: `claude` (the default), `codex`, or `all` for one route over the
accounts of both tools. Without `--tool`, `--from` entries that all carry one tool's prefix
(`codex:a,codex:b`) make a route for that tool, and prefixes of both tools make an `all` route.
Check `clausona list --json` for which tools have accounts. `route set` cannot change the tool.
- `--yes` is accepted and does nothing. You do not need it.
- Patterns are comma-separated profile names or globs (`team-*`, `claude:team-*`). A pattern
with an `@` matches account emails. Matching ignores case. Quote the list.
- On an `all` route a name without a prefix matches in both tools: `personal` is
`claude:personal` and `codex:personal`. Use the prefixed id to mean one account.
- In `route set`, each field option replaces its whole field: `--exclude old` makes the exclude
list just `old`. To add to a list, pass its current entries too (from `route list --json`).
- `--add` and `--drop` change `from` one entry at a time. `--drop` removes only an entry written
in `from`, so it cannot take one account out of `*` or `*@example.com`. Use `--exclude` for
that.
- `rename` and `remove` act at once. Ask before removing a route. `rename` also rewrites the dir
rules and defaults that name it; `remove` also removes them, and says which.
- A route name starts with a letter or a digit, and the rest is letters, digits, `.`, `_` and
`-`. Names and patterns that look like an API key or a token are refused, and clausona does
not print them back. Never put a key in either.
## Running
```bash
clausona run --route <name> -- -p "<prompt>" # Claude Code, non-interactive
clausona run --route <name> -- exec "<prompt>" # a Codex route
clausona run codex --route <name> -- exec "<prompt>" # an all route: name the tool
clausona run claude --from '<patterns>' -- -p "<prompt>" # an unsaved route
clausona run --route <name> --strategy headroom -- -p "…" # change a field for this run only
```
- Routing options (`--route`, `--from`, `--exclude`, `--strategy`, `--max-usage`, `--fallback`,
`--wait`) go before the tool's own arguments. A `--` ends them, and everything after it goes to the tool
untouched (`--model`, `--permission-mode`, `--output-format json`, …).
- The field options need `--route` or `--from`. On their own they are refused with exit 1.
- On an `all` route (`settings.tool` is `all`), put the tool word before `--route` whenever you
pass arguments: `clausona run claude --route <name> -- -p "…"`. Only that tool's accounts are
ranked. Arguments without a tool word are refused with exit 1, because Claude Code and Codex
take different ones. `route explain` and `route pick` narrow the same way with `--tool`.
- Next to `--route`, `--exclude x` leaves `x` out for this run on top of the route's own
excludes. The other field options replace their field for this run. Nothing is saved.
- Never put a profile right after routing options or a tool word. These are refused, because the
tool would get the name as its prompt: `clausona run --route main claude:work`,
`clausona run claude claude:work`. To run one account, name it alone
(`clausona run claude:work`). If a profile is named like one of the tool's commands (`exec`,
`mcp`), put `--` before the command: `clausona run codex -- exec …`.
- `clausona run claude` (or `codex`) with no routing options takes a route from the user's
[dir rules and defaults](#dir-rules-and-defaults): the deepest dir rule for the current
directory, then the tool's default, then the active profile. `clausona route explain --json`
with no name says which. With no tool word and no `--route` or `--from`, it is refused.
- Naming a profile (`clausona run claude:work`) always runs it, whatever its quota.
- A routed run names the account it picked, and why, on stderr. stdout is the tool's own.
- Without a terminal an unknown `--route` creates nothing: it exits 1 with
"Create it: clausona route add <name>". Treat that as a new route: show the members and ask
first, as above.
- `clausona run --route <name>` with no tool arguments is an interactive session. Give that
command to the user instead of starting it from your shell.
## Waiting for a free account
`--wait` makes "nobody is free" a wait instead of an exit 75, for `run` and `route pick` alike:
```bash
clausona run --route <name> --wait -- -p "<prompt>" # waits up to 5h
clausona run --route <name> --wait=2h -- -p "<prompt>" # or 30m, 1h30m: after `=`, never a space
id=$(clausona route pick <name> --wait=1h --model opus) # an orchestrator's turn, waiting
```
- It sleeps until 30 s after the soonest reset of an account at 100%, reads quota again at
least every 30 minutes, and then ranks again. stderr says `waiting until 14:05 for claude:work
(5H resets) …`; stdout stays the tool's, or `pick`'s id or JSON.
- If the soonest reset is past the cap, or no reset time is known, it exits 75 at once, and the
message says the cap that would reach it (`--wait=48h`). Ctrl-C exits 130; nothing is launched
or recorded.
- Several waits that wake together take different accounts, as picks always do.
- Your own shell tool call times out long before a wait of hours ends. Use `--wait` in a script,
in cron, or in a command you give the user; from your shell, only with a cap shorter than your
tool's timeout, or run it in the background. Ask before starting a wait of more than a few
minutes.
A cron or script recipe, for the user:
```bash
clausona run claude --route nightly --wait=4h -- -p "review yesterday's commits" > review.md
case $? in 0) ;; 75) echo "no account came free within 4h" >&2 ;; *) exit 1 ;; esac
```
cron has a short `PATH` (give it one that reaches `clausona`, `claude` and `node`) and no
terminal, so an unknown route exits 1 instead of asking.
## Dir rules and defaults
A dir rule gives a directory a route per tool: in that directory and below, a plain
`clausona run claude` (or `codex`) with no `--route` or `--from` runs on it. The deepest rule
for the current directory wins. A default does the same everywhere no rule holds. With neither,
the run takes the tool's active profile.
```bash
clausona route explain --json # here: what each tool's run takes, and why
clausona route dir # every dir rule and default
clausona route dir ~/work work # in ~/work and below, run claude takes route work
clausona route dir ~/work any --tool codex # an all route fills both tools unless --tool says one
clausona route dir ~/work --clear [--tool codex]
clausona route default main # elsewhere, run claude takes route main
clausona route default --clear --tool claude # --tool is required to clear (claude, codex or all)
```
- These change what every plain run in that directory does, the user's own included. Say what
will change (`route explain` from that directory shows what runs now) and wait for the user's OK
before you set or clear one.
- A route fills the slot of its own tool. An `all` route fills both, or the one `--tool` names. A
route of the other tool is refused. The route must exist first.
- A path may be relative, absolute or start with `~`; it is stored with `~` when it is under
home. A rule matches its directory through symlinks, and ignoring case on macOS and Windows.
- `route explain --json` with no name gives `{"directory", "runs": [...]}`, one entry per tool
(`--tool` limits it to one). A routed entry is the `explain --json` of its route, plus `tool`
and `skipped`. Its `resolvedBy` is `dir:<path>` (the rule's path as stored, with `~`) or
`default`. An entry with no route is `{"tool", "route": null, "resolvedBy": "active",
"profile", "skipped"}`, `profile` null when the tool has no active profile. `skipped` lists
the rules passed over as `{"rule", "reason"}`, `rule` being `dir:<path>` or `default`.
- A rule whose route is gone, cannot be used or is for the other tool is skipped: the run says so
on stderr and goes on to the next rule. A rule that cannot be read at all is named by
`route list` (in `problems`); a run only says that there is one. If `routes.json` cannot be read at all, a plain run
says so in one line and runs the active profile; a run with `--route` fails as before.
## Several workers at once
Take one turn per worker on a round-robin route, and start each worker on its own pick:
```bash
id=$(clausona route pick main); code=$? # one profile id on stdout; records the turn
clausona run "$id" -- -p "$(cat <brief file>)" # start this worker in the background
```
Do both for each worker in turn, and check `code` every time: 0 starts the worker on `$id`; 75
means nobody is free, so start no more workers (next section); anything else is an error to show
the user.
- Each pick records the turn, so the next pick takes the next account under the cut. Never start
every worker on one `pick` result, and never on ids copied from `explain`, which records nothing.
- With fewer accounts under the cut than workers, later picks come back to an account already in
use. Once every account is over the cut, a pick (stage `overflow`) takes the one with the most
left, not the next turn. Tell the user which workers share an account.
- One `clausona run --route main -- -p …` per worker also takes its own turn. Use `pick` when you
want the id before you start.
- On an `all` route a pick can be an account of either tool. Pick with `--tool claude` (or
`codex`) so every id is of the tool your worker command is written for.
- On a `headroom` or `expiring` route, picks made close together land on the same account
(readings are cached for 5 minutes). Add `--strategy round-robin` to each `pick`, or use a
round-robin route.
- `pick --json` prints `{"profile", "route", "stage", "usage", "reason"}`. When nobody is free it
still prints JSON, with `"profile": null` and `soonest` (`{"id", "at"}`, or null), and exits 75.
- When workers run a model with its own limit, pick with `--model` too
(`clausona route pick main --model opus`), so a spent Opus limit is not picked for an Opus worker.
- To wait for a free account instead of stopping at 75, pick with `--wait` (above).
## When nobody is free (exit 75)
Nothing was launched. Every account of the route is at 100% of a window, or was skipped. The
message on stderr lists each account with its usage and when it resets, or why it was skipped,
and marks the soonest reset (with `--json`, `soonest.at`). Tell the user which account frees up
first, and when, and which skipped ones `clausona login <profile>` would bring back. Workers
already started keep running. If the work can wait, offer the same command with `--wait` (or the
longer `--wait=<n>h` the message names) for the user to run.
A higher `--max-usage` does not help: past the cut, any account under 100% is already taken. Do
not run an account by name to get past the limit unless the user says so. If they do, name the
risk: that account is at its limit, so the session may stop at once.
## When a run stopped on a usage limit
If it was a limit on one model (Claude's Opus limit, say), start it again with that model named
(`-- --model opus`), so the account whose limit on it is spent is not picked again.
Otherwise start it again on the route. The spent account is now at or above the cut, so another one is
picked. But readings are cached for up to 5 minutes, and with every account over the cut, a
cached reading under 100% can pick the spent one again: if `explain` would still pick it, or
shows it `eligible`, add `--exclude` with it for this run. The route's own excludes still apply.
To carry on the same session, pass `-c` or `--resume` after `--`; that run only goes to accounts
that share sessions.
© larcane97 · MIT · larcane97/clausona
Похожие скиллы
Все скиллы по теме «Настройка агента: память, контекст, субагенты» →Сначала — routing от других авторов.