Skip to main content

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.json and server/functions.ts
  • Connects to your local Extensions-DB for ctx.db operations
  • Connects to local Redis for ctx.cache operations
  • Watches server/functions.ts for 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:

PrefixRole
@usernameeveryone (default)
@sub:usernamesubscriber
@vip:usernamevip
@mod:usernamemoderator
@broadcaster:usernamebroadcaster

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:

  1. Loads the extension config and handler code
  2. Creates a mock context with the specified user and role
  3. Executes the handler once
  4. Prints the response and any side effects (DB writes, cache ops, deferred jobs)
  5. 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.ts are 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.