Bot Module Local Development
Bot modules have no browser UI, so lumio dev provides a CLI-based chat simulator for interactive testing. This guide covers the dev server, single-handler testing, hot-reload, and mock users.
Start the dev server
lumio dev --bot-module
Output:
Bot Module Dev Server running
Extension: My Bot Module (install: dev-local)
Platform: twitch (simulated)
Type chat messages below. Prefix with @username to set sender.
>
The dev server:
- Loads your
lumio.config.jsonandserver/functions.ts - Connects to your local Extensions-DB for
ctx.dboperations - Connects to local Redis for
ctx.cacheoperations - Watches
server/functions.tsfor changes and hot-reloads automatically - Fires timers at their configured intervals
Interactive chat
Type messages at the prompt to simulate chat input:
> !hello
[hello] Reply: "Hello, dev_user!"
> gg
[hypeDetector] (silent - no reply)
[hypeDetector] Deferred: ctx.cache.increment("hype_count", 1)
> https://clips.twitch.tv/FunnyClip123
[clipLogger] Reply: "Clip from dev_user: https://clips.twitch.tv/FunnyClip123"
The simulator shows handler responses, actions, and deferred jobs in real time.
Mock users
Prefix your message with @username to simulate different senders:
> @viewer_jane !hello
[hello] Reply: "Hello, viewer_jane!"
Set roles with a role prefix before the username:
| Prefix | Role |
|---|---|
@username | everyone (default) |
@sub:username | subscriber |
@vip:username | vip |
@mod:username | moderator |
@broadcaster:username | broadcaster |
Examples:
> @sub:loyal_viewer !gamble 50
[gamble] Reply: "loyal_viewer won 100 points!"
> @mod:nightbot !clear
[clear] Reply: "Chat cleared by nightbot"
The simulated user object populates ctx.user with the appropriate id, name, role, isMod, isVip, and isSub fields.
Single handler testing
Test a specific handler directly without the interactive chat:
# Test a command handler with arguments
lumio run command:hello --args "" --user "testuser" --role "subscriber"
# Test a keyword handler
lumio run keyword:hypeDetector --message "gg wp nice one" --user "viewer123"
# Test a pattern handler
lumio run pattern:clipLogger --message "check this https://clips.twitch.tv/abc123" --user "clipper"
# Test an event handler
lumio run event:welcomeSub --event '{"user_name": "newSub", "cumulative_months": 3}'
# Test a moderation handler
lumio run moderate:linkFilter --message "go to banned-site.com for free stuff" --user "spammer"
Each lumio run invocation:
- Loads the extension config and handler code
- Creates a mock context with the specified user and role
- Executes the handler once
- Prints the response and any side effects (DB writes, cache ops, deferred jobs)
- Exits
Hot-reload
The dev server watches server/functions.ts and related files. When you save a change, handlers are reloaded automatically:
[hot-reload] Detected change in server/functions.ts
[hot-reload] Handlers reloaded (3 commands, 2 keywords, 1 timer)
The reload preserves your chat history and in-memory state. Timers are restarted with potentially new intervals.
Timer testing
Timers fire at their configured intervals during lumio dev. For faster iteration, you can trigger a timer manually:
> /timer reminder
[periodicReminder] Reply: "Remember to follow the channel!"
The /timer <name> command fires the named timer handler immediately without waiting for the interval.
Platform simulation
By default, the dev server simulates Twitch. Switch platforms with:
> /platform youtube
Platform switched to: youtube
> /platform kick
Platform switched to: kick
This changes the ctx.user.platform value for subsequent messages.
Database and cache
The dev server uses your local infrastructure:
- Database: Local Extensions-DB (port 5434). Tables from
server/schema.tsare provisioned automatically. - Cache: Local Redis. Cache keys are scoped under
ext-cache:dev-local:*.
Both persist across dev server restarts, so you can build up test data over time.
Debugging
The dev server prints detailed output for each handler invocation:
> !points
[points] Executing command handler...
[points] ctx.cache.get("pts:viewer123") → 150
[points] ctx.cache.set("pts:viewer123", 151, 3600) → OK
[points] Reply: "viewer123: 151 points"
[points] Deferred: 1 job queued
[points] Deferred[0]: ctx.db.patch("user_points", "viewer123", {"balance": 151}) → OK
[points] Completed in 8ms
This shows every ctx.db, ctx.cache, and ctx.fetch call made by the handler, along with deferred job execution.
Production debugging
After deploying your bot module, use lumio logs to stream production handler execution logs:
# Stream all logs
lumio logs
# Filter by handler
lumio logs --handler points
# Filter by level
lumio logs --level error
See Error Reporting for information about the anonymized error reports available in the developer dashboard.