> For the complete documentation index, see [llms.txt](https://cyr1en.gitbook.io/commandprompter/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cyr1en.gitbook.io/commandprompter/features/command-flows.md).

# Command Flows

CommandPrompter 3.3.0 executes a prompted command as a staged flow:

1. Collect local prompt answers.
2. Evaluate any pre-dispatch approval gates.
3. Dispatch the assembled primary command once.
4. Run completion or cancellation post-actions in source order.

If a gate is denied, times out, or cannot resolve safely, the primary command does not run. Delayed post-actions are in memory only and are dropped when the plugin or server shuts down.

## Approval gates

An approval gate asks a resolved second player for consent after local answers have been collected. Define the trusted target, message, and optional denial action in `presets.json`:

```json
{
  "prompts": [],
  "post_commands": [],
  "approval_gates": [
    {
      "id": "trade_confirm",
      "target": "{0}",
      "message": "{player} wants to trade with you. Accept?",
      "timeout": 30,
      "self_approval_policy": "auto_approve",
      "on_deny": {
        "command": "tell {player} The trade request was declined.",
        "execute_as": "player",
        "delay_ticks": 0
      }
    }
  ],
  "conditional_post_commands": []
}
```

Reference the gate after the prompts that produce its target:

```
/trade <p:Choose a player> <i:Choose an item> <!gate:@trade_confirm>
```

`target` and `message` use zero-based answer references (`{0}`, `{1}`, ...) plus `{player}` for the initiator. The target must resolve to one online player by exact name or UUID. Approval is presented in chat with single-use Accept and Decline actions bound to that target.

| Field                  | Values                            | Notes                                                  |
| ---------------------- | --------------------------------- | ------------------------------------------------------ |
| `id`                   | `^[a-z0-9_.-]{1,64}$`             | IDs are lowercase and unique across every preset kind. |
| `target`               | Template                          | Required player name/UUID expression.                  |
| `message`              | Template                          | Required text shown to the target.                     |
| `timeout`              | 1–3600 seconds                    | Defaults to 30.                                        |
| `self_approval_policy` | `auto_approve`, `require_confirm` | Defaults to `auto_approve`.                            |
| `on_deny`              | Trusted action                    | Optional; `delay_ticks` must be 0.                     |

Only the canonical `<!gate:@id>` form is accepted. Inline target, message, delay, executor, and denial-command forms are rejected so a player cannot author a privileged gate from a command string. A target disconnect acts as denial and may run `on_deny`; an initiator disconnect discards the flow without running `on_deny`.

{% hint style="info" %}
A local [Confirmation Prompt](/commandprompter/prompts/confirmation-prompt.md) asks the initiator during input collection. An approval gate asks the configured target immediately before primary dispatch.
{% endhint %}

## Conditional post-commands

Conditional post-commands choose a trusted action branch after completion or cancellation. Define them in `conditional_post_commands` and reference them with the normal post-command preset form `<!@id>`:

```json
{
  "id": "large_payment_audit",
  "condition": "{1} >= 500",
  "execution_policy": "on_complete",
  "if_true": {
    "command": "broadcast {player} sent a large payment of {1}",
    "execute_as": "console",
    "delay_ticks": 0
  },
  "if_false": {
    "command": "tell {player} Payment recorded.",
    "execute_as": "player",
    "delay_ticks": 0
  }
}
```

```
/pay <p:Recipient> <d:num[1,10000]:Amount> <!@large_payment_audit>
```

At least one of `if_true` or `if_false` is required. A missing branch is a no-op when that result is selected. Branch actions accept `command`, `execute_as`, and `delay_ticks` from 0 through 72000 ticks.

Conditions support:

| Kind    | Operators                                      |
| ------- | ---------------------------------------------- |
| Numeric | `==`, `!=`, `<`, `<=`, `>`, `>=`               |
| String  | `equals`, `contains`, `startsWith`, `endsWith` |
| Boolean | `&&`, \`                                       |

Answers use zero-based references. Quoted string literals support `\"` and `\\`. Trusted preset conditions may also use bounded PlaceholderAPI references such as `%vault_eco_balance%`; inline `-breakIf` conditions may not.

```json
"condition": "{0} equals \"confirm\" && %player_level% >= 10"
```

Malformed expressions, missing answer references, missing PlaceholderAPI values, or exceeded evaluation bounds fail closed instead of selecting a branch by default.

## Post-action transformers

Post-command and trusted action templates can transform one answer during substitution:

| Transformer      | Example                 | Result for sample input                        |
| ---------------- | ----------------------- | ---------------------------------------------- |
| `upper`          | `{0:upper}`             | `SWORD` from `sword`                           |
| `lower`          | `{0:lower}`             | `sword` from `SWORD`                           |
| `capitalize`     | `{0:capitalize}`        | `Sword` from `sWORD`                           |
| `trim`           | `{0:trim}`              | Removes leading/trailing whitespace.           |
| `stripcolor`     | `{0:stripcolor}`        | Removes legacy color codes.                    |
| `default="text"` | `{0:default="unknown"}` | Uses the default for a blank or missing value. |
| `math(...)`      | `{1:math(*1.5)}`        | `30.00` from `20`.                             |
| `round`          | `{1:round}`             | Rounds to a whole number.                      |

Preset aliases remain available: `{input}` and `{input:1}` refer to the first answer, so `{input:1:upper}` is equivalent to `{0:upper}`. `{player}` inserts the initiator's name. Transformers are single-pass and cannot be chained.

Math uses bounded decimal arithmetic: at most 8 operations, 64 characters in the expression, 4 decimal places, and an absolute result no larger than 10^12. Results use plain decimal notation with at least two decimal places. Invalid numeric input or exceeded bounds fails the action. Division by zero in a normal post-action produces `0` and records a diagnostic.

PlaceholderAPI expansions are supported only in trusted preset actions, are length-bounded, and are inserted as data. Inline post-actions do not expand PlaceholderAPI values.

## Early termination with `-breakIf`

Attach `-breakIf:<condition>` to a prompt to stop the flow immediately after that answer when the condition is true:

```
/report <p:Player> <Reason -breakIf:{1} equals "skip"> <!!tell {player} Report cancelled>
```

The candidate answer is available at its normal zero-based position, alongside answers already collected. A true result cancels manually, prevents primary dispatch, and runs cancellation post-actions. A false result continues to the next prompt. An invalid or unresolvable condition cancels with an error.

`-breakIf` is intended for answer-only checks. PlaceholderAPI references are rejected in inline conditions; use a conditional post-command for trusted PAPI logic.

## Reload and snapshot behavior

Every flow captures an immutable snapshot of its referenced presets. Reload validates `presets.json`, `item-catalogs.yml`, and configuration before publishing them together. If any candidate fails, the previous validated state remains active; partially parsed definitions are never served.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://cyr1en.gitbook.io/commandprompter/features/command-flows.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
