use a spore
A spore is an AI agent declared in a short file, spore.cmk, and kept in a folder of
its own. Every turn — the agent's work on one message — and every message and tool call lands in
a database in that folder. spore setup makes a first spore, called main. This page shows three ways to talk to it, simplest first: a terminal screen
on the machine, a Telegram bot, and a Discord channel. Every plugin and package, with its
README, is on plugins.
the terminal
You are on the machine where your spores live. You want to ask one something, read what it
answered yesterday, or watch the turn it is running now. spore tui opens a TUI (terminal
user interface): one spore per screen.
- Open a spore by name.
spore tuiwith no name opens the last one opened.spore tui main - Read back. The screen replays the conversation from the spore's records. A turn that is running shows live, from its events — the log of what the turn does.
- Type a message and press Enter. While a turn runs, the message is not held for a new one: it lands in the running turn between its rounds, a round being one model call. Alt+Enter makes a new line; Esc Esc stops the running turn.
- Watch the status line, under the line you type on: the running turn's limits, the spend and the model. The line you type on names the spore and its state at its right. When another spore answers or asks, the status line says so and the terminal gets a notification.
- Type
/for the slash commands, commands typed in the message line:/stop /wrap /extend /model /curate /pause /unpause /spores /status /copy /help /quit/copy [<n>]copies the last answer, or its code blockn. A message that itself starts with/is typed//text. - Press Ctrl+P to open another spore in the same screen. Ctrl+D on an empty line leaves.
spore here, from the install page, is the same
screen, opened on the spore that works in a directory.
a model the catalog lacks
Models are known through mohdel's catalog: the models mohdel (the mo command) has
entries for, with their prices. spore doctor notes a model with no prices there;
its calls then count as $0 against the spore's cost limit. In the screen, /curate [<provider>] opens a picker over what the provider lists beyond the
catalog, with its prices, and mohdel's curate writes the one you pick. Outside it, mo curate <provider> asks for what an entry is missing. Either only adds the
model to the catalog: a spore uses it once its spore.cmk names it in model, models or cell-models.
when the core is missing
The screen is always installed with @rhizogrip/spore-cli: the package @earendil-works/pi-tui 1.2.0. What is optional is the core, @rhizogrip/spore, which runs spore on the machine; npm installs it only on Linux
x64 and arm64. A server install made with --omit=optional, to leave extras out,
leaves out the core, not the screen. On Linux, spore setup then makes a VM to run spore
in, and every other command stops and says:
spore: this install has no @rhizogrip/spore, which runs spore on this machine — it is built for x64 and arm64 and left out by --omit=optional; npm install -g @rhizogrip/spore-cli adds it, or spore setup runs spore in a vm To add the core, install again without that flag:
npm install -g @rhizogrip/spore-cli Every key and command is in the terminal's README in the spore repository.
Telegram
You want to reach a spore from your phone. You write to a Telegram bot in a private chat; the
message goes to the spore your Telegram user id is mapped to, and the answer comes back in the
same chat. The plugin @rhizogrip/spore-plugin-telegram is a service that runs on
the machine the spores are on, once per bot, as a systemd user unit: a service systemd runs for
your user, defined under ~/.config/systemd/user/. It gives spores nothing, so it
needs no spore plugin allow.
- Install the plugin.
npm i -g @rhizogrip/spore-plugin-telegram - Get the bot's token from @BotFather on Telegram, and add it to
~/.config/spore/environment, the file where spore keeps keys:
The service reads the token there, and it never reaches a spore. The file takes plainecho 'TRIAGE_BOT_TOKEN=…' >> ~/.config/spore/environmentKEY=valuelines, with noexport; it holds keys, so keep it mode 0600. - Write the bot file. Each bot is one file,
~/.config/spore/telegram/<bot>.json; here the bot istriage.mkdir -p ~/.config/spore/telegram~/.config/spore/telegram/triage.json:{ "token": "${TRIAGE_BOT_TOKEN}", "people": { "148392011": "triage" } }tokennames the variable from step 2.peoplesays who may talk to the bot in private and which spore each reaches, as a Telegram user id and a spore's name. A chat not in the file gets silence, and the service's log gets the line to add. That is also how you learn your own user id: start with"people": {}, message the bot, and read the log (step 4):refused chat 148392011 (@alice) — to allow it, add "148392011": "<a spore>" to the people of …/telegram/triage.json - Define and start the service.
spore service define telegram@triagespore service start telegram@triagedefinechecks the bot file and its token, then writes the unit: the template~/.config/systemd/user/[email protected], with each bot an instance of it,telegram@<bot>.startruns it now;spore service enable telegram@triageruns it at every login;spore service log telegram@triage -ffollows its log.spore service lssays where each service stands and whether lingering is on — without it, user services stop when you log out. Without its bot file, without the token the file names, or without a Telegram that answers the token, the service refuses to start, with exit status 2 and the line to fix. - Write to the bot in private. It posts
working…and shows which tools run as they run. When the turn ends, the answer arrives as a new message replying to yours, so it notifies you however long the turn took. Files the turn left indata/out/follow as documents. In the chat:/status— what the spore is doing, its turns and what they cost/stop— end the turn it is running, and set aside what you sent that it had not read/wrap [10m]— ask the running turn to wrap up, now or in a while/extend wall 30m— give it more wall time, cost or rounds, up to what itsspore.cmkgrants/flush— start the conversation over from the next turn; nothing is forgotten
what it guarantees
- A message reaches its spore once. Telegram may hand the same message over again; the service passes each one on under its Telegram update id, so the spore is not told it twice.
- A finished turn reaches its chat at least once. What the turn owes the chat waits in the spore's outbox until Telegram has accepted it. A crash between the two repeats a message; it does not lose one.
Groups, files, approvals and every option are in the Telegram plugin's README in the spore repository.
Discord
Your team already talks in a Discord channel. Spores join it beside the people: each spore has a
role, so @triage reaches it the way a person is reached, and each answers under its
own name. One channel holds many people and many spores. The plugin, @rhizogrip/spore-plugin-discord, runs on the machine the spores are on, as a
systemd user unit.
- Install the plugin and allow it.
Unlike Telegram's, this plugin gives spores something:npm i -g @rhizogrip/spore-plugin-discordspore plugin allow discord$SPORE_DISCORD, with which a spore reads what was said in the channel before it was addressed.spore plugin allowchecks the plugin, then records it inconfig.jsonamong the plugins allowed on this machine. - Make the bot in the Developer Portal, and turn its Message Content intent on. Without it, Discord sends the bot
every message empty, except those that mention the bot itself — and people mention a spore by
its role, not the bot. Invite the bot to the server with these permissions: View Channels,
Send Messages, Read Message History, Manage Webhooks and Manage Roles. Its token goes in the
environment file, and never reaches a spore:
echo 'DISCORD_BOT_TOKEN=…' >> ~/.config/spore/environment - Name the channels. The bot file, here
ops, says which spores answer in which channel and who may address them.mkdir -p ~/.config/spore/discord~/.config/spore/discord/ops.json:{ "token": "${DISCORD_BOT_TOKEN}", "channels": { "1234567890": { "spores": ["triage", "ledger"], "people": ["111111111111", "role:222222222222"] } } }channelsis the routing: the bot ignores every channel the file does not name. For each spore inspores, the bot finds or makes a mentionable role of that name.peoplelists who may address them: user ids,role:<id>for everyone holding a role, or"*"for anyone in the channel. Someone else gets silence, and the log gets the line to add. The file is read on every message, so adding a channel, a spore or a person is editing a line. - Define and start the service.
spore service define discord@opsspore service start discord@ops - Say which channel history each spore may read. The bot can see more channels than a spore
should read, so each spore in a channel names, in its
spore.cmk, the channels whose history it reads, and a turn is refused without them:plugins: [discord] sources: [discord] discord.path: [<channel id>/messages]plugins:gives the spore$SPORE_DISCORD.sources:lists the sources it may call — endpoints a spore calls by name through spore's source broker.discord.path:lists the channels whose messages it may read. - Address a spore: mention its role,
@triage, or reply to one of its posts. A message addressing two spores goes to both. The spore posts@you ↪ "what you said…" working…, and when the turn ends posts its answer under its own name, opened with whom it answers. In the channel,@triage status,@triage stop,@triage wrap 10m,@triage extend wall 30mand@triage flushwork as the Telegram commands do. Stopping, wrapping, extending and flushing are for the people the channel lists by id or role, not for everyone"*"lets talk.
As with Telegram, a message reaches each spore it addresses once, and a finished turn reaches
its channel at least once; a post repeated after the service stopped opens with (this may repeat an earlier message).
Channel options, files and what the service keeps are in the Discord plugin's README in the spore repository.
Slack and Teams
Your team talks in Slack or Microsoft Teams instead. A plugin puts your spores there the same way: a person's own chat with the bot reaches their spore, and a channel reaches its spore when someone there mentions the bot. Each runs on the machine the spores are on, once per bot, as a service. Setting up the bot, the people and the channels is in the Slack plugin's README and the Teams plugin's README.