The sithbit campaign CLI (participant beacons & campaigns)
The sithbit campaign command tree is the chain-direct authoring surface for
the participant-pool marketplace: a wallet
publishes an on-chain participant beacon advertising the tags it is willing
to be reached on, and a campaign wallet discovers those participants by tag,
prices a bountied send to the matched set, and sends it.
Two roles use this tree:
- A participant runs
create,updateandcloseto opt in, edit and opt out. Opting in is setting a mailbox price: the advertised participation price is the wallet’s mailboxdefault_postage, so a beacon can only be published for a wallet that already has a mailbox. - A campaign wallet runs
search,quoteandsendto reach the pool.sendis direct-signed only — the funded campaign wallet signs every delivery locally; there is no mail-server path for a campaign.
sithbit campaign create [--tag <TAG>]… [--detail-cid <CID> | --profile-file <PATH>] [-k <KEY>]
sithbit campaign update [--tag <TAG>]… [--detail-cid <CID> | --profile-file <PATH>] [-k <KEY>]
sithbit campaign close [-k <KEY>]
sithbit campaign search --tag <TAG>… [--limit <N>]
sithbit campaign quote --tag <TAG>… --bounty <LAMPORTS> [--postage <LAMPORTS>] [--limit <N>]
sithbit campaign send --tag <TAG>… --subject <TEXT> --bounty <LAMPORTS> \
[--body-file <PATH>] [--limit <N>] [-y] [-k <KEY>]
Tags
Every beacon carries a fixed-vocabulary tag bitmap. A --tag is one name from
that vocabulary — an interest.*, skill.*, age.* or region.* name, e.g.
interest.technology, skill.software, age.25_34, region.apac. Names are
case-insensitive; an unknown name is rejected with the full valid list. --tag
is repeatable, and search/quote/send treat multiple tags as a logical AND —
a beacon must carry every requested tag to match. The vocabulary is derived
from the mail_model TAG_* constants; see the
participant-marketplace note
for the bitmap layout.
sithbit campaign create
Publishes the signing wallet’s participant beacon, opting it in on the given
tags. The wallet’s mailbox must already exist — the advertised price is its
default_postage.
sithbit campaign create \
--tag interest.technology \
--tag skill.software \
--tag region.apac
Flags:
--tag <TAG>— a tag to advertise on (repeatable).--detail-cid <CID>— attach an existing IPFS CID as the beacon’s off-chain detail profile. Mutually exclusive with--profile-file.--profile-file <PATH>— seal a local profile file under a fresh key, pin it to IPFS, and attach the resulting CID. Needs the CLI’srandfeature. See--ipfs-endpoint/--ipfs-tokenbelow.--ipfs-endpoint <URL>— thesithbit-ipfsdendpoint a--profile-fileis pinned to (defaulthttp://127.0.0.1:8182).--ipfs-token <TOKEN>— bearer token for that daemon, when it requires one.-k, --keypair <KEY_PATH>— the wallet publishing the beacon (defaults to the Solana CLI keypair).-s, --skip-preflight— skip the transaction pre-flight simulation.
sithbit campaign update
Rewrites the beacon wholesale: the given tags and detail CID replace its
current contents in full — this is a replace, not a merge, so omitting --tag
clears all tags and omitting a CID clears the attached profile.
sithbit campaign update --tag interest.finance --tag region.emea
Takes the same flags as create.
sithbit campaign close
Closes the signing wallet’s beacon — the opt-out. It drops out of every tag search and its rent is refunded to the wallet.
sithbit campaign close
Flags: -k, --keypair <KEY_PATH>, -s, --skip-preflight.
sithbit campaign search
Runs a trustless getProgramAccounts scan of the mail program for beacons
carrying every requested tag, and lists each match’s sendable wallet, its tag
names, and whether it advertises a detail profile. The wallet is recovered from
the beacon’s on-chain owner field (a beacon PDA can’t be inverted to it), so
the results are directly mailable.
sithbit campaign search --tag interest.technology --tag skill.software
2 matching participant beacon(s):
mAiLiLdgjgGdWoCZkpW3cj7JLAC56qb4NErFyQFWNJg [interest.technology, skill.software] detail: yes
CaMUbt4zNKeZb2AUaa4icv33CQEvBeJ8EsWKFsDvKWrT [interest.technology, skill.software, region.apac] detail: no
Flags:
--tag <TAG>— a tag a beacon must carry to match (repeatable, required, logical AND).--limit <N>— cap the number of matches returned (default 100). The newest beacons are kept first.
sithbit campaign quote
Prices a campaign before committing funds. It counts the beacons matching the
tag filter (the same trustless scan search runs) and multiplies by the
per-recipient cost, itemized so you see where the money goes. The per-recipient
figure mirrors the on-chain SendMail funding term for term: the message
account rent, a new frombox’s rent, the prepaid postage, the escrowed bounty,
one signature fee, and the per-stamp settlement surcharge.
sithbit campaign quote --tag interest.gaming --bounty 1000000
Campaign quote for 3 recipient(s):
message rent 1670160 lamports
frombox rent 1224960 lamports
postage 1000000000 lamports
bounty 1000000 lamports
signature fee 5000 lamports
stamp surcharge 10000 lamports
per recipient 1003915120 lamports
total 3011745360 lamports (3.01174536 SOL)
Flags:
--tag <TAG>— recipient tag filter (repeatable, required, logical AND).--bounty <LAMPORTS>— the per-recipient bounty being offered.--postage <LAMPORTS>— the per-recipient postage the quote assumes; defaults to the protocol default a mailbox charges unknown senders. Lower it toward the price you expect recipients’ fromboxes to actually charge.--limit <N>— cap the quote at this many recipients (default: the full match set).
sithbit campaign send
Sends one bountied message to every recipient matching the tag filter. It
selects recipients by the same trustless scan, prints the quote,
gates on a confirmation (unless -y), then delivers the batch — one
direct-signed SendMail per recipient, each escrowing
the per-recipient reply bounty with the campaign message
as the parent a recipient replies to. The loop continues past a per-recipient
failure so one bad address can’t strand the rest of a paid campaign, and
prints a sent/failed summary at the end.
sithbit campaign send \
--tag interest.gaming \
--subject 'Paid gaming survey' \
--bounty 1000000 \
--body-file ./invite.txt \
--yes
Campaign quote for 3 recipient(s):
…
sent to mAiLiLdgjgGdWoCZkpW3cj7JLAC56qb4NErFyQFWNJg https://explorer.solana.com/tx/…
sent to CaMUbt4zNKeZb2AUaa4icv33CQEvBeJ8EsWKFsDvKWrT https://explorer.solana.com/tx/…
sent to maiLtdkxym8CCmo9TwDuXywqd9DXaK3tB6toKFVeBFR https://explorer.solana.com/tx/…
Campaign complete: 3 sent, 0 failed.
Flags:
--tag <TAG>— recipient tag filter (repeatable, required, logical AND).--subject <TEXT>— the message subject line.--body-file <PATH>— the message body; read from stdin when omitted.--bounty <LAMPORTS>— the per-recipient bounty escrowed for each recipient to claim. The claim window is the standard 7-day bounty default.--limit <N>— cap the send at this many recipients (default: the full match set).-y, --yes— skip the quote-then-confirm prompt and send immediately.-k, --keypair <KEY_PATH>— the sending (and funding) wallet.-s, --skip-preflight— skip the transaction pre-flight simulation.
Recipients collect a bounty by replying before the window closes; anything unclaimed can be refunded to the campaign wallet after it expires.