Skip to main content
Two safety gates sit in front of certain ish commands: a confirmation gate (for credit-spending and destructive verbs) and a hard cap on how many participants one dispatch can carry. Both are client-side. This page is the complete reference for both. The gate logic lives in confirmDestructive and assumeYes (ish-cli/src/lib/command-helpers.ts); the cap is PARTICIPANT_BATCH_CAP.

The confirmation gate

A gated command asks for confirmation before it acts. There are two classes. Behavior depends on whether stdout is an interactive terminal.
  • Interactive TTY. The command prints a prompt and waits. Billable verbs also print a one-line credit estimate and a pointer to the credits reference above the prompt; they default to yes, because you already typed the billable command. Destructive verbs default to no.
  • --json or any non-TTY (piped stdout, CI, an agent). The command refuses rather than prompt or proceed silently. It exits 2 with a ConfirmationRequired error and a copy-pasteable example field showing the same command with --yes appended. See Refusal in non-interactive contexts.
Credits draw from your usage allowance, not a per-call bill. The gate exists for human review, not to discourage spending. See credits and limits for the cost model and run vs ask for what each verb dispatches.

Confirming a gated command

Pass -y (or --yes) to skip the prompt. Both flags are identical.
To opt in once for a whole session instead of repeating -y, set the ISH_ASSUME_YES environment variable. It mirrors -y exactly and applies to both billable and destructive gates.
flag
Skip the confirmation prompt for this one command. Required in --json or any non-TTY context for a gated command to proceed.
env
Truthy value (1, true, yes, or on, case-insensitive) pre-authorizes every gated command for the session. Mirrors -y. Session-scoped and never written to config, so it cannot silently pre-authorize a future run.
ISH_ASSUME_YES is read from the environment on every command and is never persisted. Unset it (or open a new shell) to restore the gate.

Gated commands

Billable (credit-spend)

These dispatch simulations and draw credits, so each one is gated as billable.
ish ask create --no-dispatch is the one exempt billable path. It creates the ask in draft and dispatches nothing, so it draws no credits and needs no confirmation. Start the draft later with ish ask dispatch <id>, which is gated.

Destructive

These delete or revoke and cannot be undone, so each is gated as destructive.

Refusal in non-interactive contexts

When a gated command runs under --json or any non-TTY and you have not passed -y or set ISH_ASSUME_YES, the CLI refuses. This is the agent and CI default. It is a usage error, not a fault, so it exits 2 with no “report a bug” nudge. See exit codes for the full table. The refusal message differs by class. Billable verbs reframe around spending and point at ISH_ASSUME_YES; destructive verbs keep firmer fail-closed wording.
An agent that hits this can read example and re-run it verbatim, or set ISH_ASSUME_YES=1 once at the start of the session to pre-authorize every gated command.

The 20-participant dispatch cap

The backend caps each dispatch at 20 participants. The CLI enforces this client-side so an over-cap selection fails with a clear message instead of an opaque backend validation_error after a wasted round-trip. PARTICIPANT_BATCH_CAP is 20. It applies to the person-selection flags shared by study run and ask commands. See people for how selection works and what each flag matches. The cap fires in two places.
  • --sample N over the cap. Caught before any API call, since the value alone is over the limit.
  • --all or filter flags resolving to more than 20. Caught after the pool is fetched, when the match count exceeds the cap. --all is only safe when the matching pool is 20 or fewer.
Both refusals are usage errors and exit 2. To run a cohort larger than 20, split it into slices and dispatch each slice separately. --sample 20 randomly subsamples a larger matching pool; narrower filters select a different slice each time.
Explicit --person <id> selection is also subject to the backend cap. Passing more than 20 IDs reaches the backend and returns its validation_error. Keep explicit selections to 20 or fewer per dispatch.

The MCP server

The MCP server has no -y equivalent. Confirming a credit draw is the calling agent’s job, not ish’s: a dispatch tool runs when called. The advice in the server instructions is to check pool headroom with workspace_get (.credits) before a large run, rather than gate each dispatch behind a prompt. See tool conventions. The 20-participant cap is a backend constraint, so it applies to MCP dispatches too. The MCP simulation tools and ask tools surface an over-cap selection as a backend validation error.