Skip to content
OpenLimiter Pro is here. Everything you can see is free. Alerts, history, phone access, extra accounts and spend tracking above $100 are Pro.

Configuration

OpenLimiter keeps everything in one state directory under your own user account: a configuration file, a cache, a lock, and the optional manual document. This page says where that is and what each file does.

The state directory

Where the state directory lives on each platform
platformpath
Windows%LOCALAPPDATA%\openlimiter
macOS~/Library/Application Support/openlimiter
Linux${XDG_STATE_HOME:-~/.local/state}/openlimiter

The directory is created with restrictive permissions where the platform supports them. A path that turns out to be a symbolic link is rejected rather than followed.

What lives in it

Files inside the state directory
filerole
openlimiter-config.jsonWritten by openlimiter init. Records the connector list, whether each one was detected, and the statusline layout.
openlimiter-cache.jsonThe one cache every command reads and every writer merges into.
openlimiter.lockHeld by writers only. Readers never take it.
manual.jsonOptional. Quota you maintain by hand. See ingestion for the shape.

How the cache behaves

  • One schema, one file, one lock. There are no competing state files to reconcile.
  • Readers never take the lock. A reader opens the file, validates that open descriptor, and reads through it, so a path swapped after the check cannot redirect the bytes.
  • Writers take the lock, and the read, the merge, and the write all happen inside it. A lock older than five seconds is treated as abandoned and reclaimed.
  • Every replacement flushes to stable storage before the rename, so a reader observes either the previous content or the new content and never a partial file.

Cache health is visible at any time through openlimiter doctor, which prints the cache status and how many rows were dropped for failing validation.

The statusline layout

The default statusline draws bars for one connected host at a time, in the ten block grammar the agent context page documents. Nine keys in the configuration file decide how a row is built, and openlimiter config is how they are read and changed.

captured 10 August 2026, synthetic fixtures
NO_COLOR=1 node packages/cli/dist/bin.js statusline
OpenLimiter NEAR_CAP PREFER ANTIGRAVITY  CLAUDE ###.. 64.0%  CODEX ####. 84.0%  ANTIGRAVITY #.... 28.0%  OPENCODE ####. 92.0%
MANUAL #.... 35.0%  OPENROUTER ###.. 62.3%

Every key

The statusline keys and what each one accepts
keyacceptsmeaning
orderprovider ids, comma separated, or NONEThe order the cells appear in. Whatever you list comes first; every provider you leave out follows the built in order behind it, which is the subscription plans and then the credit and API meters. NONE is the way back to that built in order. Default NONE.
metersworst or allA provider with several meters shows the one closest to its cap, or all of them as separate cells named PROVIDER:METER. Meters order session, daily, weekly, monthly, credits. Default worst.
widtha whole number from 40 to 400The columns one row may spend before the line stacks. Nothing measures your terminal: a statusline host runs the command with no terminal attached, so the number here is the number honoured. Default 140.
rows1 or 2How many rows the layout may use. Default 2.
barstrue or falseFalse restores the single plain line from 0.1.0, byte for byte. Default true.
colorauto, always, or neverauto follows the terminal, which for a statusline host usually means no colour, because the host captures the output rather than handing the command a terminal. always is how you say the host understands escape codes. Default auto.
stylebar or cellsbar is the ten block grammar openlimiter terminal wires by default. cells restores the previous reason led row with a five block bar per provider. Default bar.
showprovider ids, comma separated, or NONEWhich connected providers actually draw a bar in bar style. NONE, the default, shows every connected provider. openlimiter terminal show and terminal hide are the commands that change it.
hostswritten by openlimiter terminal, not by handWhich command each wired host was left running before OpenLimiter took the slot, kept so terminal uninstall can restore it byte for byte.

Reading and writing them

captured 10 August 2026
openlimiter config get statusline
statusline.order=NONE
statusline.meters=worst
statusline.width=140
statusline.rows=2
statusline.bars=true
statusline.color=auto

One key at a time, validated before it is written. A value the key cannot use exits 2 and names what it wanted, and nothing partial is written, because the whole document is replaced atomically. Statusline keys are the only thing this command mutates: the connector list belongs to openlimiter init, and any other key exits 2.

openlimiter config set statusline.order codex,claude
statusline.order=codex,claude

openlimiter config set statusline.meters all
statusline.meters=all

openlimiter config set statusline.width 12
openlimiter config: statusline.width must be a whole number from 40 to 400.

openlimiter config set statusline.theme dark
openlimiter config: unknown statusline key. Known keys: order, meters, width, rows, bars, color.

Re running openlimiter init keeps whatever is configured here and only redetects the connectors. A statusline key this version cannot read falls back to its default rather than stopping the draw, so a hand edited typo in one field never costs you the other five.

When the row runs out of room

The line stacks instead of truncating. A break lands between two cells and never inside one, and two rows is the ceiling. Past that the providers closest to their caps are the ones kept, and the last row ends by saying how many it could not show.

captured 10 August 2026, synthetic fixtures
openlimiter config set statusline.rows 1 && NO_COLOR=1 node packages/cli/dist/bin.js statusline
OpenLimiter NEAR_CAP PREFER ANTIGRAVITY  CODEX ####. 84.0%  OPENCODE ####. 92.0%  +4 more

The 0.1.0 line, on request

The format before this layout was one plain line with no bars. If you wrote a script against it, bars false returns it exactly, and a test pins that exact string so it cannot drift.

captured 10 August 2026, synthetic fixtures
openlimiter config set statusline.bars false && node packages/cli/dist/bin.js statusline
OpenLimiter NEAR_CAP CLAUDE 64.0% OPENROUTER 62.3% CODEX 84.0% ANTIGRAVITY 28.0% OPENCODE 92.0% MANUAL 35.0% PREFER ANTIGRAVITY

Claude Code settings

Use the absolute path to your clone. Forward slashes work on every platform, including Windows.

settings.json
{
  "statusLine": {
    "type": "command",
    "command": "node /absolute/path/to/openlimiter/packages/cli/dist/bin.js statusline"
  },
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "node /absolute/path/to/openlimiter/packages/cli/dist/bin.js hook"
          }
        ]
      }
    ]
  }
}

Which of the two writes

Only the statusline. It is the path that receives the session payload, so it is the path that updates the cache. The hook reads and never writes.

Credentials

The credential library call sits behind an interface, and the adapter is stubbed in this release, so openlimiter init cannot store a key until a driver is supplied. Nothing else on your machine is touched.

Connector detection

Detection is a pure function of the environment the CLI hands a connector. Facts only the CLI can observe, such as a manual document sitting in the state directory, arrive as explicit markers, which is why openlimiter doctor never claims a connector is ready when it could not receive data.

terminal
openlimiter doctor
CONNECTOR DETECTED FRESHNESS DRIFT
claude no unknown UNVERIFIED
openrouter no unknown UNVERIFIED
codex no unknown UNVERIFIED
antigravity no unknown UNVERIFIED
opencode no unknown UNVERIFIED
manual yes fresh UNVERIFIED
CACHE ok DROPPED 0

A cache that would not parse, or one that parsed with rows thrown out, adds one more line in red saying so. It reports against the cache rather than against a provider, because a corrupt file cannot be trusted to say whose reading it held.