docs

outl docs

Random Task

Capability: keybinding · Source on GitHub

Pick one open TODO at random and tell you to focus on it. A tiny, read-only plugin whose whole point is to show how a keybinding hangs off a command.

What it demonstrates

The keybinding capability: a chord (Ctrl+Shift+R) that fires a command without opening the slash menu.

A keybinding never stands alone — it dispatches a registered command. The plugin registers pick via ctx.commands.register("pick", ...), declares it under contributes.commands, and then contributes.keybindings binds Ctrl+Shift+R to that same id. The slash menu can fire pick too, which is why the manifest also lists slash-command.

The handler is read-only: it runs ctx.blocks.query({ todo: "TODO" }), picks a random block with Math.random() (the host’s Boa engine ships a normal one), and shows a notification. Nothing is mutated, so there’s no describe→apply ordering to think about.

The code

/**
 * Random Task — example outl plugin.
 *
 * Demonstrates the `keybinding` capability: a command bound to a chord that
 * needs no slash menu to fire. Press `Ctrl+Shift+R` and the plugin picks one
 * open TODO at random and nudges you to focus on it.
 *
 * The command is read-only: it queries the workspace and shows a notification,
 * never mutating a block. That's the most robust shape for an example — there's
 * no describe→apply ordering to worry about and nothing to undo.
 *
 * A keybinding always needs a registered command behind it: the chord just
 * dispatches the `pick` command declared in `plugin.json`. The slash menu can
 * fire the same command, which is why we list both capabilities.
 */

import { definePlugin, type Block, type PluginContext } from "@outl/plugin-sdk";

export default definePlugin({
  activate(ctx: PluginContext) {
    // The command id ("pick") must match contributes.commands in plugin.json;
    // the Ctrl+Shift+R keybinding declared there dispatches this same handler.
    ctx.commands.register("pick", async () => {
      const open = await ctx.blocks.query({ todo: "TODO" });

      if (open.length === 0) {
        ctx.ui.notify("🎉 No open tasks!");
        return;
      }

      // Boa (the host JS engine) supports a normal Math.random(); use it to
      // pick the index. Not deterministic, which is exactly what we want here.
      const chosen = open[Math.floor(Math.random() * open.length)] as Block;
      ctx.ui.notify(`👉 Focus on: ${chosen.text}`);
    });
  },
});

Manifest

  • capabilities: ["slash-command", "keybinding"] — the command exists (slash-command), and a chord can fire it (keybinding).
  • permissions: ["read-page"] — all it does is read blocks.
  • contributes.commands: [{ "id": "pick", "title": "Pick a random task" }] — declares the command id the handler registers against.
  • contributes.keybindings: [{ "command": "pick", "key": "Ctrl+Shift+R" }] — binds the chord to that declared command.

Try it

outl -w <workspace> plugin install ./examples/random-task --yes
# Press Ctrl+Shift+R, or run `pick` from the slash menu.