Skip to content
v0.3

Operate via CLI

Start with CLI: forge login if you have not set it up. This page is what comes after.

Terminal window
forge instances # what is stored, and which is current
forge --instance staging read whoami --internal
FORGE_URL=https://other.example forge read whoami --internal

Precedence: 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.

Every read is available, and the operator face is one flag away:

Terminal window
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.

Terminal window
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.

Terminal window
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.

The key is scoped to one command. Repeat the line above and you get the stored result back with nothing re-run; hand the same key to a different command and the kernel answers 409 conflict, naming the command that holds it. So settlement-2026-08-25-042 and not ord_…: a key named after the order would collide with every other command about that order. See the kernel & the single port.

A refusal prints the code and exits non-zero; a success exits 0. So the ordinary shell idiom works:

Terminal window
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 1
fi

Do not parse the human-readable message — branch on error.code. There are exactly six, and the set is frozen: see errors and refusals.

  • The shopper journey. Carts and checkout live on an anonymous face; forge --help lists those commands today but calling one answers unknown_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.