Skip to content
rply.shDocs

Blocks

Blocks are typed pieces of content in a message: a table, a progress bar, a choice. Pass them as a JSON array with --blocks on rply send, rply ask, rply pin set and rply edit, or as the argument to rply status set. Each option also accepts a file path, or - for stdin.

Terminal window
rply send "Weekly report" --blocks '[{"type":"heading","text":"acme.dev"},{"type":"progress","value":42,"max":120,"label":"Pages crawled"}]'

Every block has a type. An optional id (1 to 64 characters) lets you patch the block later with --patch '{"id":"…", …}'. Input blocks require an id, which keys their answer.

{"type":"markdown","text":"**Bold**, lists and [links](https://rply.sh)"}
{"type":"heading","text":"Results"}
{"type":"code","code":"npm run build","language":"sh"}
{"type":"link","url":"https://acme.dev/pricing","label":"Open the new pricing page"}
Field Type
value number Required.
max number Optional, positive.
label string Optional.
{"type":"progress","id":"crawl","value":42,"max":120,"label":"Pages crawled"}
{"type":"keyvalue","items":[{"key":"Pages live","value":"42"},{"key":"Indexed","value":"38"}]}

Both key and value are strings.

{"type":"table","columns":["Keyword","Rank"],"rows":[["agent inbox",4],["ai approvals",7]]}

Cells are strings or numbers.

Field Type
file_id string Required. From rply file upload.
name string Optional.
alt string Optional.
{"type":"image","file_id":"9fk2…","alt":"Clicks per day"}

rply send --image chart.png creates this block for you.

Field Type
file_id string Required. From rply file upload.
name string Required.
mime string Optional.
size number Optional, in bytes.

Runs your HTML in a sandboxed frame inside the message. See HTML embeds and apps.

Field Type
html string Required. A fragment or a full document.
label string Optional header above the embed.
height number Optional fixed height in pixels, up to 2000. Otherwise it grows to fit.
question boolean Optional. Makes the embed a question answered with rply.reply(). Requires an id.

A message with at least one input block is a question. Inputs need an id, unique within the message. The answer is keyed by that id: one input prints its value, several print a JSON object.

A question with two choices

Field Type
options array Required. Each has label, and optionally value, description, danger.
label string Optional.
multi boolean Allow picking several. The answer is an array.
other boolean Allow a typed answer besides the options.
required boolean
default string or array Used if the question expires.
{"type":"choice","id":"tone","label":"Tone","options":[{"label":"Formal"},{"label":"Casual","description":"Default"}],"default":"Casual"}
Field Type
label string
placeholder string
multiline boolean
required boolean
default string
{"type":"text_input","id":"title","label":"Title","required":true}
Field Type
label string
min, max number
required boolean
default number
{"type":"number_input","id":"count","label":"How many pages?","min":1,"max":50}
Field Type
label string Required.
default boolean
{"type":"toggle","id":"notify","label":"Email subscribers"}

A single button. Answering it confirms.

Field Type
label string Required. The button text.
description string Optional.
danger boolean Style as destructive.
{"type":"confirm","id":"go","label":"Deploy now","description":"Takes about 2 minutes"}

When a message has exactly one simple input (a single choice, a confirm button, or an html question), the app submits as soon as the person picks. Otherwise it shows a Send answers button for all inputs together.

The server accepts block types it doesn’t know, and the apps show them as a short “update the app” placeholder. That lets new block types ship without breaking older apps. Known types are validated: a malformed table or a choice without options is rejected with a 400 error that names the invalid field, and the CLI adds a pointer to rply guide blocks.