ledger CLI keeps your catalog in your repository, as ledger.config.ts or ledger.catalog.json. You change pricing by editing the file, review the change in a pull request, and publish it with ledger push. Setup walks through the first run.
Install it with npm install --save-dev integrateledger-cli and run npx ledger, or run npx integrateledger-cli without installing. It needs Node 22.18 or later, or Bun.
The config file
ledger.config.ts
- The fields are the API’s, as on Catalog.
defineCatalog,plan,featureandcreditPackonly add types. - The file holds the whole catalog. Items you remove from it are archived when you push.
- There’s no
environment: the API key chooses it, so one file serves Sandbox and Live. ledger.catalog.jsonholds the same catalog in thePOST /v1/catalogbody’s shape, where packs areaddOns. It’s what the onboarding skill writes, and the default for projects without apackage.json. If it names anenvironment, the key must match it.
What a push changes
Pushing an unchanged file changes nothing and retries any Stripe sync that hasn’t finished. In CI, run
ledger diff --exit-code on pull requests and ledger push --live --yes after merge, as in Deploy.
Commands
Flags
API keys
The key’s prefix is its environment:ledger_test_ for Sandbox, ledger_live_ for Live. The CLI uses the first key for the selected environment from:
LEDGER_API_KEY.ledger/credentials.json(fromledger login)LEDGER_API_KEYin.env.local, then.env
--live. The key needs the catalog:read and catalog:write actions, and for migrate also customers:read, customers:write and billing:write. The CLI never prints it.
Exit codes
JSON output
With--json, diff prints:
kindisplan,featureorcredit_pack;actionisadd,updateorarchive.- Effect codes:
new_plan_version,stripe_product_and_price,stripe_price,stripe_overage_product,stripe_none,subscribers_keep_plan,in_place,purchase_pending_risk,archived. pushadds the API’schangedandstripeSync(synced,pending,failed,awaiting_connection).pullprints{ environment, organizationId, path, counts, wrote };initprints{ path, format, source, environment, counts, skills }withsourceworkspaceortemplate;skillsprints{ skills, linkCommand }, each skill with{ name, path, status }andstatuswritten,updatedorunchanged.- Errors print
{ "error": { "code", "message", "issues"? } }, whereissueslists{ path, message }with paths likeplans.1.monthlyPriceCents. Codes includeinvalid_config,no_api_key,confirmation_required,local_changes,config_not_found,unauthorizedandpurchase_pending.