Ingestion
Three paths put quota data in front of OpenLimiter. All three are offline. None of them reaches the network, and until one of them runs, every command honestly reports unknown.
1. The Claude Code statusline payload
This is the path that needs no extra work once Claude Code is wired up. Claude Code runs your statusline command on every render and writes a JSON object describing the current session to that command's standard input. When that object carries a rate limit block, openlimiter statusline validates it, writes it to the cache, and renders the fresh numbers in the same call.
{
"rate_limits": {
"five_hour": { "utilization": 87.5, "resets_at": "2026-08-09T13:11:01.351Z" },
"seven_day": { "utilization": 41.25, "resets_at": "2026-08-15T12:11:01.351Z" }
}
}Anything else in the session object is ignored. A window that fails validation is dropped and the other window still counts.
2. A manual document on disk
Write manual.json inside the state directory and every command picks it up. See configuration for where that directory lives on each platform.
{
"version": 1,
"meters": [
{ "name": "MONTHLY", "used_percent": 61.5, "reset_at": "2026-08-29T12:11:29.714Z" }
]
}The rules each row must satisfy
nameis one uppercase identifier of up to 32 characters, starting with a letter.used_percentis a number from 0 to 100.reset_atis an ISO instant in the future.- Up to ten meters are read. Rows past the tenth are ignored.
- A row that breaks any of those rules is dropped, and the remaining rows still count. Nothing is repaired.
Run openlimiter snapshot --refresh to fold the file into the cache.
3. The generic ingest command
Any script or agent can hand OpenLimiter a document without a provider integration. The command reads standard input, or an inline document passed with --payload.
echo '{"meters":[{"name":"AGENT_BUDGET","used_percent":12.5,"reset_at":"2026-08-09T13:11:30.141Z"}]}' | openlimiter ingest
openlimiter ingest --payload '{"meters":[{"name":"AGENT_BUDGET","used_percent":12.5,"reset_at":"2026-08-09T13:11:30.141Z"}]}'Without a provider flag the document is treated as a manual document, so the resulting snapshot is labelled with manual precision. With --provider <id> the document is handed to that connector's own parser and keeps that connector's labels.
openlimiter ingest --provider codex --payload '{"rate_limits":{"primary_window":{"used_percent":33,"reset_at":"2026-08-09T14:11:30.264Z"}}}'Valid provider ids are claude, openrouter, codex, antigravity, opencode, and manual. An unknown id is a usage error and exits 2.
What happens to the data
Ingested rows merge into one cache under the same lock every other writer uses, so nothing already cached is lost and two writers observing different providers cannot silently drop each other's rows.
- Values are validated against the snapshot schema before anything is written.
- Percentages stay between 0 and 100. A value outside that range is not clamped, it is dropped.
- Every write lands through an atomic replacement, so a reader observes either the previous content or the new content and never a partial file.
- Freshness is derived from when a reading was observed and when it expires, so stale data is labelled rather than silently reused as current.
Nothing survives validation? The command reports that no bounded meter survived and exits with a failure, rather than writing a placeholder.