Skip to content

Actions ​

Actions are explicit one-shot operations: migrations, builds, tests, data seeding, or inspection commands. They are not represented as continuously running services.

Running the same service action twice, switching between its numbered results, and opening retained run history

Service actions ​

yaml
services:
  api:
    command: npm run dev
    dir: apps/api
    env_files: [.env]
    actions:
      migrate:
        command: npm run db:migrate
        description: Apply pending database migrations
        timeout: 2m
        confirm: true
      test:
        command: npm test
        timeout: 5m

Service actions inherit dir, shell, env, and env_files. Expand a service with Enter, focus an action, and press s. Output, exit code, and duration are retained separately from service logs.

Run the action again and both results remain independently addressable. [ and ] move through the target's retained runs, l returns to the latest, and v opens the full run history. The selected run keeps its own scroll and search position, so comparing two executions does not lose your place.

Typed parameters ​

Use parameters when several actions differ only by a target, count, flag, or environment value. One declaration becomes the source of truth for the TUI, CLI, MCP, and prerequisites:

yaml
actions:
  seed:
    params:
      environment:
        type: select
        options: [dev, staging, prod]
        default: dev
        arg: --environment
      count:
        type: number
        min: 1
        max: 10000
        default: 100
        arg: --count
      write:
        type: checkbox
        default: false
        flag: --write
        confirm: This writes data
    run: [./seed]

Editing typed action values in the TUI, reviewing the live argv preview, and running the confirmed invocation

Parameterized actions use an argument vector instead of shell interpolation. The runtime validates raw values, normalizes defaults, renders the preview and executable definition once, and binds confirmation to that exact result. An interactive parameterized action hands the same immutable argv to the terminal after confirmation; a reload cannot swap in a different command.

The CLI exposes the same schema and values without prompting:

bash
kranz actions info tools/seed
kranz actions run tools/seed \
  --param environment=staging \
  --param count=250 \
  --param write=true \
  --confirm

Inspecting accepted command parameters in the CLI and running one typed invocation

MCP reads the advisory JSON Schema from action_info and sends native values in action_run.params; the runtime repeats validation at execution. See the runnable action-parameters example and the configuration reference.

Project action groups ​

Use an action group when the operation does not belong to one service:

yaml
action_groups:
  infrastructure:
    description: Shared development infrastructure
    dir: infra
    actions:
      inspect:
        command: docker compose ps
      reset:
        command: docker compose down --volumes
        confirm: true

Groups can provide shared execution context. An action's own values override the inherited group values.

Running an action before a service starts ​

Some actions are not something you remember to run — they are a precondition. before_start declares that relationship:

yaml
services:
  api:
    command: npm run dev
    actions:
      migrate:
        command: npm run db:migrate
    before_start:
      - action: migrate
      - group: infrastructure
        action: up
        run: always

Each entry references an action that already exists, so the command keeps one definition and stays runnable on demand. Reference an action of the declaring service with action: alone, another service's action with service:, or a group's with group:.

Prerequisites run in declared order, after dependencies are ready and before the service starts:

Dependencies become ready, before-start actions complete, the service starts, and its readiness probe runs

run: once is the default and means one successful run per Kranz session, including across restarts — a migration is not re-applied every time you restart the service. run: always runs before every start, for checks that are cheap and whose answer can change.

If a prerequisite fails, the service stays stopped and its log names the action and the reason. Only success is remembered, so fixing the cause and starting again retries it. When two services reference the same prerequisite, whichever reaches it first runs it and the other waits for that same run.

Interactive actions cannot be prerequisites: they run unattended while a start is already in flight, so they cannot own the terminal.

See the prerequisites example for a runnable walkthrough.

Confirmation and cancellation ​

confirm: true requires a separate explicit approval before starting an action. In the CLI, review the confirmation_required plan and repeat the command with --confirm; MCP repeats the call with the returned confirmation_token. Both paths use the same plan-bound, one-shot supervisor token. Actions without this setting still run immediately. Stopping a running action always asks for confirmation regardless of its start setting. timeout covers the whole process group; cancellation sends a graceful signal and escalates when necessary.

Actions that ask a question ​

Some commands have to be answered: a migration that confirms before it writes, a REPL, a scaffolding wizard. interactive: true hands the real terminal to the command:

yaml
actions:
  migrate:
    command: npm run db:migrate
    interactive: true

Running one always asks first, whether or not it also sets confirm. The confirmation says plainly that Kranz is about to leave the screen, because handing the terminal over is not something that should happen to someone who just pressed a key in a list:

text
Run action "migrate"?

⚠ KRANZ WILL LEAVE THE SCREEN
OWNER  api

This action takes over your terminal so you can answer it.
Kranz returns as soon as the command exits.

[Enter/y] Hand over the terminal  [Esc/n] Cancel

Confirming the handoff, answering the command in the terminal, and returning to Kranz

After you accept, the command owns the terminal until it exits. Kranz then resumes and records the result — running, succeeded or failed, with the exit code and duration — exactly like a captured action. Because the output went to your terminal rather than into a buffer, the action's log pane says so instead of showing an empty capture.

Two limits follow from what handoff means:

  • lifecycle start, stop, and logs commands cannot be interactive; they run unattended, sometimes while Kranz is shutting down;
  • an interactive action cannot be a prerequisite, because prerequisites run while a start is already in flight.

confirm and interactive answer different questions. confirm is about whether the command should run at all — use it for anything destructive. interactive is about who owns the terminal while it runs. An interactive action already forces confirmation with handoff-specific wording, so adding confirm: true to it has no further effect.

Released under the MIT License.