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.