Commands and palette
Palette, shortcut, menu, toolbar, console and script all converge on K.commands.execute(). Zone and capability are checked there once and for all, which leaves a single file to read in order to know what can run, and under what conditions.
The command object
| Field | Type | Description |
|---|---|---|
| id | string | Required. A command without an identifier throws. |
| title | {fr, en} or key | Resolved by K.resolveTitle(). |
| handler | function | (args, context). Sync or promise. Absent when declarative. |
| category | string | Grouping in the palette and the Actions panel. |
| capability | string | Required capability. The core is exempt. |
| zone | string | 'local' restricts the command to developer mode. |
| when | function | Receives the context service. A thrown exception counts as false. |
| keybinding | string | Suggested combination. The effective binding lives in a separate table. |
| quickAccess | bool | Offered in the quick-access section. |
| declarative | bool | Declared by manifest, handler absent until activation. |
Context keys
The context store mirrors the current state of the application, and predicates are evaluated against it. It is open: any view may set a key through K.context.set(), and predicates may read it.
| Key set by the kernel | Value |
|---|---|
| kernel.zone | distribution or local. |
| shell.ready | Boolean. Set by shell-dock.js once the docks are mounted. |
Dispatch sequence
| # | Check | Rejection |
|---|---|---|
| 1 | Identifier resolution. | Commande inconnue: <id> |
| 2 | Zone. | Commande réservée à la zone locale |
| 3 | Capability, except for the core. | Capacité refusée: <cap> |
| 4 | when predicate. | Commande indisponible dans ce contexte |
| 5 | Source activation, if dormant. | The activation error is propagated. |
| 6 | Handler present after activation. | Commande sans gestionnaire après activation |
| 7 | command.before, handler, command.after. | Any failure emits command.error and rejects. |
Activation happens before the handler is resolved: a command declared by manifest has no handler yet, and it is the activation of its source that installs one.
Listing what is available
Overriding a command
K.commands.override(id, wrapper) wraps a command without touching the original. Disposing the token restores the previous state exactly. This is the pattern used for the CRM extensions, and the primitive that customisations rely on when they have to survive a core update.
The palette
Ctrl + Shift + P → core.palette.open
The palette calls K.commands.list() every time it opens, so it only shows commands available in the current context, with their category and shortcut. A command brought in by a plugin loaded mid-session appears without a restart.
Figure 1: The command palette, filtered as you type.
Why a command is missing
| Cause | Check |
|---|---|
| Zone local outside developer mode. | K.get('command', id).zone |
| Capability not granted to the source. | K.get('command', id).capability, then the capability provider. |
| when predicate is false. | K.context.all(), then read the predicate. |
| Source not registered. | K.get('command', id) returns null. |
The action log
The Journal panel feeds on command.before, command.after and command.error, as well as on lines written through K.log(). It also captures the console.