Getting Started
From zero to your first chatops command in under five minutes. No dependencies, no ceremony โ just Bun and a module directory.
Bun v1.0 or later is required.
Install it with curl -fsSL https://bun.sh/install | bash.
Installation
mkdir mission-control && cd mission-control
bun init -y
bun add @devchitchat/chatopsjs
mkdir modules
Modules auto-load from this directory. Any .js file that exports a default async function is picked up automatically.
// app.js
import { Robot, CliAdapter } from '@devchitchat/chatopsjs'
const robot = await Robot.create({ directory: './modules' })
const cli = new CliAdapter(robot)
robot.adapters.add(cli)
await cli.start()
Your First Command
Create a file at modules/hello.js:
import { Command, createTextResponse } from '@devchitchat/chatopsjs'
export default async function (robot) {
robot.commands.register(new Command({
id: 'hello',
description: 'Say hello from mission control',
aliases: ['hi', 'greet'],
args: {
name: { type: 'string', required: false }
},
handler: async (ctx) => {
const who = ctx.args.name ?? ctx.envelope.actor.id
return createTextResponse(`Hello, ${who}! All systems nominal. ๐`)
}
}))
}
Run it:
bun run app.js
chatops> hello
Hello, cli! All systems nominal. ๐
chatops> hello --name "Houston"
Hello, Houston! All systems nominal. ๐
chatops> hi
Hello, cli! All systems nominal. ๐
Structured Responses
chatops.js has three response types that let you be as rich or as portable as you need:
import {
createTextResponse,
createMessageResponse,
createNativeResponse
} from '@devchitchat/chatopsjs'
// 1. Plain text โ works everywhere
createTextResponse('Deploy complete.')
// 2. Structured IR โ adapters render blocks to platform-native UI
createMessageResponse({
fallbackText: 'Deploy complete',
blocks: [
{ type: 'section', text: 'โ
Deploy complete' },
{ type: 'facts', items: [
{ label: 'Service', value: 'api-gateway' },
{ label: 'Version', value: 'v2.4.1' },
{ label: 'Environment', value: 'production' }
]}
]
})
// 3. Native โ full provider payload as escape hatch
createNativeResponse({
fallbackText: 'Deploy complete',
provider: 'slack',
payload: {
blocks: [
{ type: 'header', text: { type: 'plain_text', text: 'โ
Deploy complete' } }
]
}
})
Built-In Help
The help command is registered automatically by Robot.create().
It lists every registered command with its description.
chatops> help
Available commands:
hello Say hello from mission control
help List available commands
Permissions
Commands can declare required permissions. The CLI adapter assigns permissions via the actor option:
import { Robot, CliAdapter, Command, createTextResponse } from '@devchitchat/chatopsjs'
const robot = await Robot.create({ directory: './modules' })
const cli = new CliAdapter(robot, {
actor: {
id: 'ops-engineer',
permissions: ['deploys:write', 'tickets:read']
}
})
robot.adapters.add(cli)
await cli.start()
// In a module:
robot.commands.register(new Command({
id: 'deploy',
description: 'Trigger a deployment',
permissions: ['deploys:write'], // โ required
handler: async (ctx) => createTextResponse('Launching deployment...')
}))
Confirmation Flow
Add confirm to a command to require explicit approval before execution:
robot.commands.register(new Command({
id: 'rollback',
description: 'Roll back the last deployment',
permissions: ['deploys:write'],
confirm: {
mode: 'yes-no',
message: 'โ ๏ธ This will roll back production. Are you sure? (yes/no)'
},
handler: async (ctx) => createTextResponse('Rolling backโฆ hang tight.')
}))
chatops> rollback
โ ๏ธ This will roll back production. Are you sure? (yes/no)
chatops> yes
Rolling backโฆ hang tight.
Middleware
Middleware functions run on every command. Use them for logging, metrics, or cross-cutting concerns:
robot.use(async (ctx, next) => {
const start = Date.now()
console.log(`โ ${ctx.command.id} by ${ctx.envelope.actor.id}`)
await next()
console.log(`โ ${ctx.command.id} in ${Date.now() - start}ms`)
})
The CLI adapter is great for development. When you're ready to connect to Slack, Discord, or another platform, see the Creating Adapters guide.