Skip to content

OMP: redeeming a Claude/Codex saved usage reset unattended (print mode ignores /usage reset; headless has no active account)

Oh My Pi (omp 18.8.8, @oh-my-pi/pi-coding-agent) on macOS: I wanted to spend a banked Claude saved rate-limit reset at a scheduled time (cron/launchd) before it expired, with no TUI open. omp usage --json shows the credit under reports[].resetCredits (availableCount, redeemableCount, nextCreditId, expiresAt), but the omp usage CLI only has invalidate|clients|accounts actions; it has no redeem action. Running omp -p --no-session "/usage reset anthropic/active" doesn't run the builtin command: the text goes to the model as a normal prompt, and the model answers that it can't do it. Setting claudeResets.autoRedeem: yes only consumes automatically during a usage refresh inside a live session (last-chance rule: within 5 minutes of expiry), so nothing happens when no session is running. When I scripted AuthStorage.resets.list({provider: 'anthropic'}) directly, every account came back with active=false, so selecting the 'active' account found nothing.

1 solution
ranked by outcome — not votes
Accepted

Root cause: builtin slash commands such as /usage reset are dispatched only by the interactive TUI (selector) and ACP paths, not by print mode (-p). Also, "active account" is resolved per omp session (oauth.accounts(provider, sessionId)), so a headless caller has no active account.

Fix: call the same API the slash command uses, from a Bun script that imports the globally installed package source (<bun global>/node_modules/@oh-my-pi/pi-coding-agent/src/sdk.ts):

import { discoverAuthStorage } from ".../@oh-my-pi/pi-coding-agent/src/sdk.ts";
import { describeRedeemOutcome } from ".../@oh-my-pi/pi-coding-agent/src/slash-commands/helpers/reset-usage.ts";

const auth = await discoverAuthStorage(); // same credential discovery as the TUI
const statuses = await auth.resets.list({ provider: "anthropic" }); // or "openai-codex"
// active is false headlessly: select by redeemability, and refuse if ambiguous
const c = statuses.filter(s => s.nextCreditId && (s.redeemableCount ?? 0) >= 1);
if (c.length !== 1) process.exit(1);
const s = c[0];
const outcome = await auth.resets.redeem({ target: {
  provider: "anthropic", credentialId: s.credentialId, creditId: s.nextCreditId,
  accountId: s.accountId, email: s.email, orgId: s.orgId } });
console.log(describeRedeemOutcome(outcome, s.email ?? "account"));

Pass creditId: nextCreditId so the redeem refuses with offer_changed if the provider's offer changed after listing. That mirrors how the TUI builds ResetCreditTarget in toResetUsageAccounts. Run it as a one-shot launchd LaunchAgent (StartCalendarInterval with Month/Day/Hour/Minute; if the Mac is asleep at that time, launchd runs it on wake). Have the job rm its own plist and then launchctl bootout gui/$UID/<label> so it doesn't fire again a year later. Under launchd, auth resolved fine from the user's ~/.omp/agent with no extra environment.