Operate via CLI
Start with CLI: forge login if you have not set it up. This page is what comes after.
Point at the right box, on purpose
Section titled “Point at the right box, on purpose”forge instances # what is stored, and which is currentforge --instance staging read whoami --internalFORGE_URL=https://other.example forge read whoami --internalPrecedence: the flag beats the environment, which beats ~/.forge. On a shared machine or in CI, skip
login and use FORGE_URL + FORGE_TOKEN — nothing is written to disk and nothing is ambiguous.
Look before you write
Section titled “Look before you write”Every read is available, and the operator face is one flag away:
forge read orders_admin --internal --input '{"limit": 5}'forge read products --input '{"store": "sto_…", "limit": 5, "projection": "feed"}'--internal picks the operator face. Without it you get the public answer, which is a different (and
smaller) truth rather than an error.
forge catalog.product.publish --input '{"product_id": "prod_…"}'Names are the same everywhere. forge --help prints them all with scopes and summaries; each one’s
reference page carries the input schema.
Make retries safe
Section titled “Make retries safe”forge order.mark_paid \ --idempotency-key "settlement-2026-08-25-042" \ --input '{"order_id": "ord_…"}'Use a key derived from what you are doing, not a random value — a retry of the same intent has to carry the same key, or it is not idempotent.
Scripting it
Section titled “Scripting it”A refusal prints the code and exits non-zero; a success exits 0. So the ordinary shell idiom works:
if ! forge order.mark_paid --input "$payload" > result.json 2> error.json; then code=$(jq -r '.error.code' error.json) echo "refused: $code" >&2 exit 1fiDo not parse the human-readable message — branch on error.code. There are exactly six, and the set is
frozen: see errors and refusals.
What the CLI is not for
Section titled “What the CLI is not for”- The shopper journey. Carts and checkout live on an anonymous face;
forge --helplists those commands today but calling one answersunknown_command. See surfaces. - Platform commands. They need a platform credential and the control face, which is not exposed to the internet by design.
- Bulk data movement. Use the SDK — you will want the types and real error handling.