In-Chat Commands
These commands work inside chat channels and interactive agent sessions:
| Command | Description |
|---|---|
/new | Stop the current task and start a new conversation |
/stop | Stop the current task |
/restart | Restart nanoinfra |
/status | Show the running nanoinfra version and model, what the last turn cost in tokens, context use, session message count, uptime, and the number of active tasks |
/model | Show the current model and available model presets |
/model <preset> | Switch and persist the model preset for the current session |
/dream | Run Dream memory consolidation now |
/dream-log | Show the latest Dream memory change |
/dream-log <sha> | Show a specific Dream memory change |
/dream-restore | List recent Dream memory versions |
/dream-restore <sha> | Restore memory to the state before a specific change |
/dream-prompt | Show the instructions that guide Dream for memory |
/dream-prompt init | Create an editable Dream memory guide at prompts/dream.md |
/skill | List enabled skills and their descriptions |
/trigger | Show local trigger usage |
/trigger <name> | Create a named local trigger for the current chat session |
/pairing | List pending pairing requests |
/pairing list | List pending pairing requests. /pairing with no subcommand does the same |
/pairing approve <code> | Approve a pairing code |
/pairing deny <code> | Deny a pending pairing request |
/pairing revoke <user_id> | Revoke a previously approved user on the current channel |
/pairing revoke <channel> <user_id> | Revoke a previously approved user on a specific channel |
/approve <request-id> | Approve one suspended remote action |
/deny <request-id> <reason> | Refuse one suspended remote action |
/help | Show available in-chat commands |
Pairing
nanoinfra automatically replies with a pairing code (like ABCD-EFGH) when someone sends it a DM and is not on the allowlist. This covers a new user, and an existing user on a new channel. The code expires in 10 minutes. To grant them access:
/pairing approve ABCD-EFGH
To see who is waiting, use /pairing. To remove someone later, use /pairing revoke <user_id>. The /pairing list output holds the user IDs.
See Configuration: Pairing for the full setup guide.
Approve or Refuse a Suspended Action
The capability gate suspends an unusual remote action and waits for a person. nanoinfra sends the suspended action to every approver who may answer it, with the command and the host list the executor rendered. Answer with the request id it carries:
/approve 0123456789abcdef
/deny 0123456789abcdef this host is in a maintenance window
Three things to know before you rely on this:
- A pairing approval is not an approval here.
/pairingdecides who can reach nanoinfra.gates.approversdecides whose answer counts, and it lives in config that a git review covers. An approver needs both. - You cannot answer a request your own chat raised. The answer has to arrive on a path other than the one that asked. That rule is the point: one compromised account must not hold both halves.
- The model never sees either command. Both run before the turn reaches a model, so the text stays out of the conversation.
Read Capability Gates: Answer From a Chat Channel for the identity rules and for how to add a second channel.
Model Presets
Use /model to inspect the current runtime model:
/model
The response shows the current session's model and preset, plus the available preset names. Named presets come from the top-level modelPresets config and are the recommended way to configure model choices. default is always available and represents the model settings from direct agents.defaults.* fields.
To switch presets for future turns:
/model fast
/model deep
/model default
Preset names come from the top-level modelPresets config. Switching affects only the current session and persists the selection in that session, so later turns keep using it across process restarts. It does not rewrite config.json, does not change other sessions, and does not alter an in-progress turn's captured model. Sessions without a saved selection follow agents.defaults.modelPreset (or the implicit default preset when it is omitted). See Configuration: Model presets for setup details.
Local triggers
Use /trigger <name> when a local script or another service must send a message
into the current chat session later. You must give a name. Plain
/trigger only shows the usage hint.
Create the trigger from the chat where future messages should arrive:
/trigger PR review
nanoinfra replies with a trigger ID and a command shaped like:
nanoinfra trigger trg_8K4P2Q9X "Review PR #4502"
The reply also states that the trigger is not rehearsed. nanoinfra runs a scheduled
automation once at creation and previews every gated action, so you learn the
permission it needs before its schedule does. A trigger carries no stored
message, because its content arrives from whoever fires it. Rehearsing an invented
message would propose a standing grant for a command the real firing may never
use, so nanoinfra says so instead of guessing. Fire it once while you are watching
to learn what it needs. See
automations.md#creating-one-rehearses-it.
Replace "Review PR #4502" with the message you want nanoinfra to receive. nanoinfra
binds the trigger to the session where you created it, so the message goes back
to that same chat. Keep nanoinfra gateway running so nanoinfra can deliver trigger
messages. The trigger message starts an automation turn recorded in that
session with the message you passed to the CLI. nanoinfra does not treat it as a
normal user message. If that session is already running a turn, the trigger waits
until the session is idle rather than joining the active turn.
nanoinfra stores trigger deliveries in the workspace until their linked agent turn finishes successfully. If nanoinfra exits after claiming a delivery but before the turn completes, the next start requeues that delivery. This is an at-least-once local queue. A delivery may run more than once if the process exits at the wrong time, so external scripts should make repeated trigger messages safe. If the delivery reaches nanoinfra and the agent turn fails, Automations marks the delivery failed instead of retrying forever.
For longer or generated content, omit the message argument and pipe stdin:
printf '%s\n' "Review the latest failed CI job" | nanoinfra trigger trg_8K4P2Q9X
If an external webhook should send a message into nanoinfra, run your own small webhook service. Have it call the trigger command after it builds the final message:
nanoinfra trigger <trigger-id> "<message>"
If you run multiple nanoinfra instances, pass the same config or workspace selector used by the gateway:
nanoinfra trigger --config ./bot-a/config.json trg_8K4P2Q9X "Nightly report"
nanoinfra trigger --workspace ./bot-a/workspace trg_8K4P2Q9X "Nightly report"
Manage triggers from the WebUI Automations view. You can search, pause, resume, rename, delete, and copy the trigger command there. A session may have multiple triggers, just like it may have multiple scheduled automations.
See Automations for how local triggers fit with scheduled automations, heartbeat, and gateway delivery.
Periodic Tasks
The heartbeat is not a chat command. It is a protected cron job nanoinfra registers, and
HEARTBEAT.md in your workspace drives it. It is the one automation type you edit as a
file rather than create from a chat.
See Gateway Heartbeat for the interval, the
notification gate and keepRecentMessages. See
Choose an Automation Type for when a
heartbeat is the right choice rather than a scheduled automation.
Setup: edit ~/.nanoinfra/workspaces/default/HEARTBEAT.md. nanoinfra onboard creates
it for you:
## Active Tasks
- Check weather forecast and notify me only if storms are expected
- Scan inbox for urgent emails and notify me if any are found
nanoinfra can also manage this file itself. Ask it to "add a periodic background check", or to "check this periodically but only notify me if something changes", and it updates HEARTBEAT.md for you. Delete completed tasks from the file rather than moving them to another section.
You can change the interval or disable the built-in heartbeat in ~/.nanoinfra/config.json:
{
"gateway": {
"heartbeat": {
"enabled": true,
"intervalS": 1800
}
}
}
The heartbeat job appears in cron(action="list") as heartbeat, but nanoinfra manages it and the cron tool cannot remove it. To stop it, set gateway.heartbeat.enabled to false and restart the gateway.
Note: nanoinfra must be running (
nanoinfra gateway). You must also have chatted with nanoinfra at least once, so it knows which channel to deliver to.