agentlb runs Codex with isolated per-alias CODEX_HOME and a background supervisor that tracks session usage in ~/.agentlb/status.json.
cargo build --releasecargo install --path .agentlb config init
agentlb new work
agentlb new personal
agentlb status
agentlb new
agentlb supervisor
agentlb supervisor start --backgroundagentlb- Pick best session using
~/.agentlb/status.json(same selector asagentlb new). - If status is unusable after retry, falls back to existing managed aliases.
- Use
--print-commandto print the resolved shell command (withCODEX_HOME) instead of executing it.
- Pick best session using
agentlb status- Print one combined table with:
- alias
- email (when available)
- absolute session path
- usage/scoring/eligibility columns used by
agentlb newauto-selection
- Email is read from each session's auth metadata;
-means unavailable.
- Print one combined table with:
The status table includes these columns:
*(first column)- Selection marker.
*means this is the session that would be selected byagentlb new.
ALIAS- Session alias directory name under
~/.agentlb/sessions.
- Session alias directory name under
EMAIL- Account email detected from session auth metadata.
PATH- Absolute session directory path.
PRIM- Remaining percent for the primary (short/current) rate-limit window.
100means untouched,0means exhausted.-means no primary window data is available.
WEEK- Remaining percent for the secondary (long/weekly) rate-limit window.
-means no secondary window data is available.
USAGE- Blended remaining usage used in scoring (weighted primary/secondary, or fallback).
SCORE- Final auto-selection score after penalties.
-means the session is ineligible (for example stale or unhealthy).
RESTART- Number of recent managed app-server restart failures for this session.
ACTIVE- Number of currently active turns tracked for this session.
HEALTH- Session health used by selector (
healthyorunhealthy).
- Session health used by selector (
REASON- Eligibility reason:
eligiblemeans score is active.- examples like
stale (...)/unhealthyexplain exclusion.
- Eligibility reason:
At the end, selected session: ... shows the final winner (or <none> when no eligible session exists).
agentlb new <alias>- Create alias if missing.
- Run login once on first creation.
- Run command in that alias.
- Use
--print-commandto print the resolved command and skip login/run execution.
agentlb new <email>- Resolve email to an existing session alias and run that session.
- Use
agentlb statusto see available alias/email/path mappings and selection status. - If zero matches: returns a not-found error.
- If multiple matches: returns an ambiguity error and asks for explicit alias.
agentlb rm <alias-or-email>- Remove a managed session.
- Deletes session directory under
~/.agentlb/sessions/<alias>. - Removes session entry from
~/.agentlb/state/sessions/<alias>.jsonand~/.agentlb/status.json. - Clears
last_aliasif it points to the removed session. - Restarts supervisor afterward to refresh managed process set/state.
agentlb new- Pick best session using
~/.agentlb/status.json(usage-aware selection). - If status is unusable after retry, falls back to existing managed aliases.
- Use
--print-commandto print the resolved command for the selected session.
- Pick best session using
agentlb rr- Force round-robin across aliases.
- Use
--print-commandto print the resolved command for the selected alias.
agentlb last- Run the most recently selected alias.
- Use
--print-commandto print the resolved command forlast_alias.
agentlb supervisor- Print supervisor command help.
agentlb supervisor start --background- Print current supervisor status.
- Start supervisor in background if needed.
agentlb supervisor restart- Stop the running supervisor (if any) and start a new background supervisor.
agentlb supervisor stop- Stop the running supervisor (if any).
agentlb config init- Write default config to
~/.agentlb/config.toml.
- Write default config to
agentlb and agentlb new read only ~/.agentlb/status.json.
A session is eligible only if:
health == "healthy"lastRateLimitUpdateAtis parseable and not stale- staleness threshold:
now - lastRateLimitUpdateAt <= 420s
From rate limit windows:
remaining_primary = 100 - primary.usedPercent(short/current window)remaining_secondary = 100 - secondary.usedPercent(weekly window)- if both exist:
usageLeftPercent = 0.60 * remaining_primary + 0.40 * remaining_secondary
- if only one exists: use that one
- if none exist:
usageLeftPercent = 30
This makes both daily and weekly quota pressure affect picks, instead of letting only one window dominate.
For each eligible session:
score = usageLeftPercentscore -= activeTurns * 5score -= min(restartCount * 2, 20)score -= staleness_penaltystaleness_penalty = clamp((age_sec * 10 / 420), 0, 10)
Higher score wins.
When scores tie:
- Higher
usageLeftPercent - Lower
activeTurns - Older
lastSelectedAt(LRU spread) - Lexicographically smaller alias
If no usable candidate is found:
- retry status reads for up to
3000ms - if still unusable, fall back to existing managed aliases (round-robin)
- if no managed aliases exist, return an actionable error
On every normal agentlb command invocation:
- checks
~/.agentlb/supervisor.pid - starts supervisor if missing/dead
- continues command flow
Supervisor responsibilities:
- maintain managed
codex app-serverper active alias - ingest JSON-RPC usage/status events
- atomically flush
~/.agentlb/status.json - restart crashed app-servers with exponential backoff + jitter
- run startup + periodic probes for aliases without active managed app-server
- proactively refresh rate limits before sessions reach stale threshold
Supported on agentlb, agentlb new, agentlb new <alias-or-email>, agentlb rr, and agentlb last:
--print-commandprint the final shell command (includingCODEX_HOME=...) and exit without spawning login/run--cmd "<command string>"override run command for this invocation--login-cmd "<command string>"override login command (new alias only)-- <args...>pass-through args appended to run command
Examples:
agentlb --cmd "codex --model gpt-5.1-codex-mini"
agentlb --print-command --cmd "codex --model gpt-5.1-codex-mini"
agentlb new work -- --search
agentlb new work --print-command -- --search
agentlb new gngeorgiev.it@gmail.com -- --search
agentlb new --print-command -- --help
agentlb rm work
agentlb rm gngeorgiev.it@gmail.com
agentlb new -- --help
agentlb rr
agentlb last -- --search
agentlb status
agentlb supervisor
agentlb supervisor start --background
agentlb supervisor restart
agentlb supervisor stopYou can run a session by account email instead of alias:
agentlb new <email>How it works:
agentlbscans existing session directories under~/.agentlb/sessions.- It reads session auth metadata and extracts email.
- It matches your input email (case-insensitive) to existing sessions.
Outcomes:
- exactly one match: session runs
- no match: actionable error telling you to create/select alias
- multiple matches: actionable error listing matching aliases
Use agentlb status first when you want to discover alias/email/path mappings.
Path: ~/.agentlb/config.toml
[runner]
default_command = "codex"
default_command_args = []
login_command = "codex login"
[sessions]
alias_pattern = "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$"
assignment_history_window = 30
pick_behavior = "round_robin" # currently retained for compatibility
stale_sec = 420
busy_penalty = 5
unknown_usage_left_percent = 30
usage_primary_weight_percent = 60
usage_secondary_weight_percent = 40
restart_penalty_per_restart = 2
restart_penalty_cap = 20
staleness_penalty_max = 10Notes:
assignment_history_windowcontrols retained assignment timestamps per alias.pick_behavioris retained in config, butagentlb newnow uses status-based scoring.- The scoring factors above control how
agentlb newbalances short-window and weekly limits and how strongly it penalizes busy/restart/stale sessions.
-
stale_sec- What it does: excludes sessions whose rate-limit data is older than this many seconds.
- Increase it when: status updates are less frequent and you still want to use older data.
- Decrease it when: you want picks to rely only on very fresh usage info.
- Typical range:
300to900.
-
busy_penalty- What it does: subtracts
activeTurns * busy_penaltyfrom score. - Increase it when: you want to avoid sessions currently handling turns.
- Decrease it when: throughput matters more than spreading active work.
- Typical range:
2to10.
- What it does: subtracts
-
unknown_usage_left_percent- What it does: fallback usage-left value when both rate-limit windows are missing.
- Increase it when: you want unknown sessions treated as more usable.
- Decrease it when: you want unknown sessions deprioritized.
- Typical range:
10to50.
-
usage_primary_weight_percent- What it does: weight for short/current window remaining capacity in blended usage score.
- Increase it when: short-window (daily/current) pressure matters more.
- Decrease it when: weekly balancing should matter more.
-
usage_secondary_weight_percent- What it does: weight for weekly window remaining capacity in blended usage score.
- Increase it when: you want stronger week-level balancing across sessions.
- Decrease it when: short-window responsiveness is more important.
-
restart_penalty_per_restart- What it does: per-restart instability penalty before capping.
- Increase it when: unstable sessions should be avoided quickly.
- Decrease it when: occasional restarts are acceptable.
- Typical range:
1to5.
-
restart_penalty_cap- What it does: maximum total restart penalty applied.
- Increase it when: stability should heavily influence routing.
- Decrease it when: restart history should have limited impact.
- Typical range:
10to40.
-
staleness_penalty_max- What it does: max penalty as data age approaches
stale_sec. - Increase it when: near-stale data should be strongly deprioritized.
- Decrease it when: mild staleness should be tolerated.
- Typical range:
5to20.
- What it does: max penalty as data age approaches
- Start with defaults unless you already see poor balancing behavior.
- For stronger daily balancing:
- raise
usage_primary_weight_percent - lower
usage_secondary_weight_percent
- raise
- For stronger weekly balancing:
- raise
usage_secondary_weight_percent - lower
usage_primary_weight_percent
- raise
- Keep both usage weights positive; if both are set to
0, defaults are restored. - If picks feel too sticky to busy sessions:
- raise
busy_penalty
- raise
- If picks feel too noisy due to old data:
- lower
stale_secor raisestaleness_penalty_max
- lower
- If unstable sessions keep getting selected:
- raise
restart_penalty_per_restartand/orrestart_penalty_cap
- raise
~/.agentlb/
config.toml
supervisor.pid
status.json
state/
global.json
sessions/
<alias>.json
sessions/
<alias>/
locks/
state.lock
Permissions are private (0700 dirs, 0600 state/lock/status/pid files).
0success1runtime/config/state error2invalid CLI usage3alias not found (reserved)4no sessions for auto-pick5login command failed during alias creation
cargo testAGENTLB_SUPERVISOR_DISABLED=1: disable auto-supervisor startup (useful in tests)AGENTLB_DAEMON_START_TIMEOUT_MS: wait timeout for startup detectionAGENTLB_PROBE_INTERVAL_SEC: inactive-session probe intervalAGENTLB_PROBE_LIFETIME_SEC: max probe process lifetimeAGENTLB_STATUS_FLUSH_INTERVAL_SEC: status flush cadenceAGENTLB_MAX_RESTARTS_5M: crash-loop guard thresholdAGENTLB_PRE_STALE_REFRESH_SEC: how early (in seconds beforestale_sec) supervisor refreshes rate limits proactivelyAGENTLB_PRE_STALE_REFRESH_COOLDOWN_SEC: cooldown between proactive refresh attempts per session