Skip to content

Defining Commands

A command is an async function with an ID. The @Command decorator binds a class method to a command ID, and registerCommands() attaches every decorated method on a service instance to the registry.

import { Command, CommandRegistry, registerCommands } from '@coralstack/cmd-ipc'
class MathService {
@Command('math.add', 'Add two integers')
add({ a, b }: { a: number; b: number }): number {
return a + b
}
}
const registry = new CommandRegistry({ id: 'main' })
registerCommands([new MathService()], registry)

Commands become fully type-safe when paired with a Valibot schema map. The registry validates requests/responses at runtime and TypeScript infers the types at the call site.

import * as v from 'valibot'
import type { CommandSchemaMap } from '@coralstack/cmd-ipc'
export const MathSchema = {
'math.add': {
description: 'Add two integers',
request: v.object({ a: v.number(), b: v.number() }),
response: v.number(),
},
} as const satisfies CommandSchemaMap
const registry = new CommandRegistry({
id: 'main',
schemas: { commands: MathSchema },
})

See Type Safety for loose / strict / mixed modes.

Commands whose ID starts with _ are private — they stay local to the registering process and are never announced to connected channels or exposed as MCP tools.

class LocalOps {
@Command('_main.log', 'Internal logger')
log({ message }: { message: string }) {
console.log(message)
}
}