terms

The words this site uses, grouped by area. Each entry says what the term is, then how it differs from what the word usually means. Every definition follows the spore repository or mohdel's README.

what a spore is

termwhat it ishow it differs
sporeAn AI agent kept as a folder, its workspace, with a spore.cmk file at its root that says what the agent is. spore is also the name of the runtime that runs these agents.Not a process or a service. A message starts a turn and the turn exits; an idle spore runs nothing, so a million idle spores cost only the disk they take. A spore is named by its folder, not by the name its file declares.
definition, spore.cmkThe text file that declares an agent: key: value lines between two --- lines — its model, tools, limits and grants — then a body, the agent's identity: the whole of what it is told it is, addressed to it as “You …”.Not a configuration file with defaults. The grammar has no nesting and no defaults: an unknown field, a key written twice or a missing limit is refused, and the message names it. description is for a person and is never told to the model.
workspaceThe spore's folder. It holds the definition, a SQLite database with every record, the files sent with messages, and the folders the agent works in: data/ for what it makes, data/out/ for what it means to hand back, home/ as its own $HOME.Not your project directory. A directory of yours is reached only when the definition grants it: reads links it in read-only, writes links it in to be changed in place. spore here makes a spore granted writes on the directory you are in.
write islandsThe folders of its own workspace an agent may write: data/, calls/, precursors/ and home/, and schedules/ when its definition grants schedules.The rest of the workspace is read-only to the agent, its spore.cmk and its database among it: an agent cannot rewrite who it is or what it did. Beyond the islands it writes the directories its definition writes.
operatorThe Unix user spore runs as, who writes ~/.config/spore/, the definitions and the host's settings. On your own machine, that is you.The operator is trusted and the agent is not. spore confines what the agent runs and follows what the operator wrote. the principles
trust boundaryThe line between what spore trusts and what it confines. It is the operator's Unix user.It is not drawn between spores or around the machine. Another process of the same user that spore does not confine can read every workspace and every key, and spore does not defend against it; spores of one user can reach each other through UDP ports and unix sockets. where the boundary stops
pausedThe state of all of a user's spores after spore pause: every running turn and job is stopped, and none starts. spore unpause lifts it.It holds every spore of the user, not one. A message sent meanwhile is refused, not queued, and nothing of it is recorded. A stopped turn is not resumed: what it had not answered is read by the next turn. spore ls, spore show and Telegram's /status say the spores are paused.
dreamingThe state of a spore while it dreams: the tick hands the idle spore to a precursor it names — a sub-agent's definition — which puts its workspace in order — writes down what the conversation says that its memory notes do not hold, removes what can be made again and serves nothing, groups the rest — and leaves the conversation a note.Only a spore whose spore.cmk declares dream dreams, and only once left alone after enough work, never in the middle of a conversation. A dream holds the spore: a message sent meanwhile waits for its end. It has cost and wall limits of its own, and the runtime itself never deletes anything in data/.

how a turn runs

termwhat it ishow it differs
turnThe agent's work on one message, from the message to the end: every round and tool call between. It ends with an answer, a question (ask), nothing to say (quiet), at a limit, stopped from outside, or on an error.Not one request and one reply. A message sent while a turn runs is not held for a new one: it lands in the running turn between two rounds. A turn runs in the background and outlives the program that started it.
roundOne model call within a turn. The model answers or asks for tool calls, and every tool returns before the next round.Rounds are counted at the model broker, not reported by the agent: a retry is another round, and an embedding is not one. The quiet between two rounds is where a message sent mid-turn is read and where the soft limits are checked.
limitsThree bounds every definition sets per turn, each a [soft, hard] pair: rounds, the model calls; cost, in dollars; wall, the elapsed time.Soft and hard do different things: past a soft limit the agent is told to answer with what it has and say what remains; past a hard one the turn stops and a continuation record is written. None has a default. A hard limit can be raised during a turn only up to the extend.* ceiling its spore.cmk grants.
sandboxThe confined space a turn runs in, enforced by the Linux kernel: Landlock limits the files the agent and its commands reach; user, PID and mount namespaces of the turn's own let it see only the processes it started; a syscall filter refuses requests such as mounting.The boundary is not the tool list. Confinement that was asked for and did not happen stops the agent rather than letting it run unconfined. The network is open by design: the sandbox bounds what an agent reads and writes, not where it connects. what confines a turn
contain, unconfinedThe two switches that take parts of the sandbox away. contain is the host's setting, on unless set: it puts each turn in namespaces of its own. unconfined: true in one spore's spore.cmk starts that spore's agent with no Landlock, no syscall filter and no namespaces.Both are set on purpose, never fallen back to: with contain on, a host that cannot make the namespaces runs no turn, and a definition cannot change the setting. unconfined frees only the spore's own agent; its cells, jobs and routers stay confined.
runnerThe process on the host's side of a turn: it holds the workspace's lock, the provider keys and the brokers, and starts the confined agent.The agent is a separate, confined process that reaches the model only through the runner's socket. The runner is started detached, so the turn outlives the terminal that asked for it, and it lets go once nothing is left unread, so nothing of a spore runs between its turns.
brokerA go-between in the runner that makes a call for the agent and holds its credential. The model broker makes the model calls; the source broker calls the endpoints a definition names.Not a proxy server you deploy: it lives in the turn's runner, and accepts only a key minted for that one turn. The model broker also enforces: it refuses any model the definition does not name, and new calls once settled spend reaches the hard cost.
sourcesEndpoints a spore calls by name. Its definition lists the names in sources; the host's ~/.config/spore/sources.json, or a plugin, says what each means: the URL and its credential.A source is about the credential, not about network access: the network is already open to the agent. The URL and the secret stay with the source broker. A definition can narrow what a source may be asked for, to exact values or paths.
eventsThe log of what each turn does — its rounds, its tool calls, the model's output as it comes — each event numbered, in the workspace's database.Appended out of the agent's reach, and the one way anything watches a spore: the TUI, a chat plugin or your own program keeps one number, the last event it read, and asks again from there. A watcher that disconnects loses nothing. Event names never change meaning; fields are only added.
the recordEverything kept about a spore, in one SQLite file in its workspace, state.sqlite: the inbox of what was said to it, its turns, the transcript, the events and every tool call.The agent reads its record and cannot rewrite it: its writes go through one channel the runner holds, and the file is never writable to it. retain prunes older turns' call records and events; the inbox, the turns and the transcript are never pruned. No database server: the record is a file in the folder.
toolsThe seven built-in actions a model can call: read, write, edit, exec, wsexec, ask and quiet. A definition's tools lists those offered.The list shapes what the agent reaches for and bounds nothing; the sandbox bounds. exec runs a command read-only, wsexec may write the workspace, and ask and quiet end the turn. There is no fetch tool: the agent writes programs, and the programs do the work.
pluginsnpm packages named spore-plugin-<name> that add what the runtime does not ship: programs an agent may run, sources, documentation, and services such as the Telegram and Discord bots. Every plugin, with its README, is on plugins.A plugin adds no tool and no hook: spore reads its manifest and runs none of its code of its own accord. A plugin a spore uses must be allowed on the machine, spore plugin allow, and named in its plugins.
cell, precursorA cell is a sub-agent a spore starts when work has many similar parts. A precursor, a .cmk file in the spore's precursors/, is the definition a cell is made from.A cell has only the tools its precursor grants, a folder of its own, and cannot start cells. Its model is a name from the spore's cell-models; the model broker refuses any model the spore's file does not name. The spore's cost covers its cells' calls.
enzymesPrograms of the spore that a cell may run by name, granted by its precursor and described to the cell in an :::enzyme block.Not a tool: it has no entry among the model's tools. The cell runs it by name through exec or wsexec and never sees its path or file, and a call is refused once the program has changed since the cell started. Enzymes exist only in cells.
jobWork a turn starts that outlives it: a long scan, a download, a build. A spore starts jobs only when its spore.cmk grants jobs: [count, wall].Everything else a turn starts is swept when the turn ends; a job is the explicit exception. It is bounded by its own wall, runs in namespaces of its own, and its end reaches the spore as a message, not something polled.
routerA program a spore may keep for messages no person typed — a webhook's delivery, a job's message, a program's call through the API — that answers how long each may wait before the spore is told.The judgment is the spore's, the bound the operator's: the router proposes a wait, and the operator's cap, such as jobs.maxWait, limits it. Like a turn, it runs in namespaces of its own.

talking to a spore

termwhat it ishow it differs
TUIspore tui, a terminal user interface: one spore per screen, its conversation from the record, the running turn from its events, a status line with its state, limits, spend and model. spore here opens it on the spore that works in the directory you are in.It keeps no conversation of its own: it uses only the library's exports, so a conversation started there continues from Telegram or the command line. It is always installed: an install made with --omit=optional leaves out the core, not the screen. the terminal, step by step
serviceA program spore runs for you as a systemd user unit, a service systemd runs for your user, under ~/.config/systemd/user/. spore ships some, such as tick and api; a plugin can offer more, such as Telegram's, one instance per bot: telegram@<bot>.Unlike a spore, a service is a process left to systemd, restarted on failure. Defining one runs that plugin's program on the host, outside every sandbox. A chat service holds its bot's token; no bot's token is passed to a spore's runner. spore service define checks before it writes the unit, and spore never touches a unit it did not write.
once, at least onceWhat the Telegram and Discord plugins guarantee: a message reaches its spore once; a finished turn reaches its chat or channel at least once.The two directions differ on purpose. An answer waits in the spore's outbox until the chat has accepted it, so a crash between the two can repeat a message but not lose one.
schedule, tickA schedule is a file in the spore's schedules/: a message the clock says to it, and when. The tick is the service that runs every minute and fires every schedule that is due.A scheduled message takes the same inbox as any other: nothing in the runner or the brokers knows a turn was scheduled, and the agent learns it from the message. The agent writes its own schedules only when its spore.cmk grants schedules, within a count and an interval.
vmThe Linux VM (virtual machine) spore runs in where it cannot run on the machine itself: always on macOS, and on Linux when the first spore setup is told so. spore setup makes it with Lima from Debian 13, brings it to the host's Node and the same spore, and names it in vm.json, beside config.json.It is not a sandbox around a turn: inside it, spore confines each turn as on any Linux. Every command but setup and vm runs in it, through limactl shell; nothing but spore vm start and spore setup starts it, and a command given while it is stopped does nothing. The model and its key are chosen inside it, so the host never holds a key. the macOS path
LimaA tool that runs Linux VMs, driven by its limactl command. spore uses it to make, start, stop and enter its vm.It is not part of spore and spore does not install it: it must be on your path first, or spore setup stops and points to Lima's installation page.
WSLWindows Subsystem for Linux, Windows' own way of running Linux. On Windows, spore runs in it.Unlike the vm on macOS, spore does not prepare it yet: you set WSL up yourself and install spore inside it as on Linux. the Windows path

money and models

termwhat it ishow it differs
spendWhat a spore's model calls cost, in US dollars, as mohdel computes it for each call. spore settles it — counts and records it — turn by turn.Computed from your catalog's prices, not read from the provider's invoice: a model with no prices there counts as $0 against cost. Once settled spend reaches the hard cost, new calls are refused; a call already running finishes and is paid. On a ChatGPT plan, spend reads not metered · <label>.
catalog, pricing catalogmohdel's list of the models you use, with their prices, in your own ~/.config/mohdel/curated.json. Each call's cost is computed from it.Yours, not the provider's: almost no provider API returns prices, so entries are written on your machine — by mo curate, from a brief a coding agent you already run reads, or by hand — and can carry your negotiated rates. A model in the catalog is not yet one a spore uses: its spore.cmk must name it.
/curateThe TUI command for a model the catalog lacks: /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.It only adds the model to the catalog. A spore uses it once its spore.cmk names it in model, models or cell-models. a model the catalog lacks
mohdelThe library spore talks to models through, with the mo command: a self-hosted LLM (large language model) gateway and SDK for Node.A separate package, not part of the agent: the runner calls it, and the agent never sees its keys. The runner looks for a key where mo does, so a machine where mo works runs spores with no key copied.
gatewayThe one place your code sends model calls to instead of each provider; mohdel turns each call into the provider's own API call, with your key.Not a hosted service: it runs on your machines, in your own process to start with, with no SaaS proxy — no third-party hosted service — in the path. thin-gate, an optional supervisor, is the cross-process form, so a crashing provider library cannot take your service down; the API is the same.
SDKSoftware development kit: here, the mohdel npm package your Node code imports to call any model.Inference only. It returns the model's output and tool calls for your program to handle, and has no agents, memory, retrieval or prompt templates. It never retries and never swaps models: those choices are the caller's.
providerA company or service that runs models behind an API: Anthropic, OpenAI, Gemini, OpenRouter and others, fifteen through mohdel. A model is named <provider>/<name>, as anthropic/claude-sonnet-5-5.The prefix names the way a model is reached and paid for, not only the company: chatgpt/ uses a ChatGPT plan, while openai/ uses API billing.
ChatGPT planAn eligible ChatGPT subscription used in place of an API key: mo chatgpt login signs in, and models are called as chatgpt/<model>.Its calls report zero cost, which means no per-call API charge is computed, not that use is unlimited or free. So a spore's cost limits never stop it on a ChatGPT plan, while rounds and wall still do.
answer()mohdel's one call to a model, for every provider. It returns { status, output, inputTokens, outputTokens, cost }.The result has the same shape whatever the provider, and cost is in US dollars, computed from your catalog, on every result. Switching models is changing one string.