Skip to content

Latest commit

 

History

History
365 lines (260 loc) · 13.7 KB

File metadata and controls

365 lines (260 loc) · 13.7 KB

booth message

Send interactive messages and toast notifications to users inside a running booth.

booth message lets you communicate with users inside running booths — show dialogs that require a response, or fire-and-forget toast notifications that auto-dismiss. It uses the booth UI overlay to render messages on top of the booth's web UI.

# Ask a yes/no question (blocks until user responds)
booth message send --name my-booth --title "Deploy?" --body "Deploy to staging?" --type yes-no

# Show a toast notification (returns immediately)
booth message send --name my-booth --title "Build done" --body "Build completed successfully." --type toast

Back to README


Table of Contents


Overview

Booth messaging provides a way for scripts, CI pipelines, or the host CLI to present interactive UI to users working inside a booth. Messages appear as overlay dialogs on top of the booth's web UI (terminal, VS Code, Jupyter, or desktop).

All variants use the shared booth UI overlay — an nginx wrapper that injects an HTML overlay into the page. This means messages look and behave identically across all variants.


Subcommands

booth message send

Send a message and (for interactive types) wait for a response.

booth message send [flags]
Flag Description Required
--title Message title Yes
--body Message body text Yes
--type Message type (see Message Types) No (default: yes-no)
--name Target booth name (default: current directory name) No
--options Comma-separated options (for choice, choice-text, radio, checkbox) Required for those types
--expires Timeout duration (e.g., 5m, 1h). Default: 10m for interactive, 30s for toast No
--id Custom message ID (must match [A-Za-z0-9._-]+). Lets you target the message later with booth message adjust. No (default: auto-generated)

Output: Prints the message ID on the first line. For interactive types, prints the user's answer on the second line after they respond (or timeout if expired). For toast and banner, the CLI returns immediately after writing the message file.

booth message adjust

Update the title and/or body of an existing message file. Useful for banner messages whose content evolves over time (build status, progress, etc.).

booth message adjust [--name <booth>] <msg-id> [--title <new>] [--body <new>]
Flag Description Required
--title New title (omit to keep existing) No
--body New body (omit to keep existing) No
--name Target booth name (default: current directory name) No

At least one of --title or --body must be provided. The overlay reconciles changes on its next poll (≤ 2s).

# Send a banner with a deterministic id, then update it as the work progresses
booth message send --type banner --id ci-status --title "CI" --body "Step 1 of 5"
booth message adjust ci-status --body "Step 3 of 5"
booth message adjust ci-status --title "CI complete" --body "All green."

If the user dismisses the banner (clicks OK) before you adjust, the overlay won't re-show it — adjust only patches the live state, it doesn't re-publish a dismissed message.

booth message list

List all messages (pending and answered) for a booth.

booth message list [--name <booth>]

booth message response

Read the response for a specific message.

booth message response [--name <booth>] <msg-id>

Message Types

Type Buttons / Input User Response CLI Behavior
yes-no Yes, No yes or no Blocks until response
yes-no-cancel Yes, No, Cancel yes, no, or cancel Blocks until response
ok OK ok Blocks until response
text Text input + Send Free-form text Blocks until response
password Password input + Send Free-form text (masked) Blocks until response
choice One button per option Selected option text Blocks until response
choice-text Option buttons + text input Selected option or typed text Blocks until response
radio Radio buttons + Submit Selected option (single) Blocks until response
checkbox Checkboxes + Submit Comma-separated selections Blocks until response
toast None (click to dismiss) dismissed (auto) Returns immediately
banner OK button ok (when user clicks) Returns immediately

All interactive types show a centered modal overlay with a semi-transparent backdrop. The iframe (terminal, IDE, desktop) is blocked from interaction while the overlay is visible.

Toast notifications appear in the bottom-right corner without blocking interaction. Banner notifications appear at the top-center, also without blocking interaction, and stay until the user explicitly clicks OK.

Note: choice, choice-text, radio, and checkbox all require the --options flag.


Flags

--expires

Sets how long a message remains active before timing out.

# Interactive message with 5 minute timeout
booth message send --title "Continue?" --body "Proceed with migration?" --type yes-no --expires 5m

# Toast that stays for 1 minute
booth message send --title "Heads up" --body "Maintenance in 10 minutes" --type toast --expires 1m
  • Interactive messages: Default 10 minutes. If the user doesn't respond, the CLI exits with answer timeout.
  • Toast: Default 30 seconds. The toast auto-dismisses when the timer expires.

--name

Target a specific booth by name. If omitted, defaults to the current directory name (matching standard booth resolution).

booth message send --name my-project --title "Hello" --body "World" --type ok

Toast Notifications

Toasts are non-blocking notifications that appear in the bottom-right corner of the booth UI.

  • Stackable — Multiple toasts stack vertically (newest at bottom).
  • Auto-dismiss — Each toast has a countdown progress bar and auto-dismisses when time expires (default: 30s).
  • Click to dismiss — Users can click a toast to dismiss it early.
  • Fire-and-forget — The CLI returns immediately after writing the message file. No response is expected.
  • No iframe blocking — The user can continue working while toasts are visible.
# Quick notification (30s default)
booth message send --type toast --title "Build" --body "Build completed successfully."

# Longer notification
booth message send --type toast --title "Warning" --body "Disk usage above 80%" --expires 1m

# Stack multiple toasts
booth message send --type toast --title "Step 1" --body "Downloading dependencies..."
booth message send --type toast --title "Step 2" --body "Compiling source..."
booth message send --type toast --title "Step 3" --body "Running tests..."

Banner Notifications

Banners are non-blocking notifications that pin to the top-center of the booth UI. Unlike toasts they do not auto-dismiss — they stay until the user clicks OK or the host removes the message file.

  • Top-centered — Stacked vertically, above the iframe.
  • Persistent — No timer; the user dismisses explicitly.
  • No iframe blocking — The user can keep working while a banner is visible.
  • Updatable — Pair --id <handle> on send with booth message adjust <handle> to change the title/body live.
  • Fire-and-forget — The CLI returns immediately after writing the message file, the same as toasts.
# A simple banner
booth message send --type banner --title "Maintenance" --body "Disk repacking; expect slower I/O for ~10 min."

# Live-updating banner driven by a build pipeline
booth message send --type banner --id build --title "Build" --body "Compiling…"
make build && booth message adjust build --body "Tests…"
make test  && booth message adjust build --title "Build complete" --body "All green."

Terminal Support

When using the terminal variant (booth --variant terminal) or a shell session (booth -- bash, booth shell), there is no browser UI. Messages are handled via a prompt notification and the booth--msg command inside the container.

Prompt Notification

Before each prompt, a hook checks for pending messages and prints a notification:

[booth] 2 pending message(s) — run booth--msg to respond
coder@booth:~/code$

This is non-intrusive — it only appears between commands, never mid-typing.

booth--msg Command

Run inside the container to view and respond to messages interactively:

booth--msg            # Show and respond to pending messages one by one
booth--msg list       # List all messages (pending + answered)
booth--msg dismiss    # Dismiss all pending toasts

Each message type has a terminal-appropriate interaction:

Type Terminal Interaction
ok Press ENTER to acknowledge
yes-no Type y or n
yes-no-cancel Type y, n, or c
text Type free-form text
password Type text (input hidden)
choice Inline arrow-key menu
choice-text Inline arrow-key menu + "Type my own" option
radio Inline arrow-key menu
checkbox Inline checklist (arrow keys + SPACE to toggle)
toast Auto-dismissed (shown briefly then acknowledged)
banner Press ENTER to acknowledge (terminal can't render the floating bar)

How It Works

Booth messaging uses the booth UI overlay infrastructure. See that document for details on the nginx wrapper, iframe embedding, and API server architecture.

Message Flow

  1. CLI writes a .msg.json file to .booth/.tmp/messages/ on the host (bind-mounted into the container).
  2. Overlay JS polls the API server every 2 seconds for pending messages.
  3. Overlay renders the appropriate UI — modal dialog (interactive types) or toast notification.
  4. User responds (clicks a button, submits text, or toast auto-dismisses).
  5. Overlay POSTs the answer to the API server, which writes a .response.json file.
  6. CLI detects the response file and prints the answer (interactive types only).

File Format

Message file (<id>.msg.json):

{
  "id": "msg-1234567890",
  "title": "Deploy?",
  "body": "Deploy to staging?",
  "type": "yes-no",
  "created": "2026-04-06T12:00:00Z",
  "expires": "2026-04-06T12:10:00Z"
}

Response file (<id>.response.json):

{
  "id": "msg-1234567890",
  "answer": "yes",
  "answered": "2026-04-06T12:00:15Z"
}

Files are stored in .booth/.tmp/messages/ and cleaned up automatically when the booth restarts.


Examples

Scripting with booth messages

# Ask for confirmation before a destructive action
answer=$(booth message send --name dev-booth --title "Drop table?" \
  --body "This will delete all data in the users table." \
  --type yes-no --expires 1m | tail -1)

if [ "$answer" = "yes" ]; then
    echo "Dropping table..."
else
    echo "Cancelled."
fi

Choice selection

answer=$(booth message send --name dev-booth --title "Environment" \
  --body "Select deployment target:" \
  --type choice --options "staging,production,rollback" \
  --expires 2m | tail -1)

echo "Selected: $answer"

Choice with custom text input

# User can click a preset option or type their own
answer=$(booth message send --name dev-booth --title "Branch" \
  --body "Select or type a branch:" \
  --type choice-text --options "main,develop,release" \
  --expires 2m | tail -1)

echo "Branch: $answer"

Radio buttons (single select)

answer=$(booth message send --name dev-booth --title "Log Level" \
  --body "Select log level:" \
  --type radio --options "debug,info,warn,error" \
  --expires 2m | tail -1)

echo "Level: $answer"

Checkboxes (multi-select)

# Answer is comma-separated, e.g. "logging,metrics,tracing"
# Returns "none" if nothing selected
answer=$(booth message send --name dev-booth --title "Features" \
  --body "Select features to enable:" \
  --type checkbox --options "logging,metrics,tracing,profiling" \
  --expires 2m | tail -1)

echo "Enabled: $answer"

Password prompt

secret=$(booth message send --name dev-booth --title "Auth Required" \
  --body "Enter your deploy key:" \
  --type password --expires 5m | tail -1)

Toast from a build script

booth message send --type toast --title "Build started" --body "Compiling project..."

make build

booth message send --type toast --title "Build complete" --body "Ready to test."