Hermit is the OpenClaw Discord bot built on Carbon, Bun, and SQLite.
It handles:
- Discord slash commands and message-context moderation actions
- helper-thread onboarding and thread-length enforcement
- keyword-based automod responses
- announcement crossposting for selected channels
- local event and helper-thread state persistence in SQLite
- a read-only local dashboard for helper events and tracked threads
Repository: openclaw/hermit
Hermit runs as a gateway-first Discord bot:
- Bun is the runtime and package manager
- Carbon handles command registration, gateway events, and Discord API access
- Drizzle manages the SQLite schema and migrations
- SQLite stores helper event history and tracked helper thread state
- A small Bun HTTP server exposes read-only operational visibility
Main entrypoint: src/index.ts
/githublooks up GitHub issues and pull requestsSolved (Mod)marks a thread as solved in Answer Overflow and closes it/say ...posts common guidance and documentation links/helper ...posts helper-thread moderation messages and closes threads/role ...toggles specific server roles- helper-thread creation triggers a welcome message and thread tracking
- a background monitor warns on long threads and auto-closes very long ones
- automod rules can repost/redact matching messages and send guidance replies
- selected announcement channels are auto-crossposted
- Bun
- a Discord application and bot token
- access to the target Discord server
- SQLite filesystem access for
DB_PATH
- Install dependencies:
bun install- Create a
.envfile.
Recommended variables:
DISCORD_CLIENT_ID="your-client-id"
DISCORD_BOT_TOKEN="your-bot-token"
DISCORD_DEV_GUILDS="guild_id_1,guild_id_2"
ANSWER_OVERFLOW_API_KEY="your-answer-overflow-api-key"
ANSWER_OVERFLOW_API_BASE_URL="https://www.answeroverflow.com"
HELPER_THREAD_WELCOME_PARENT_ID="123456789012345678"
HELPER_THREAD_WELCOME_TEMPLATE="Welcome to helpers. Please include expected vs actual behavior, what you already tried, and relevant logs/code."
THREAD_LENGTH_CHECK_INTERVAL_HOURS="2"
DB_PATH="data/hermit.sqlite"
DRIZZLE_MIGRATIONS="drizzle"
HELPER_LOGS_HOST="127.0.0.1"
HELPER_LOGS_PORT="8787"- Apply migrations:
bun run db:migrate- Start Hermit:
bun run devbun run devstarts Hermit in watch modebun run startstarts Hermit normallybun run typecheckruns TypeScript without emitting filesbun run db:migrateapplies Drizzle migrations to SQLitebun run db:generategenerates Drizzle migration files from the schema
DISCORD_CLIENT_ID: Discord application client IDDISCORD_BOT_TOKEN: Discord bot token
DISCORD_DEV_GUILDS: comma-separated guild IDs for dev command registrationANSWER_OVERFLOW_API_KEY: required forSolved (Mod)to call Answer OverflowANSWER_OVERFLOW_API_BASE_URL: defaults tohttps://www.answeroverflow.comHELPER_THREAD_WELCOME_PARENT_ID: parent forum or helper channel whose new threads should receive the welcome messageHELPER_THREAD_WELCOME_TEMPLATE: overrides the default helper welcome textTHREAD_LENGTH_CHECK_INTERVAL_HOURS: enables the helper thread monitor when set to a positive numberDB_PATH: SQLite database path, defaults todata/hermit.sqliteDRIZZLE_MIGRATIONS: migration directory, defaults todrizzleHELPER_LOGS_HOST: host for the read-only helper dashboard, defaults to127.0.0.1HELPER_LOGS_PORT: port for the read-only helper dashboard, defaults to8787; set to0to disable itSKIP_DB_MIGRATIONS: set to1to skip automatic migration-on-startup
Looks up a GitHub issue or pull request and returns:
- title and state
- repo and author
- labels
- description summary
- recent comments
- pull request change stats when applicable
Options:
numberrequireduseroptional, defaults toopenclawrepooptional, defaults tohermit
Available in:
- guilds
- bot DMs
Source: src/commands/github.ts
Message-context moderation action that:
- posts the chosen solution message to Answer Overflow
- adds a checkmark reaction to the solved message
- archives and locks the thread
- records a
mark_solutionhelper event in SQLite
Permissions:
ManageMessagesManageThreads
Requires:
ANSWER_OVERFLOW_API_KEY
Source: src/commands/solvedMod.ts
Posts common canned guidance messages.
Subcommands:
guideserver-faqhelpuser-helpmodelstuckciansweroverflowpingingdocssecurityinstallblog-rename
Available in:
- guilds
- bot DMs
Source: src/commands/say.ts
Helper-channel moderation utilities.
Subcommands:
warn-new-thread: posts the long-thread warning messageclose: posts the close message, archives the thread, and locks itclose-thread: same behavior asclose
These commands also emit helper events into SQLite.
Source: src/commands/helper.ts
Toggles specific hard-coded server roles.
Current subcommands:
showcase-banclawtributor
Permissions:
- command requires
ManageRoles - runtime access also checks that the invoking member has the hard-coded
communityStaffrole
Source: src/commands/role.ts
On startup, Hermit logs the connected username and starts the helper thread monitor when configured.
Source: src/events/ready.ts
When a new thread is created under HELPER_THREAD_WELCOME_PARENT_ID, Hermit:
- stores the thread in
tracked_threads - records a
thread_welcome_createdevent - posts the helper welcome message
Source: src/events/threadCreateWelcome.ts
When THREAD_LENGTH_CHECK_INTERVAL_HOURS is set, Hermit polls tracked helper threads with setInterval.
Behavior:
- loads open tracked threads from SQLite
- fetches the Discord thread live
- updates message counts and close state
- warns at more than
100messages - warns again at more than
150messages - posts a close notice and archives/locks at more than
200messages
Configured messages live in:
Source: src/services/threadLengthMonitor.ts
Hermit listens to automod keyword actions and can:
- repost the triggering content through a webhook
- redact the matched trigger in the repost
- send a follow-up warning/guidance message
- optionally include a role mention in the guidance message
Automod rule configuration lives in:
Message template placeholders:
{user}{keyword}{content}
Source: src/events/autoModerationActionExecution.ts
Hermit auto-crossposts messages from a fixed set of announcement channel IDs.
Source: src/events/autoPublishMessageCreate.ts
Hermit uses SQLite via Bun and Drizzle.
Database bootstrap: src/db.ts
Schema definition: src/db/schema.ts
Generic key/value storage with:
keyvaluecreatedAtupdatedAt
Operational event log for helper-related actions.
Fields:
idevent_typethread_idmessage_countevent_timecommandinvoked_by_idinvoked_by_usernameinvoked_by_global_namereceived_atraw_payload
Typical event types:
mark_solutionhelper_commandthread_welcome_created
Persistent helper-thread state used by the monitor.
Fields:
idthread_idcreated_atlast_checkedsolvedwarning_levelclosedlast_message_countreceived_atraw_payload
Drizzle configuration: drizzle.config.ts
Migration runner: src/scripts/migrate.ts
Committed SQL migrations live under:
On startup, Hermit automatically applies migrations unless SKIP_DB_MIGRATIONS=1.
Hermit starts a small Bun HTTP server for local visibility into helper activity.
Default address:
http://127.0.0.1:8787
Routes:
GET /: dashboard UI for helper eventsGET /api/events: JSON event listingGET /api/threads: JSON tracked-thread listing
Supported GET /api/events query params:
eventTypecommandthreadIdinvokedByfromtolimitup to500
Supported GET /api/threads query params:
threadIdsolvedclosedlimitup to500
Source: src/server/helperLogsServer.ts
- src/config/automod-messages.json: automod trigger-to-response mapping
- src/config/threadLengthMessages.ts: warning and auto-close helper thread messages
- Hermit is Bun-first;
package-lock.jsonis intentionally not used - command registration and gateway listeners are wired in src/index.ts
- helper events and tracked-thread writes are internal; the HTTP server is read-only
- the thread-length scheduler is interval-based, not cron-based
Useful local checks:
bun run typecheck
bun run db:migrate
bun run devMIT