yummy is a Mattermost bot bridge for pi and codex CLIs with:
- single-post progress updates (edits one bot message as work runs)
- stateless resume tokens (
/sessions,/resume) - per-channel and per-thread engine/model/reasoning preferences
- optional OAuth login helpers for OpenAI Codex and GitHub Copilot
Credit to the original pi project by Mario Zechner and contributors:
- Node.js 20+
- Mattermost bot account + token
piand/orcodexCLI installed and authenticated
npm ci
npm run build
export YUMMY_URL="https://mattermost.example.com"
export YUMMY_TOKEN="YOUR_BOT_TOKEN"
export YUMMY_DEFAULT_ENGINE="pi" # pi|codex
export YUMMY_ALLOWED_USERS="alice,bob,@carol" # strongly recommended
node dist/main.js /var/lib/yummyYUMMY_URL/YUMMY_TOKEN can also be set as MM_URL/MM_TOKEN.
Core:
| Variable | Required | Description |
|---|---|---|
YUMMY_URL |
yes | Mattermost base URL (for example https://mattermost.example.com) |
YUMMY_TOKEN |
yes | Mattermost bot token |
YUMMY_DEFAULT_ENGINE |
no | pi (default) or codex |
YUMMY_ALLOWED_USERS |
no | Comma/space-separated allowlist of usernames or user IDs |
PI runner:
| Variable | Required | Description |
|---|---|---|
YUMMY_PI_CMD |
no | CLI command path (default pi) |
YUMMY_PI_MODEL |
no | Default model |
YUMMY_PI_PROVIDER |
no | Provider passed to pi --provider ... |
YUMMY_PI_EXTRA_ARGS |
no | Extra CLI args |
YUMMY_PI_SESSION_DIR |
no | Explicit session directory |
YUMMY_PI_THINKING |
no | `off |
YUMMY_PI_TITLE |
no | Display label in progress UI |
Codex runner:
| Variable | Required | Description |
|---|---|---|
YUMMY_CODEX_CMD |
no | CLI command path (default codex) |
YUMMY_CODEX_EXTRA_ARGS |
no | Extra CLI args (default -c notify=[]) |
YUMMY_CODEX_TITLE |
no | Display label in progress UI |
YUMMY_CODEX_MODEL |
no | Default model |
YUMMY_CODEX_REASONING |
no | `none |
- DMs always trigger the bot.
- In channels, mentions trigger by default.
- Replies to bot messages trigger.
/trigger allcan enable non-mention channel messages for a channel/thread scope.cancelor/cancelstops the active run for the channel/thread queue.
All commands can be used in-channel or thread-scoped (thread when sent in a thread).
| Command | Description |
|---|---|
/pi <prompt> |
Force pi runner for this message |
/codex <prompt> |
Force codex runner for this message |
/sessions |
List recent sessions |
/resume [n] [prompt] |
Resume session by index or latest |
/session [n] [prompt] |
Alias for /resume |
/agent [pi|codex|clear] |
Get/set/clear default engine |
/model [pi|codex] <model|clear> |
Get/set/clear model override |
/reasoning [pi|codex] <off|minimal|low|medium|high|xhigh|clear> |
Get/set/clear reasoning override |
/trigger [mentions|all|clear] |
Get/set/clear trigger mode |
/login openai-codex |
Start OpenAI Codex OAuth flow |
/login github-copilot [enterprise-domain] |
Start GitHub Copilot device flow |
- Saved to
~/.pi/agent/auth.json(or$PI_CODING_AGENT_DIR/auth.json). - File permissions are restricted to user-only (
0600). - Do not commit this file.
Per channel:
<channelId>/log.jsonlmessage log<channelId>/attachments/*downloaded files<channelId>/sessions.jsonlstored resume lines
Global:
prefs.jsonchannel/thread defaults and overrides
Use a dedicated directory (for example /var/lib/yummy), not the repo root.
- Run with a dedicated bot account and minimum necessary Mattermost permissions.
- Set
YUMMY_ALLOWED_USERSto limit who can invoke the bot. - Keep runtime data on persistent storage with restricted filesystem ACLs.
- Run under a process manager (
systemd, container orchestrator, etc.). - Monitor logs and rotate/retain
log.jsonlbased on your policy.
Example systemd unit:
[Unit]
Description=yummy Mattermost bridge
After=network-online.target
[Service]
Type=simple
WorkingDirectory=/opt/yummy
Environment=YUMMY_URL=https://mattermost.example.com
Environment=YUMMY_TOKEN=REPLACE_ME
Environment=YUMMY_DEFAULT_ENGINE=pi
Environment=YUMMY_ALLOWED_USERS=alice,bob
ExecStart=/usr/bin/node /opt/yummy/dist/main.js /var/lib/yummy
Restart=always
RestartSec=3
User=yummy
Group=yummy
[Install]
WantedBy=multi-user.target