# Hubot: Scriptable Chat Bot Framework for Team Automation

> Hubot is an open source JavaScript framework for building customizable chat bots that connect to Slack, Discord, Microsoft Teams, and other platforms. Version 14 runs on Node.js 18 or later as a pure ESM module and includes a structured command bus alongside the legacy script listener system.

**hubotio/hubot** — A customizable life embetterment robot.

- Repository: https://github.com/hubotio/hubot
- Website: https://hubotio.github.io/hubot/
- Stars: 16,795 · Forks: 3,707
- Language: JavaScript
- License: MIT
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/hubotio-hubot

## What Hubot Does and Who Uses It

Hubot is a framework for building chat bots that automate team tasks inside messaging platforms. The README describes it as "a framework to build chat bots, modeled after GitHub's Campfire bot of the same name." The typical use case is internal ChatOps: a bot that listens in a team Slack channel or Discord server, responds to commands, runs scripts against internal systems, and posts results back to the channel.

The framework is code-first: developers write JavaScript scripts that define what the bot hears and how it responds. Scripts are plain JavaScript modules that export a function receiving the `robot` object. The bot's behavior is entirely determined by the scripts it loads, with no graphical configuration or conversation flow designer involved.

Hubot connects to chat services through adapter packages. The current set of officially maintained adapters is provided under the `@hubot-friends` namespace: `@hubot-friends/hubot-slack`, `@hubot-friends/hubot-discord`, `@hubot-friends/hubot-ms-teams`, and `@hubot-friends/hubot-irc`. Each adapter handles the platform-specific authentication and message transport, while the Hubot core stays platform-agnostic.

Hubot is a library, not an application. The repository provides the npm package that other projects depend on when building their own bot, and most teams deploying Hubot never modify the core repository. Node.js 18 or later is required, with npm 9 or later, as specified in the `engines` field of the core package.json.

## Creating a New Hubot Instance

Creating a new Hubot instance uses `npx` to scaffold a project directory. The `--adapter` flag selects the chat platform at creation time:

```sh
npx hubot --create myhubot --adapter @hubot-friends/hubot-slack
```

Other available adapters use the same pattern:

```sh
npx hubot --create myhubot --adapter @hubot-friends/hubot-discord
npx hubot --create myhubot --adapter @hubot-friends/hubot-ms-teams
npx hubot --create myhubot --adapter @hubot-friends/hubot-irc
```

The command creates a `myhubot` directory containing the project structure. A `scripts/example.mjs` file demonstrates the basic script pattern. Additional scripts go in the `scripts/` folder and are loaded automatically.

The core Hubot package's runtime dependencies are intentionally thin: Express 5 for the HTTP server, express-basic-auth for HTTP basic authentication, and pino for logging. This keeps the base footprint small. The full behavior of any Hubot deployment comes from scripts and adapters, not from the core package.

The repository includes two deployment examples: `examples/hubot-start.ps1` for starting Hubot on Windows, and `examples/hubot.service` for running Hubot as a systemd service on Linux.

## Writing Scripts: Listeners and the Legacy System

The traditional Hubot scripting model uses `hear` and `respond` listeners. `hear` triggers on any message matching a regex in a room; `respond` triggers only when the bot is directly addressed by name. Both are still supported in v14 and described in the README as "legacy listeners."

A script file exports a default function that receives the `robot` object and attaches listeners:

```mjs
export default (robot) => {
  robot.hear(/deploy/, (res) => {
    res.reply('Starting deployment...')
  })
}
```

Scripts can read from and write to a key-value store that Hubot persists between restarts. The script system is the foundation on which the rest of the Hubot ecosystem was built: thousands of community scripts exist for everything from GitHub integration to random GIF replies.

Version 11 removed CoffeeScript from the codebase and converted everything to ECMAScript Modules. The README notes that v10.0.4 accidentally included an early version of this removal, while v10.0.5 reverted it. CoffeeScript scripts from the pre-v11 era need to be rewritten in JavaScript to run on v11 and later. Existing scripts written in plain JavaScript may need minor adjustments to use `import` and `export` rather than `require` and `module.exports`.

The current major version is 14, with v14.1.0 released on 2026-02-24. The last push to the main branch was on 2026-09-23, confirming the project is actively maintained.

## The Command Bus: Structured Commands with Argument Validation

Version 14 introduced a command bus (`robot.commands`) as an alternative to the text-matching approach of `hear` and `respond`. The command bus is deterministic and safe by default, meaning it does not interfere with the legacy listener system.

Registering a command defines its identifier, description, arguments with types and constraints, and a handler:

```mjs
export default (robot) => {
  robot.commands.register({
    id: 'tickets.create',
    description: 'Create a ticket',
    aliases: ['ticket new', 'new ticket'],
    args: {
      title: { type: 'string', required: true },
      priority: { type: 'enum', values: ['low', 'medium', 'high'], default: 'medium' }
    },
    sideEffects: ['creates external ticket'],
    handler: async (ctx) => {
      return `Created ticket: ${ctx.args.title}`
    }
  })
}
```

Users invoke commands by addressing the bot with the command ID and arguments:

```sh
@hubot tickets.create --title "VPN down" --priority high
```

Commands that declare `sideEffects` require explicit confirmation before execution. The bot presents a proposal, and the user confirms or cancels:

```sh
@hubot yes
@hubot no
@hubot cancel
```

The command bus configuration supports `proposalTTL` to set a timeout for pending confirmations in milliseconds (default 300000, which is 5 minutes), a `logPath` for an NDJSON event log, a `prefix` for namespacing commands, and a `permissionProvider` for custom role checking.

Aliases are for discovery and search only. They do not execute commands or create proposals. Commands are typed, so argument validation happens in the framework before the handler runs.

A built-in help command registers automatically and supports filtered search:

```sh
@hubot help tickets
@hubot help search "create ticket"
```

## Permissions: Room-Based and Role-Based Access Control

The command bus supports two permission layers that restrict which users can run which commands and from which channels.

Room-based permissions restrict a command to specific chat rooms. When a command declares a `rooms` list under `permissions`, users in other rooms receive a "Permission denied: command not allowed in this room" message:

```mjs
robot.commands.register({
  id: 'sensitive.action',
  permissions: {
    rooms: ['#admin', '#ops']
  },
  handler: async (ctx) => 'Action executed!'
})
```

Room-based permissions are always enforced, regardless of whether a permission provider is configured.

Role-based permissions require a `permissionProvider` to supply the role-checking logic. The provider's `hasRole` function receives the user, the required roles, and the context, and returns a boolean. Without a provider, role-based permissions are ignored (allow by default):

```mjs
const commandBus = new CommandBus(robot, {
  permissionProvider: {
    hasRole: async (user, requiredRoles, context) => {
      const userRoles = await fetchUserRoles(user.id)
      return requiredRoles.some(role => userRoles.includes(role))
    }
  }
})
```

This design separates the framework's permission checking interface from the application's data source: Hubot does not know where user roles come from. Any data source (a database, an LDAP directory, a hard-coded list) works as long as the `hasRole` function returns the expected boolean.

## Custom Type Resolvers and Extensibility

The command argument type system is extensible. Beyond the built-in types (string, enum), scripts can register custom type resolvers that validate and transform argument values before they reach the handler:

```mjs
robot.commands.registerTypeResolver('project_id', async (value, schema, context) => {
  if (!value.startsWith('PRJ-')) {
    throw new Error('must start with PRJ-')
  }
  return value.toUpperCase()
})
```

Once registered, the custom type is available to any command in the same script that declares it as an argument type. This allows enforcing domain-specific constraints, calling external validation services, or normalizing input format before the handler receives it.

The `configuration/` directory in the repository holds configuration files, and the `src/` directory contains the framework source. The project uses Node's built-in test runner (`node --test`) rather than a separate test framework. The `test:e2e` script runs end-to-end tests via a shell script.

## Hubot vs Botpress: Script Automation vs Conversation Design

Botpress is an open source bot platform that includes a visual conversation flow editor, natural language understanding (NLU) for intent detection, and a built-in knowledge base for FAQ-style responses. It is designed primarily for customer-facing conversational bots where the conversation has structured intents and expected dialog paths.

Hubot occupies a different position. It does not include NLU, intent detection, or a conversation flow designer. Its strength is internal team automation: the command bus provides typed, permission-controlled commands that engineering and operations teams can trigger from their chat tool to run scripts against internal systems. The adapter model makes it straightforward to connect to the platforms teams already use.

The practical difference in adoption: Botpress is built for companies deploying a customer support bot on a website or product surface, where the bot needs to understand varied natural-language input and guide users through a defined flow. Hubot is built for engineering teams where the bot is a shared automation tool invoked with explicit commands by people who know what the commands do.

Both are MIT-licensed. Hubot's design has remained stable over multiple major versions. Its history goes back to GitHub's internal tool, and the README links to a 2011 GitHub blog post announcing its open source release.

## Conclusion

Hubot suits engineering teams that want a code-first, extensible bot framework for internal ChatOps automation: incident triage commands, deployment triggers, ticket creation, and team notifications over Slack, Discord, or other platforms. Teams building customer-facing conversational AI with NLU and dialog flow management should look at platforms designed for that workload instead. Before creating a new instance, verify the adapter package availability for your chat platform and confirm Node.js 18 or later is installed.

## FAQ

### What are the alternatives to Hubot?

The README does not list alternatives directly. Botpress is a widely used open source alternative for teams that need NLU and conversation flow design. For teams that want Hubot's code-first, script-based approach on a different runtime, Errbot (Python) provides similar functionality.

### How do I create a new Hubot bot?

Run `npx hubot --create myhubot --adapter @hubot-friends/hubot-slack` (or a different adapter for Discord, MS Teams, or IRC). This creates a project directory with a starter script in `scripts/example.mjs`. Add more scripts to the `scripts/` folder to extend the bot's behavior.

### What chat platforms does Hubot support?

The officially maintained adapters under the `@hubot-friends` namespace cover Slack, Discord, Microsoft Teams, and IRC. The adapter is selected when creating a new Hubot instance and handles platform-specific authentication and message transport.

## Sources

- [hubotio/hubot on GitHub](https://github.com/hubotio/hubot)
- [License: MIT](https://github.com/hubotio/hubot/blob/main/LICENSE)
- [Project website](https://hubotio.github.io/hubot/)
- [README](https://github.com/hubotio/hubot/blob/main/README.md)
- [Releases](https://github.com/hubotio/hubot/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/hubotio-hubot
