# grove.commands.register()

Replace the running instance's slash-command definitions.

## Signature

```ts
grove.commands.register(commands: CommandDefinition[]): void
interface CommandDefinition {
  name: string
  summary?: string
  usage?: string
  subcommands?: { name: string; summary?: string; usage?: string }[]
}
```

## Availability

IRC-bound Sprigs and Roots with commands.register. Composer utilities use manifest contributions.commands instead; application Roots and settings pages cannot register commands.

## Parameters

| Parameter | Required | Description |
| --- | --- | --- |
| `commands` | Yes | Complete replacement array; [] unregisters all. |
| `name` | Yes | Command token. Trimmed, lowercased, leading slashes removed; must remain nonempty and have no whitespace. |
| `summary` | No | Palette help text, default empty. Collapsed to a single line and capped at 120 characters. |
| `usage` | No | Argument hint, default empty. Same 120-character single-line limit. |
| `subcommands` | No | Discovery metadata for second tokens; each uses the same name/help rules. Default []. |

## Return value

Returns `undefined`, not the accepted command list.

## Behavior and errors

At most 32 input commands and 16 subcommands per command are considered. Invalid names and duplicate normalized names are skipped (first wins). Built-ins cannot be claimed; cross-extension routing favors the existing owner. Subcommands do not create separate callbacks: /weather get Paris still produces command weather with argString 'get Paris'. Registration is document-local and must be restored after reload. Subscribe to command before registering.

## Example

```js
grove.on('command', event => {
  if (event.command === 'weather') console.info('Weather command invoked')
})
grove.commands.register([{
  name: 'weather', summary: 'Look up weather', usage: '<city>',
  subcommands: [{ name: 'get', summary: 'Current weather', usage: '<city>' }]
}])
```

See [Event reference](events.md#command) and [grove.card()](grove-card.md).

