Chat-Native Command Grammar for the Metanet
Every chat-style client invents its own commands, so what you learn in one is useless in the next. This fixes a common set of verbs that behave the same way everywhere.
Summary
- Why
- Chat clients needed one command language whose verbs mean exactly the same thing everywhere, so that a typed or agent-generated command can't be reinterpreted or hijacked by the client reading it.
- What
- BRC-218 is a specification for a slash-command grammar and a global, versioned set of command verbs that every conforming Metanet chat client must parse and confirm the same way.
- How
- A client parses a leading slash and verb against the global grammar, resolves recipients and amounts via BRC-169, shows a confirmation sheet for anything that moves value or changes policy, and skips that sheet entirely for pure lookups.
What this lets you do
- Parse slash commands like /pay, /trolltoll, /whois identically across clients
- Show a structured confirmation before any value-moving or policy-changing command executes
- Convert fiat amounts to satoshis at send time through an oracle with staleness and disclosure rules
- Advertise ecosystem-specific custom verbs without colliding with the global reserved set
- Reject commands parsed from received message content instead of user input
Written by claude-sonnet-5 from the specification text. Where the two differ, the original is correct.
Reference for an AI
Everything an assistant needs to answer questions about BRC-218 accurately, including what it depends on.
The specification
Abstract
This document specifies a slash-command grammar for conversational Metanet clients, and a global set of command verbs that MUST behave identically in every conforming client regardless of ecosystem.
Commands are the chat-native surface over the addressing, payment, messaging, reachability, and delegation mechanics of BRC-169. /pay @brandon@handcash $2.18 performs a BRC-169 section 6 payment; /trolltoll 300 sats sets a BRC-169 section 8 policy. This document defines the syntax, the parsing and confirmation rules, and the exact behavior of each verb. It defines no new cryptographic or wire mechanics.
It also reserves a set of verbs for commands that are anticipated but not yet specified, so that ecosystems cannot claim them, and defines how an ecosystem advertises its own custom commands without colliding with the global set.
Motivation
The interface through which people use the Metanet is converging on chat, and two properties make a standardized command grammar worth writing down.
Agents read and write the same grammar. An agent that can parse /pay @brandon@handcash $2.18 can also emit it. A slash command is simultaneously a human-readable interface and a machine-parsable API, which is what an agent-mediated decade requires. That dual role is also a hazard: text that arrives from a counterparty must never be executable, and an agent acting for a user must be bound by verifiable authority rather than by convention. Both are addressed here.
Identical parsing is what makes commands portable. If /pay means one thing in one client and something else in another, the grammar is worthless as an interoperability layer, and worse than worthless as a target for agents. Reserving the global verbs and fixing their meanings in a versioned document is the whole contribution.
A note on scope. Commands requiring a multi-party protocol or an on-chain construct that BRC-169 does not define are reserved in section 6 rather than described loosely. "Every client MUST parse this identically" is not a meaningful requirement for behavior that has not been specified, and a verb sketched in a sentence invites divergent implementations with funds at stake. Reserving the name costs nothing and keeps it available for a specification that does the work.
Specification
The key words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY in this document are to be interpreted as described in RFC 2119.
Throughout, "resolve" means the client resolution algorithm of BRC-169 section 5.7, and "value-moving action" has the meaning given in BRC-169 section 1.
1. Terminology
- Command: a line of user input beginning with
/, parsed per section 2. - Global verb: a verb defined in section 5, or reserved in section 6. Global verbs are reserved across all ecosystems.
- Custom verb: a verb defined by a single ecosystem and advertised per section 8.
- Thread: the conversation in which a command is issued. A command issued in reply to a specific message is bound to that message.
2. Grammar and Parsing
command = "/" verb *( 1*SP arg )
verb = alnum [ *30( alnum / "-" ) alnum ] ; 1 to 32 characters
arg = recipient / amount / duration / period / quoted / word
recipient = <the recipient rule of BRC-169 section 2.1>
amount = fiat / sats
fiat = [ iso4217 1*SP ] "$" 1*DIGIT [ "." 1*2DIGIT ]
/ iso4217 1*SP 1*DIGIT [ "." 1*2DIGIT ]
sats = 1*DIGIT 1*SP ( "sat" / "sats" )
duration = 1*DIGIT ( "m" / "h" / "d" ) ; minutes, hours, days
period = "/" ( "day" / "week" / "month" )
quoted = DQUOTE *( %x20-21 / %x23-5B / %x5D-7E / "\" DQUOTE ) DQUOTE
word = 1*64( %x21-7E ) ; no whitespace
iso4217 = 3UPPER
alnum = lower / DIGIT
lower = %x61-7A
UPPER = %x41-5A
- A line beginning with
/is a command. A line beginning with//is chat whose first character is a literal/, with the leading//reduced to/before display. Any other line is chat. - Verbs are case-insensitive and MUST be normalized to lowercase before dispatch. Arguments are case-sensitive except where a referenced specification requires normalization.
- Where a command takes free text as its last argument, that argument extends to the end of the line and is not subject to the
wordrule. - A client MUST parse commands only from input composed locally by its own user. Text received from a counterparty, whether in message content, a display name, a memo field, an attachment, or a search result, MUST NOT be parsed or executed as a command under any circumstances, and MUST be rendered as literal text. See Security Considerations.
- A client encountering a verb it does not implement MUST report it as unsupported. It MUST NOT execute a different command, and it MUST NOT reassign the verb's meaning.
- Parsing MUST NOT have side effects. A command takes effect only after the confirmation rules of section 4 are satisfied.
- Token boundaries are whitespace, not
@. A fully-qualified recipient contains two@characters (BRC-169 section 2.1). A client MUST find the start of a recipient token by scanning back to the preceding whitespace or the start of input, not to the nearest@. Scanning to the nearest@truncates the token the moment the user types the ecosystem separator, which is precisely when autocomplete is most useful. - Where an input could be read as either a handle or a paymail address, a leading
@decides: with one, the token is a handle per BRC-169 section 2.1; without one, it MAY be treated as paymail per BRC-169 section 2.1(7).
3. Amounts
21545 satsdenotes exactly 21,545 satoshis.$2.18denotes 2.18 USD. Other currencies use an ISO-4217 prefix, as inCHF 5.- Fiat amounts MUST be converted at send time through the oracle interface of BRC-169 section 6.2, subject to its staleness bound, disclosure rules, and audit-trail requirements.
- A client MUST display the satoshi amount alongside the fiat amount in the confirmation of section 4 for any fiat-denominated command.
- A client MUST reject a fiat amount it cannot convert. It MUST NOT substitute a stale rate, a cached rate beyond its validity, or a rate from an undisclosed source.
- The
fiatrule permits at most two decimal places. A client MUST reject a finer fiat amount rather than rounding it, and SHOULD direct the user to satoshis, which have no such limit. Examples elsewhere in this document are held to the same rule.
3.1 Token-denominated amounts
Ecosystems issue tokens, and a payment in one is a different operation from a BSV payment rather than a formatting variant of it. A client MAY accept a token amount:
amount =/ token
token = 1*DIGIT 1*SP symbol
symbol = 1*12( ALPHA / DIGIT )
- The symbol MUST resolve against a token list the client already knows. An unrecognised symbol MUST NOT be treated as an amount; it falls through to free text, so that
3 nutriand a memo beginning "nutri" cannot be confused. - The confirmation MUST state that the transfer is of a token and not of BSV.
- Any fiat equivalent shown for a token amount MUST be marked indicative. A token is worth what its issuer and its market say it is, and a client quoting a rate for one is making a claim it cannot support.
4. Confirmation and Execution
- Before executing any command that moves value, issues or revokes a certificate, or changes a reachability policy, a client MUST present a structured confirmation showing at minimum: the verb, the fully-qualified recipient where one applies, the amount in both satoshis and the typed fiat where applicable, and a plain statement of the effect.
- A command that does none of those MUST NOT require a confirmation. A lookup moves nothing, sends nothing, and is not disclosed to the handle being looked up; there is nothing for the user to consent to. Asking anyway is not a free precaution: a client that puts the same sheet in front of a read and a payment teaches the user to dismiss it, and the dismissal habit is carried to the sheet that mattered.
/whoisand/helpare the clear cases. - The confirmation MUST show the recipient as
@handle@domain.tldin fully-qualified form, never as an alias alone, and MUST reflect the display and confusability rules of BRC-169 sections 2.3 and 2.4. - Clients MUST offer autocomplete for verbs and recipients. Autocomplete MUST NOT substitute a recipient the user did not select, and a completed recipient MUST remain visible and editable before confirmation. Accepting a suggestion MUST insert the fully-qualified handle, which is what makes the no-substitution rule observable. A suggestion list MAY display the bare handle: in a single-ecosystem thread every row otherwise ends in the same suffix, and the list becomes harder to read rather than safer.
- Argument navigation is not substitution. A client MAY offer keyboard navigation between a command's argument positions — the grammar is positional, and a user filling in
<recipient> <amount> [memo]will reach for a key that moves between them. Doing so MUST NOT alter the command text. Only an explicit accept per rule 4 may insert anything. This is easy to violate without noticing: where the navigation key is also bound to an open suggestion list, pressing it completes the token under the caret instead of moving past it, and the command that executes is not the one on screen. - Resolution failures, revoked handles, and key changes MUST be surfaced at confirmation time and MUST block execution of a value-moving command until acknowledged, per BRC-169 sections 4.4 and 5.3.
- Non-interactive execution. An agent or automation executing commands on a user's behalf without per-command human confirmation MUST hold a delegation certificate per BRC-169 section 9 covering each verb it executes, and MUST remain within that certificate's scope, caps, and expiry. A client MUST NOT offer a mode that suppresses confirmation without a corresponding delegation, and MUST NOT treat a suppressed confirmation as raising the limits in the certificate.
- Disclosure of automated participants. Where an agent acts in a conversation under a delegation, the other participants cannot tell from the messages alone whether they are addressing the person or the automation. A client that supports non-interactive execution MUST provide a way for the delegating user to declare in the conversation that an agent is acting for them, and what its scope and expiry are. The delegation itself is between the user and the agent; the participants' need to know who they are dealing with is not served by it. The declaration mechanism is left to the ecosystem, which MAY define a custom command for it under section 8.
- A command bound to a message applies to that message. Where a command requires a binding and none exists, the client MUST report the error rather than apply the command to the thread's most recent message.
- A client that offers bound verbs MUST provide a way to establish the binding that does not depend on hover. A reply affordance revealed only on pointer hover makes every bound verb unreachable on a touch device.
- Actions offered on a command's result. A client MAY offer actions on the record of a completed command — lifting a toll it set, cancelling a subscription it started, revoking a certificate it issued, paying a request it made. Where such an action moves value, it MUST route through the confirmation of 4.1; a control inside a popover or a notification is not a structured confirmation. Where it only reverses standing state and moves no value, it MAY execute directly. Either way the action SHOULD be recorded in the conversation as its own command, so that the change is visible to the participants rather than happening silently.
5. The Global Command Set
The verbs in this section are reserved across all ecosystems and are versioned by this document: additions and changes happen by revision. Every conforming client MUST parse them identically. A client MAY decline to execute a verb it does not support, but MUST NOT reassign its meaning.
5.1 /pay
/pay <recipient> <amount> [memo]
Resolve the recipient and execute a BRC-169 section 6.1 payment. memo is free text and MUST be carried in the encrypted envelope content, not in envelope metadata.
Where the recipient has a toll in force, the client MUST follow BRC-169 section 8.3, quoting before sending and attaching the toll in addition to the payment amount. The toll and the payment are distinct amounts and MUST be shown separately at confirmation.
5.2 /message
/message <recipient> <text>
Send text to the recipient as a BRC-169 section 7.2 envelope. Equivalent to plain chat once a thread exists; the explicit form exists for cross-ecosystem first contact and for agents.
5.3 /request
/request <recipient> <amount> [memo]
Send a payment request. The recipient's client MUST render it as an actionable item that, on acceptance, executes /pay back to the requester for the stated amount, and MUST re-derive the amount at acceptance time where it was fiat-denominated, showing both the original and current satoshi values.
A request confers no authority. It MUST NOT cause any transfer without the recipient's explicit confirmation, and a client MUST NOT allow a request to be auto-accepted by any policy short of a delegation certificate scoped to pay.
5.4 /tip
/tip [amount]
A /pay bound to the message being replied to, addressed to that message's verified sender. The binding MUST be recorded in the envelope content so the recipient can attribute the tip. Where amount is omitted the client SHOULD offer a configured default, and MUST still confirm per section 4.
5.5 /split
/split <recipient> 1*( 1*SP <recipient> ) <amount>
Divide amount among the named recipients and send each leg as an independent BRC-169 section 6.1 payment. Recipients MAY be in different ecosystems.
- Division is equal by default. Clients MAY offer custom weights through their own interface, but the grammar above is what MUST be parsed identically.
- Rounding MUST be deterministic: divide into integer satoshis, and allocate any remainder one satoshi at a time to recipients in the order given.
- Legs are independent and failure is partial. A resolution or delivery failure on one leg MUST NOT roll back the others. The client MUST report per-leg outcomes and MUST NOT report the command as succeeded unless every leg succeeded.
- All recipients MUST be resolved and displayed at confirmation before any leg is sent. Clients SHOULD warn when a split exceeds a configured number of legs, since fan-out multiplies both cost and disclosure.
5.6 /subscribe
/subscribe <recipient> <amount> <period>
/subscribe <recipient> "off"
Establish a standing payment executed by the sender's wallet on the stated period, or end one already running.
- This grants the recipient no pull authority. No certificate is issued, nothing is delegated, and the recipient cannot initiate. Each execution is an ordinary
/payperformed by the sender's own wallet. - The subscription is cancellable at any time, and cancellation MUST take effect before the next scheduled execution without requiring the recipient's cooperation. The
offform is the interoperable way to express this: without it, every client invents its own gesture and the counterparty learns nothing. Cancellation ends future executions only and reverses nothing already sent. - Before each execution after the first, the client MUST re-resolve the recipient and apply the key-change rule of BRC-169 section 4.4, suspending the subscription and requiring confirmation if the identity key has changed.
- Where the amount is fiat-denominated it MUST be re-converted at each execution. The client MUST disclose at setup that the satoshi amount will vary, and SHOULD allow a satoshi ceiling above which execution pauses for confirmation.
- A client MUST maintain a visible list of active subscriptions with their next execution time.
5.7 /whois
/whois <recipient>
Resolve and display the attested identity without transacting: handle, domain, identity key, certificate status including the revocation check and the time it was performed, messagebox, whether the identity is in the user's address book, whether its key has changed since it was added, and any peer attestations per BRC-169 section 10.
/whoison a subhandle MUST return the base handle's identity, noting the queried tag, per BRC-169 section 3.1.- Unverified, host-supplied attributes such as a display name or avatar MUST be labeled as unverified.
/whoisMUST perform a fresh resolution rather than answering from cache, and MUST report the age of the revocation check it relied on.- The result belongs in the conversation. A resolution presented only in a panel outside the thread turns the command into a navigation step and leaves the conversation with no record of what was resolved — which is the case people most often run it for, showing someone else who a handle belongs to. A client SHOULD render the outcome inline where the command was issued, with the identity key, the resolving domain, and the certificate state legible without a further click.
- Resolution is not instantaneous, and SHOULD NOT be drawn as though it were. A handle is resolved over the network. A client that paints a complete answer in the same frame the command was issued teaches its user that resolution is free and always succeeds, which is the belief that makes a stale binding or a substituted key easy to miss later. Rule 3 already requires reporting the age of the revocation check the answer relied on.
5.8 /attest
/attest <recipient>
Publish a peer attestation of the recipient's handle to key binding, per BRC-169 section 10.3. The client MUST require a fresh, successful /whois-equivalent verification immediately before issuing, and MUST make clear at confirmation that the attestation is a public, signed statement that others may rely on.
5.9 /scope
/scope ( "everyone" / "contacts" / "ecosystem" / "toll" ) [ <recipient> ]
Set the reachability scope defined in BRC-169 section 8.1. The optional recipient argument, which MUST be a subhandle of the user's own handle, scopes the setting to that tag.
The command changes policy at the user's own messagebox. A client MUST confirm that the change was accepted by the messagebox before reporting success, and MUST warn that the messagebox, not the client, is the enforcement point.
5.10 /trolltoll
/trolltoll [ <recipient> ] ( <amount> / "off" )
Set, change, or lift the per-message toll defined in BRC-169 section 8.2. With a recipient, the toll applies to that sender; without one, to everyone in scope. A recipient that is a subhandle of the user's own handle sets a per-tag toll.
- The toll is paid to the user, is due for every message each time, and is not refunded on reply.
- Setting a toll MUST NOT retroactively apply to quotes already issued and still valid, per BRC-169 section 8.3.
offlifts the toll for the named sender, or for everyone where no sender is named. Lifting a general toll does not lift per-sender tolls, and the client MUST say so.
5.11 /delegate
/delegate <recipient> [scope] [amount] [duration]
Issue a delegation certificate to the recipient per BRC-169 section 9.1, where scope is a BRC-169 section 9.2 scope string, amount sets fields.perActionCap, and duration sets fields.expiry.
The confirmation MUST state, in plain language: which verbs are being granted, the per-action cap, the expiry, whether onward delegation is permitted, and, where a cumulative cap is set, whether it is actually enforced per BRC-169 section 9.3.3. A client MUST NOT describe a cumulative cap as guaranteed unless a principal-funded arrangement is in place.
Issuing * scope MUST require an additional, distinct confirmation.
5.12 /revoke
/revoke <recipient> [serial]
Revoke a delegation certificate the user issued, by spending its revocation ,[object Object]. Where the user has issued more than one certificate to the recipient and no serial is given, the client MUST list them and require a selection rather than guessing.
The client MUST report that revocation is detectable rather than instantaneous, and is subject to the indexing lag described in BRC-169 section 4.2. It MUST NOT report the delegate as unable to act until the spend is confirmed.
5.13 /handoff
/handoff <recipient> [amount] [duration]
Issue a delegation certificate bound to the current thread, per BRC-169 section 9.7, with scope qualified by thread:<id> for the thread in which the command is issued.
The confirmation MUST state the thread being delegated, the per-action cap, and the expiry. Where amount is presented to the user as a spend limit, the client MUST apply BRC-169 section 9.3.3 and state explicitly whether the limit bounds total spend or only each individual action. A client MUST NOT use the words "hard cap", "maximum", or equivalent for a cumulative limit that is not principal-funded.
5.14 /sign
/sign [text]
Sign content with the user's identity key, producing a BRC-3 signature over its canonical hash, delivered into the same thread.
The binding is optional, and decides what is signed:
- Bound — issued in reply to a message, the signature covers that message's content as the signer received and displayed it. This is a countersignature.
- Unbound — issued on a message the user is composing, the signature covers that message: its text and every attachment carried with it. With no attachment it covers the text alone.
Further requirements:
- A client MUST show the exact content being signed at confirmation, including an enumeration of the attachments covered.
- The result MUST state what the signature covered. "Signed" over a message and "signed" over a message and four files are different claims and a reader cannot distinguish them from the word alone.
- Signing an unbound message requires that its attachments exist on the draft before it is sent. A client that posts an attachment the moment it is selected cannot offer this form at all, because there is no composed message for a signature to cover.
- Verifiers MUST check the signature against the signer's resolved identity key, per BRC-169 section 5.7.
- Multi-party document signing, counterparty ordering, and on-chain anchoring of a completed document are not specified here. See section 6.
5.15 /receipt
/receipt
Request a signed acknowledgment for the message being replied to, or for the user's most recent message in the thread where the command is unbound. The counterparty's client, if it honours the request, returns a BRC-3 signature over the message hash together with a timestamp.
A receipt is voluntary. No client is obliged to honour a request, absence of a receipt means nothing, and clients MUST NOT present a missing receipt as evidence that a message was not delivered or not read.
5.16 /help
/help [command]
List the commands the client supports, or describe a single command where one is named.
- A conforming client MUST implement
/help. It is the only command a user can issue without already knowing the grammar, which makes it the entry point to everything else; a grammar discoverable only by reading this document is not discoverable. - The listing MUST distinguish verbs the client will execute from those it reports as unsupported, covering both section 2.5 declinations and the reserved verbs of section 6. A user who cannot tell "this client does not do that" from "nobody does that" has been told very little.
- Custom verbs (section 8) MUST be listed as belonging to their ecosystem rather than to this document.
- The argument is a command name, and clients MUST accept it with or without the leading slash. A reader who has just been told to type
/paywill type/help /pay. Calling the argument a verb in the prompt, or reusing the free-text placeholder for it, tells a user who does not know the grammar to type the wrong thing. - Order. The listing MUST lead with the commands runnable in this ecosystem, custom verbs (section 8) before the global set, and MUST place declined and reserved verbs after both. The order answers "what can I do here" before "what exists but not here". Section 5's own order is not a listing order: it puts the verbs a user can actually run last.
- One line per command is not sufficient. A summary that fits beside a grammar string cannot also carry the behaviour a user needs before running the command — that a per-action cap is enforced by the counterparty and a cumulative one generally is not, or that lifting a general toll leaves a per-sender toll in force. The listing MUST make a fuller description reachable for each command, and SHOULD keep the list itself scannable rather than expanding every description at once.
/helpis answered locally. It MUST NOT be transmitted, and its reply MUST be presented per section 9.
5.17 /refund
/refund [amount]
Return a payment, bound to the payment it returns.
/refundMUST bind to a message carrying a completed payment, per section 4.9.- Nothing reverses on chain, so a refund is a new payment in the opposite direction. The client MUST carry a machine-readable reference to the payment being returned. A memo is not sufficient: section 2.4 forbids executing received text, so a reference a counterparty's client can act on cannot be prose.
- Omitting the amount returns the full amount of the bound payment. A smaller amount is a partial refund and MUST be shown as such at confirmation, stating both figures; "refund" implies the whole of it, and often is not.
- Only the party that received a payment can refund it. A client MUST refuse
/refundbound to a payment the user sent, and SHOULD point at/request, which is what asking for money back actually is. - A recipient's client SHOULD mark the original payment as refunded on receiving one that references it, in whole or in part.
5.18 /cancel
/cancel
Withdraw a payment request you sent.
/cancelMUST bind to a message carrying a/request(section 5.3) that the user sent. A client MUST refuse to cancel a request it did not send.- A request creates an obligation in the recipient's client that section 5.3 gave no way to discharge except paying it. Without a defined withdrawal the sender's only remaining move is to ask repeatedly, and every client invents its own gesture, which the counterparty cannot read.
- On cancellation the recipient's client MUST stop presenting the request as owed. Nothing moved, so nothing is returned, and a client MUST NOT present a cancellation as a payment or a refund.
5.19 /standing
/standing
List everything still acting on the user's behalf.
- A conforming client MUST implement
/standing, and MUST list at minimum: delegation certificates issued and not revoked, active subscriptions, tolls in force, and the current reachability scope. - Every entry MUST state its bounds — scope, cap, and expiry — rather than only naming the thing. An entry without them is a claim that no bound exists, which for a certificate is the most dangerous thing it could fail to say.
- Authority that has lapsed or been revoked SHOULD be listed and labelled as such. "It expired" and "it was never issued" are different answers to the same question, and only one of them means the user remembered correctly.
/standingmoves nothing and is answered locally. It MUST NOT be transmitted, and its reply MUST be presented per section 9.- This section exists because everything it lists keeps acting without asking again. A grammar that hands out standing authority and never requires a way to enumerate it leaves users holding authority they would revoke if they could see it. The prior art is the authorized-applications list every OAuth provider was eventually obliged to ship.
5.20 /send
/send <recipient> #asset
Transfer a non-fungible asset the sender holds.
/sendmoves the thing, not an amount. Clients MUST NOT treat it as a variant of/pay: the two answer different questions and a client that renders them alike will eventually let someone confirm the wrong one.- An asset is named by a
#referencethat a person can type from looking at it. A client MUST resolve the reference against assets the sender actually holds and MUST refuse an unresolved one rather than guessing at a near match. - The confirmation of section 4.1 MUST show the asset's artwork and its serial, not only its name and id. A collectible is identified by looking at it, and confirming against an identifier asks the user to verify from the label on the box — which is the check people skip.
- The record left in the conversation MUST identify both parties, not only the recipient. "Sent to Randy" is ambiguous the moment it is quoted, forwarded, or read by somebody who joined the room afterwards.
- Where the transfer settles on chain, the record SHOULD link to the transaction. An asset transfer is the case where a reader most wants to check for themselves.
5.21 /escrow
/escrow <agent> [#asset] [amount] <duration>
Commit one side of a trade to a named agent for a bounded window.
This section claims a verb reserved by section 6, which anticipated exactly that: each reserved verb is a candidate for its own BRC that extends this document by claiming its name. It claims the named-agent case only. Arbitration, dispute resolution and script-enforced release remain unspecified and out of scope; see the note at the end.
- Each party commits one side: the asset, or the payment. A commitment naming neither is not a side and MUST be refused.
- An escrow forms when two sides name the same agent, carry complementary halves, and agree on the amount, before either window closes.
- Pairing MUST be deterministic. Where more than one open side could match, a client MUST pair the earliest unmatched one, and MUST show the committer which side it paired with. Two offers of the same amount to one agent are otherwise indistinguishable, and an agent left to guess which payment answers which asset will eventually guess wrong.
- Two commands mean two clocks. The escrow lives by the earlier of the two windows. A side whose window closes unmatched lapses alone, and nothing moves.
- The agent's acceptance moves value and therefore MUST route through the confirmation of section 4.1. A control on a card is not a structured confirmation, and this is the point at which two other people's property becomes the agent's responsibility.
- Every state change — pairing, acceptance, refusal, lapse, release — MUST be reported in the conversation. The parties cannot see the agent's client, and an escrow that changes state silently is one where the only person who knows is the one holding everything.
- The client MUST state what it does not guarantee. Nothing here is arbitrated: the agent holds both halves and can keep them. A client MUST say so, in those terms, before either side commits, and for as long as the statement is true. It MUST stop saying it once the escrow has settled — a released escrow claiming nothing has moved is worse than saying nothing.
- A client SHOULD show the agent's standing under BRC-169 section 10 at the point of commitment. The agent's reputation is the only bond in this arrangement, which makes it the one fact a committer most needs and the one they are least likely to go and look up.
- Controls addressed to the agent MAY be shown only to them, but a client MUST NOT present this as enforcement. Visibility inside a shared room is a courtesy of the rendering client; what constrains the agent is that they are the party the other two named.
Deliberately unspecified. A dispute path, an arbiter with a defined role beyond custody, partial release, and any script that removes the need to trust the agent. Each needs an on-chain construct BRC-169 does not provide, and specifying a trusted-agent escrow does not make an arbitrated one out of scope for a later document — it narrows what that document has left to settle.
6. Reserved Verbs
The following verbs are reserved and MUST NOT be assigned by any ecosystem, but are not specified by this document. /escrow was among them until section 5.21 claimed it, which is the route this section intends: a reservation is a name held open for a specification, not a name held closed. A conforming client MUST report them as unsupported rather than implementing local behavior under these names.
| Verb | Intended purpose | What a specification must settle |
|---|---|---|
/bounty | An open, claimable payment addressed to a room | Claim submission and adjudication, protection against front-running a claim, and release or expiry of unclaimed funds |
/poll | Payment-gated voting | Vote aggregation, the auditability claim, protection against the poll operator discarding votes, and refund or forfeit of vote payments |
/gate | An entry fee for a room or channel | A room and membership model, which BRC-169 does not define, plus fee custody and split policy. /gate is the write half — charging for entry. Section 11 specifies the read half, which needs no verb and no custody |
/contract | Multi-party document signing and anchoring | Party enumeration, signing order, partial-signature state, the canonical document hash, and the anchoring transaction format |
Each of these requires either a multi-party protocol or an on-chain construct that BRC-169 does not provide. Each is a candidate for its own BRC, which would extend this document by claiming its reserved verb.
7. Precedence
- Global verbs, whether specified in section 5 or reserved in section 6, are reserved across all ecosystems. A custom verb MUST NOT shadow one.
- Where a collision occurs, including where a future revision of this document promotes a verb that an ecosystem had already claimed, clients MUST resolve it in favour of the global meaning and the ecosystem MUST rename its custom command.
- A client MUST NOT allow a user, a configuration file, or a plugin to rebind a global verb to different behavior. Aliases that expand to a global verb are permitted; redefinitions are not.
8. Ecosystem-Custom Commands
An ecosystem MAY define additional verbs and advertise them in the metanet.handles.commands array of its manifest (BRC-169 section 5.1), so that foreign clients can surface them contextually or explain why they cannot.
{
"verb": "gift",
"description": "Send a payment wrapped in an animated gift card.",
"args": [
{ "name": "recipient", "type": "recipient", "required": true },
{ "name": "amount", "type": "amount", "required": true },
{ "name": "design", "type": "word", "required": false }
],
"fallback": "payment",
"docs": "https://example.com/docs/gift"
}
| Field | Requirement | Meaning |
|---|---|---|
verb | MUST | The verb, per the verb rule of section 2. MUST NOT be a global verb. |
description | MUST | One sentence, for display in autocomplete and help. |
args | MUST | Ordered argument descriptors. May be empty. |
args[].type | MUST | One of recipient, amount, duration, period, quoted, word, text, enum. |
args[].values | MUST for enum | Permitted values. |
fallback | MUST | What a client that does not implement the verb should do: payment, message, or none. |
docs | MAY | A URL documenting the command. |
-
Custom commands MUST follow the section 2 grammar, the section 4 confirmation rules, and the section 7 precedence rule.
-
A client MUST NOT execute a custom verb it does not implement. It MAY offer the declared
fallback:paymentmeans the equivalent plain/pay,messagemeans a plain/message, andnonemeans the command is unavailable outside its ecosystem. A fallback MUST be presented as a substitution and separately confirmed. -
A client that shows where a verb comes from MUST label a custom verb by its ecosystem and a global verb by its section in this document, and MUST NOT use one format for both. Citing a custom verb as though it were specified here claims an authority it does not have.
-
Descriptors are host-supplied and unattested. A client MUST render
descriptionanddocsas untrusted text, MUST NOT followdocsautomatically, and MUST NOT allow a descriptor to alter the confirmation requirements of section 4. -
Commands advertised by one ecosystem apply to recipients of that ecosystem. A client MUST NOT offer a custom verb for a recipient whose domain does not advertise it.
-
A custom verb carrying a flag that changes who is exposed MUST confirm the flag explicitly. Where an argument decides whether the user is identified — as
/renounce [p|public]does — the confirmation of section 4.1 MUST state which way it is going, in words, before it runs. A single character deciding whether a statement is anonymous is the kind of argument that is mistyped once and cannot be untyped.
Three illustrations. A wallet ecosystem might define /gift @r $x [design], wrapping a payment in an animated presentation for its own users while foreign clients fall back to a plain payment carrying the design as an attachment. A machine-to-machine ecosystem might define /charge 15kWh for device handles such as @charger-0042@voltnet, where a vehicle's agent pays a charging post through streamed payments under a thread-scoped delegation, with no account and no roaming contract. And an ecosystem that has defined a vouch verb will eventually want its inverse: Nexus defines /renounce [p|public] @handle [reason], a signed statement that the author does not stand behind someone, unattributed unless they choose otherwise, under the rules of BRC-169 section 10(7). It is deliberately not offered as a button anywhere — speaking against someone should cost the effort of typing it.
9. Local Responses
Several things a client says in a conversation are not messages: the /help listing of section 5.16, the unsupported-verb report of section 2.5, a parse error, a confusability warning under BRC-169 section 2.3, and a resolution failure under section 4.4. Each is the client answering its own user, inside a thread, with no counterparty.
- A local response MUST NOT be transmitted to any counterparty and MUST NOT appear in any other participant's view of the thread.
- It MUST be visually distinguishable from a message, and MUST be labelled. A local response is drawn inside a shared transcript and looks like a message in it; the label is the only thing separating "the client answered me" from "I posted a manual at everyone", which is not a SHOULD.
- The label MUST say that nothing was sent, and that no other participant receives it, human or automated. "Only visible to you" is no longer enough on its own: a conversation may hold agents acting under section 4.7 delegation, and a user who knows an agent is reading the thread cannot tell from that phrase whether the agent is included. The
/helplisting of section 5.16 needs this most, because it is the local response that most resembles a document deliberately posted to the room. - It MUST be dismissible, and MUST NOT be treated as part of the transcript for the purposes of signing (section 5.14), receipts (section 5.15), or export.
- It MUST NOT be parseable as a command on a later pass, per section 2.4. A client's own output is still not user-composed input.
10. Display
This document specifies what a command means, not how it looks, with three exceptions where display is load-bearing.
- A command is a message. A command the user issued SHOULD be rendered inline, as the line they typed, with its resolved arguments legible. Rendering every result as a full-width record turns a conversation into a stack of receipts: a
/whoisthen occupies the same space as a paragraph, and the conversation it was issued in becomes hard to follow. The structured record of section 4.1 remains available; it does not have to be the resting state. - Amounts and recipients keep their marks. Where a client renders a resolved argument, it SHOULD carry the same identifying mark used elsewhere for that thing — the person's avatar for a recipient, the token's mark for an amount — so that a misdirected command is visible at a glance rather than only on reading.
- Rendering a handle MUST NOT rewrite it. Where a handle is displayed as a chip or otherwise decorated, the client MUST render the form the user wrote.
@23@treechatand@thoth@treechatname one identity, and silently redrawing one as the other edits the message. Resolution is canonical; display is not.
11. Access Gates
A room may condition reading it on facts about the reader — a token they hold, a vouch somebody signed, a statement written against them. That mechanism is specified in BRC-190, which subsumes and replaces the sketch that previously stood in this section.
Two boundaries are worth restating here, because both are about this document.
- Access gates define no verbs and reserve none. Configuring a gate from a conversational interface is a matter for this document; what a gate is and how it evaluates is a matter for BRC-190.
- The
/gateverb reserved in section 6 is a different thing and remains reserved. It is the write half — charging for entry, with custody, refunds, and a rule for what happens when the room ends. BRC-190 specifies the read half only.
Security Considerations
Received text must never be executable. A chat client that parses commands out of incoming message content, memos, display names, or search results hands every counterparty the ability to spend the recipient's money. Section 2.4 forbids it absolutely. This extends to agents: an agent that reads a thread and acts on instructions found in it is executing counterparty-supplied commands, and MUST treat message content as data. Where an agent is intended to act on a counterparty's request, the action must still pass its delegation's scope and caps, and the request must be treated as a proposal rather than an instruction.
Agents are bounded by delegation, not by the client. Section 4.5 requires a delegation certificate for non-interactive execution because a client-side "auto-approve" toggle is unverifiable by anyone else and unenforceable once the agent holds keys. The exposure is what BRC-169 section 9.3 says it is: bounded per action, and bounded in total only where the principal funds each action. An agent granted /pay with a per-action cap and no principal funding can spend without limit until its certificate expires.
Confirmation is the last line of defence, and it is a human factors problem. Homoglyph handles, an alias that resolves somewhere unexpected, an autocomplete that fills a similar recipient, or a fiat amount whose satoshi value has moved are all things a user confirms without noticing. Sections 4.2 and 4.3 exist for this reason, along with the confusability rules of BRC-169 section 2.3. Clients should resist the temptation to make confirmation frictionless for value-moving commands.
Fan-out amplifies mistakes and disclosure. A /split across many recipients in several ecosystems performs many resolutions and many payments, discloses the sender's intent to every domain involved, and fails partially by design (section 5.5.3). A mistyped recipient in a long split is not recoverable.
Standing authority accumulates quietly. /subscribe grants no pull authority, which makes it safer than a card mandate, but it does create a recurring outflow that a user may forget. Section 5.6.5 requires a visible list. Fiat-denominated subscriptions vary in satoshi terms and can grow without any further user action, which is why 5.6.4 requires disclosure and recommends a ceiling.
Revocation is not immediate. /revoke spends an outpoint. Until that spend is confirmed and indexed by whatever source a counterparty consults, the delegate may still transact successfully. Section 5.12 requires the client to say so rather than implying the delegate has been cut off.
Custom command descriptors are attacker-influenced input. A hostile or compromised host can publish a descriptor whose description misrepresents what the command does. Section 8.3 requires descriptors to be treated as untrusted and forbids them from weakening confirmation. A client that renders a description as instructions to an agent has reintroduced the injection problem from a different direction.
Reserved verbs are reserved for a reason. A client that implements /escrow with locally invented semantics creates the exact interoperability failure this document exists to prevent, with funds at stake. Section 6 requires such verbs to be reported as unsupported.
Implementations
- Every command in section 5 is implementable today against the BRC-169 stack and the reference
@bsv/sdkand@bsv/wallet-toolboxcomponents. No command in section 5 requires a mechanism that BRC-169 does not define, which was the criterion for including it here rather than reserving it in section 6. - A minimal conforming client implements the section 2 grammar, the section 4 confirmation rules, and
/pay,/message, and/whois. Everything else is independently optional, provided unimplemented verbs are reported as unsupported rather than repurposed. - Ecosystems adopting custom commands are encouraged to publish descriptors from launch, so that foreign clients can explain an unavailable command rather than failing silently.