04 — Amp usage API
Documents Amp quota endpoints, credit balances, authentication paths, plan labels, and reset semantics.
Summary
Amp exposes its current quota and balance as server-authored display text, so parsing must preserve the reported cadence without inventing reset precision.
Question and scope
(1) Which official Amp API endpoint(s) expose usage/quota — the "Amp Free" window, percent left, reset info? (2) Which endpoint(s) expose credit balances, both individual and workspace/team, and under which field names? (3) What auth does the usage surface take, and where do credentials live on disk (location/type only)? (4) Is the plan label ("Amp Free" vs paid) an API field or client-side inference? (5) Which display elements have no direct API source and need client-side computation?
This chapter informs jackin-desktop.
Method
Verification cutoff: 2026-07-24
Method: web + codebase cross-reference. Primary artifact analyzed: the official Amp CLI binary @ampcode/cli v0.0.1784824164-g9bdb69 (npm latest on 2026-07-24), platform package @ampcode/cli-darwin-arm64, strings extracted from the shipped package/amp executable. Minified identifiers below (I5R, h1T, …) are quoted verbatim from that bundle. Clean-room note: CodexBar/OpenUsage source was not read; no endpoints were taken from them. No embedded instructions were encountered in any fetched page; all fetched content was treated as data.
Findings
Current evidence
Chapter 11 verifies the current Amp Free cadence and line shape from a redacted live amp usage capture:
- current Amp Free is
N% remaining today (resets daily); Workspace <name>: $N remainingcan occur in the sameuserDisplayBalanceInfo.displayText;- the daily line has no exact reset timestamp;
- daily is proven only for Amp Free; paid subscription
displayTextremains uncaptured.
Detailed findings
1. Endpoint(s) exposing usage/quota (Amp Free window, percent left, reset)
- There is exactly one usage/balance API call in the official Amp CLI: the internal JSON-RPC method
userDisplayBalanceInfo, sent asPOST {AMP_URL}/api/internal?userDisplayBalanceInfowith body{"method":"userDisplayBalanceInfo","params":{}}. The generic client builds every internal call asJSON.stringify({method:R,params:h})posted to"/api/internal?"+encodeURIComponent(R)withContent-Type: application/json(gzip +Content-Encoding: gzipwhen the body is large) — extracted from theh1Tproxy function in the@ampcode/clibinary, https://registry.npmjs.org/@ampcode/cli-darwin-arm64/-/cli-darwin-arm64-0.0.1784824164-g9bdb69.tgz (confidence: HIGH) - The
amp usagesubcommand ("Show your current Amp usage and credit balance") is a thin wrapper:H0.userDisplayBalanceInfo({},{config:t})then printsc.result.displayText— functionQh0in the same binary (confidence: HIGH) - Response envelope is
{ok:boolean, result:{...}, error?:{code,message}}; the CLI checksc.ok,c.error.code==="auth-required", then readsc.result.displayText—Qh0in the binary; matches theresult-unwrapping incrates/jackin-usage/src/usage/amp.rs:140(confidence: HIGH) - The declared response schema for
userDisplayBalanceInfois[K.object({}), I5R]whereI5R=K.object({displayText:K.string()})— the entire usage payload is ONE server-rendered text string. No structured fields for remaining, limit, percent, or reset exist in the API response — RPC schema map in the binary (confidence: HIGH) - The CLI's renderer proves the text's shape: it splits
displayTexton newlines, treats everything before the first:as a bold label, and tokenizes content with the regex(\+?\$[\d,.]+(?:\/\$[\d,.]+)?(?:\/hour)?)|(\busage paid\b|\bpaid\b)|(\s-\s(?=https?:\/\/))|((https?:\/\/)[^\s]+)|([^$\s][^\s]*)— i.e. the server text carries$remaining/$limitpairs,$X/hourreplenishment rates, "paid" markers, and URLs — functionsUh0/e3T/Bh0in the binary (confidence: HIGH) - Current Amp Free text reports
N% remaining today (resets daily)without an exact reset timestamp. Preserve that cadence and do not infer hourly replenishment or midnight — chapter 11 (confidence: HIGH). - Default server URL is
https://ampcode.com(hidden settings keyurl, "The Amp server URL to connect to"), overridable via theAMP_URLenv var — settings-schema and env-help strings in the binary (confidence: HIGH) - Docs corroborate the CLI as the only documented programmatic surface: "check your balance in user settings or workspace settings, or by running
amp usage" — https://ampcode.com/manual (confidence: HIGH) - jackin❯ already calls exactly this endpoint with the same body —
crates/jackin-usage/src/usage/amp.rs:214-243— and falls back to parsingamp --no-color usageoutput —crates/jackin-usage/src/usage/amp.rs:339-343(confidence: HIGH)
2. Credit balances — individual AND workspace/team
- Individual credits reach clients only as prose inside
displayText(an "Individual credits: $N"-shaped line). The literal strings "Individual credits", "Amp Free", and "Signed in as" occur zero times in the CLI binary, so those labels are generated server-side; jackin❯ parser targets them atcrates/jackin-usage/src/usage/amp.rs:345-372(confidence: HIGH for server-side origin; MED that the current server text still uses those exact labels — label wording is unversioned server output) - No separate workspace/team balance RPC exists in the CLI. The full
internal-RPC method map contains no workspace-balance method; however,
chapter 11's live current
amp usagecapture proves workspace balances can arrive as prose lines inside the existinguserDisplayBalanceInfo.displayText(confidence: HIGH). - Workspace credits exist as a product concept: "Workspace credits are pooled and shared by all workspace members. Workspace admins … purchase credits for the pool"; balance is checked "in user settings or workspace settings" (web pages) — https://ampcode.com/manual (confidence: HIGH)
- The only structured numeric credit fields in the whole CLI API schema are sandbox(orb)-credit gates:
reconcileSandboxUsage→{remainingCredits:number}andcanConsumeSandboxCredits(params{minimumBalanceCredits?:number}) →{canConsume:boolean, remainingCredits:number, details?}— RPC schema map in the binary. WhetherremainingCreditsreflects the individual or pooled workspace balance is not stated in the schema (confidence: HIGH for existence/field names) getUserInfo— the other candidate — is declared[K.object({}), K.any()](untyped) in the CLI, so no balance/plan fields can be confirmed from the binary (confidence: HIGH that it is untyped client-side; response contents unknown)- The speculative structured keys jackin❯ probes as fallbacks (
ampFreeRemaining,freeRemaining,remainingBalance,ampFreeLimit,hourlyReplenishment,individualCredits,individualBalance—crates/jackin-usage/src/usage/amp.rs:150-159) have no counterpart in the CLI's declared schemas; the only real key isdisplayText(confidence: HIGH) - Per-user spending limits ("entitlements", e.g. "$50/week for regular users") exist for Amp Enterprise Premium workspaces, configured in the workspace settings web page; no API is documented — https://ampcode.com/news/workspace-entitlements (confidence: HIGH for the feature; no API surface found)
3. Auth and credential storage (location/type only)
- Auth is a bearer token: every internal API request sends
Authorization: Bearer <apiKey>where the key is resolved per server URL viagetToken("apiKey", url)— request-builder strings in the binary (confidence: HIGH) - Env var:
AMP_API_KEY— "Access token for Amp (see https://ampcode.com/settings/security#access-token)" — env-help string in the binary; also documented at https://ampcode.com/manual (confidence: HIGH) - On-disk file store:
<dataDir>/secrets.jsonwheredataDirdefaults to$XDG_DATA_HOME/ampfalling back to~/.local/share/amp(one bundled module additionally forces~/.local/shareon darwin/win32 regardless ofXDG_DATA_HOME). Keys are"${kind}@${normalizedServerURL}"with secret kinds["apiKey","mcp-oauth-client-secret","mcp-oauth-token"]— i.e. anapiKey@https://ampcode.com/-style JSON key — path/keying logic in the binary (constant"secrets.json",BvT, key template`${r}@${l}`, kind listD1T) (confidence: HIGH) - Alternate backend: OS-native keychain (getPassword/setPassword credential store) gated by the settings flag
experimental.cli.nativeSecretsStorage.enabled; when enabled, secrets live in the OS credential store instead ofsecrets.json—QvTin the binary (confidence: HIGH) - Non-secret settings live at
$XDG_CONFIG_HOME/amp/settings.json(default~/.config/amp/settings.json), overridable viaAMP_SETTINGS_FILE— binary path constants; corroborated by https://github.com/sourcegraph/amp-examples-and-guides/blob/main/guides/cli/README.md (confidence: HIGH) - jackin❯ cross-reference: resolution order env
AMP_API_KEY→~/.local/share/amp/secrets.json(scanningapiKey@-prefixed keys) → container handoff path —crates/jackin-usage/src/usage/amp.rs:16-34,crates/jackin-usage/src/usage/amp.rs:245-266, handoff constant atcrates/jackin-usage/src/usage.rs:184. This matches the CLI's real storage format (confidence: HIGH)
4. Plan label source ("Amp Free" vs paid)
- There is no structured plan field in any CLI-visible API response; the only usage payload is
displayText:string. Any "Amp Free" wording a client shows either comes from the server's prose or is client-side inference — RPC schema map + zero occurrences of "Amp Free" in the binary (confidence: HIGH) - jackin❯ currently hardcodes the plan label client-side:
plan_label: … "Amp Free"whenever any usage was fetched —crates/jackin-usage/src/usage/amp.rs:99(confidence: HIGH) - Amp offers Megawatt and Gigawatt paid subscriptions plus linked-ChatGPT-subscription usage — https://ampcode.com/news/subscriptions. How these plans appear in
displayTextis unverified (confidence: HIGH for the plans existing; LOW for any specificdisplayTextrepresentation).
5. Display elements with NO direct API source (client-side computation required)
- Percent left: current server text directly supplies the remaining
percentage in its daily Amp Free line; the API still exposes it only
inside prose, not as a structured JSON field. Clamp the parsed value and
derive used geometry as
100 − remaining— chapter 11 (confidence: HIGH). - Reset: current server text supplies only
"resets daily", with no exact timestamp. Preserve that cadence verbatim; do not derive the retired hourly countdown or fabricate midnight — chapter 11 (confidence: HIGH). - Used percentage: derived as
100 − remaining; no dollar used/limit pair is present in the current daily line (confidence: HIGH). - Plan label: client-side (see §4) (confidence: HIGH)
- Account identity: only available by parsing the server's "Signed in as …" prose line ("Signed in as" absent from the binary → server text) — jackin❯ parses it at
crates/jackin-usage/src/usage/amp.rs:348-350; alternative structured source would begetUserInfo, which isK.any()-untyped (confidence: HIGH) - In short: every numeric or semantic element (amounts, percent, reset, plan, identity) requires client-side parsing of one prose string; the API contributes structure only via the
{ok,result:{displayText},error}envelope (confidence: HIGH)
Dead ends and contradictions
- Official Amp CLI source repositories are not public:
github.com/sourcegraph/ampandgithub.com/ampcode/cliboth return HTTP 404 via the GitHub API (checked 2026-07-24). The npm-shipped binary is the closest primary artifact; findings above come from strings in that binary, not from a readable repo. @sourcegraph/ampis a compatibility alias for@ampcode/cli; the executable comes from the latter's native package — package README/manifest in https://registry.npmjs.org/@sourcegraph/amp and https://ampcode.com/news/npm-package-changes.- The public fixture proves only
"Resets daily"; it does not authorize an exact midnight timestamp. - The "replenish" strings inside the binary are MCP-server restart logic, not billing — ruled out as quota evidence.
- No REST-style documented usage endpoint exists in https://ampcode.com/manual or the examples-and-guides repo; the manual points only at
amp usageand the settings web pages. - jackin❯ structured-key fallbacks (
ampFreeRemaining,individualCredits, …,crates/jackin-usage/src/usage/amp.rs:150-159) match nothing in the CLI's declared schemas — dead weight against the current API, kept alive only as defensive parsing. threadDisplayCostInfo({totalCostUSD, costBreakdown:{freeUSD,paidUSD}, costBreakdownURL, usedModelProviderKey, …}) is per-thread cost, not quota — noted for completeness and out of scope for jackin❯ usage surfaces (limits-only rule).- No embedded instructions were found in any fetched web content or the binary strings examined.
Implications for jackin❯
Prefer the current Amp RPC or CLI output as evidence, preserve percentage-without-timestamp semantics, and avoid fabricating exact daily reset anchors.
Limitations and unknowns
- Exact paid-subscription
displayText— Megawatt/Gigawatt included usage, linked-ChatGPT/X allowances, and paid-only accounts — remains uncaptured. The current Amp Free daily and workspace-balance line shapes are resolved by chapter 11. - Whether the ampcode.com web app's user/workspace settings pages fetch a structured workspace-balance JSON from separate (non-CLI) endpoints. Needs an operator-authenticated browser session inspecting network traffic on
ampcode.com/settingsand the workspace settings page. getUserInforesponse contents (declaredK.any()in the CLI) — may carry plan/workspace identifiers usable as a structured plan-label source. Needs authenticated capture.- Whether
canConsumeSandboxCredits/reconcileSandboxUsageremainingCreditsreflects the individual balance, the pooled workspace balance, or a sandbox-specific bucket — schema is silent; needs authenticated observation. - Any API surface for Enterprise Premium "entitlements" (per-user quota remaining/used) — nothing documented; needs authenticated workspace-admin session.
- Whether the paused-signup ("full") state or subscription plans changed the
auth-required/error codes or added new RPC error variants relevant to usage polling — onlyauth-requiredis visible in the binary's usage path.