Plugin CLI Commands — Weavetab Docs — Weavetab Docs

Authoring standalone terminal commands in plugins, parsing flags, permissions gating, and execution lifecycles.

Plugin CLI Commands — Weavetab Docs

Authoring standalone terminal commands in plugins, parsing flags, permissions gating, and execution lifecycles.

# Plugin CLI Commands

While MCP tools are designed for AI agents operating inside an active agent loop, **Plugin CLI Commands** allow plugins to expose terminal-first subcommands. Developers and CI/CD pipelines can invoke these commands directly from the shell without launching an LLM agent.

```
┌─────────────────────────────────────────────────────────────┐
│                 Two Execution Surfaces                      │
├──────────────────────────────┬──────────────────────────────┤
│  MCP Tools                   │  AI Agents (Claude/Cursor)   │
│  CLI Commands                │  Terminal / Shell Scripts    │
└──────────────────────────────┴──────────────────────────────┘
```

---

## 1. Declaring a Command (`defineCommand`)

Import `defineCommand` from `@weavetab/sdk`:

```typescript
import { defineCommand } from "@weavetab/sdk";

export const migrateCommand = defineCommand({
  name: "migrate",
  description: "Run pending database schema migrations",
  usage: "weavetab plugin use @my-org/plugin-db migrate [--dry-run] [--target <version>]",
  schema: {
    "dry-run": {
      type: "boolean",
      description: "Preview migration steps without writing to disk or database",
    },
    target: {
      type: "string",
      description: "Target migration version timestamp",
    },
  },
  handler: async (args, ctx) => {
    // args is typed based on the schema: { "dry-run"?: boolean; target?: string }
    const isDryRun = Boolean(args["dry-run"]);
    ctx.logger.info(`Running migrations (dry-run: ${isDryRun})...`);

    const result = {
      applied: ["001_init.sql", "002_users.sql"],
      dryRun: isDryRun,
      target: args.target || "latest",
      durationMs: 42,
    };

    // Return value is formatted as JSON when piped or displayed cleanly in terminal
    return result;
  },
});
```

---

## 2. Registering Commands in `definePlugin`

You can declare commands statically in `definePlugin({ commands: [...] })` or dynamically in `onLoad(ctx)`:

```typescript
import { definePlugin, type PluginContext } from "@weavetab/sdk";
import { migrateCommand } from "./commands/migrate.js";
import { pingCommand } from "./commands/ping.js";

export default definePlugin({
  name: "@my-org/plugin-db",
  version: "1.0.0",
  instructions: "Database migration and inspection utilities.",

  // 1. Static registration
  commands: [migrateCommand],

  async onLoad(ctx: PluginContext) {
    // 2. Dynamic registration via ctx.cli
    ctx.cli.registerCommand(pingCommand);
  },
});
```

---

## 3. Permission Gating

Registering CLI commands requires the `commands` capability in `weavetab.json`:

```json
{
  "permissions": {
    "commands": {
      "add": true,
      "reason": "Allows developers to execute schema migrations and status checks via CLI."
    }
  }
}
```

If a plugin attempts to call `ctx.cli.registerCommand()` without `permissions.commands.add: true`, the runtime throws an `UNAUTHORIZED_CAPABILITY` exception and aborts loading.

---

## 4. Invoking Commands via Terminal

Once a plugin is installed or linked locally, users invoke its commands through the Weavetab CLI:

### Full Syntax
```bash
weavetab plugin use <plugin-name-or-alias> <command-name> [--flags]
```

### Shorthand Syntax
```bash
weavetab use <plugin-name-or-alias> <command-name> [--flags]
```

### Examples

```bash
# Run the migrate command with flags
weavetab plugin use @my-org/plugin-db migrate --dry-run

# Shorthand invocation
weavetab use db migrate --target 20261105

# Inspect all commands and tools provided by a plugin
weavetab plugin use db
```

When called without a command name (`weavetab plugin use <pkg>`), the CLI prints:
1. Package version and description.
2. The declared agent instructions.
3. A table of available CLI Commands.
4. A table of available MCP Tools.
5. A table of Utilities (`/` Prompts and `@` Resources).

---

## 5. Command Execution Context

Command handlers receive a `PluginCommandContext` containing:
- `ctx.name`: The plugin package name.
- `ctx.version`: The plugin version.
- `ctx.config`: The active plugin configuration.
- `ctx.storage`: The sandboxed storage API (`get`, `set`, `list`, `getJson`, `setJson`).
- `ctx.logger`: The scoped logger.
- `ctx.tab`: Optional lightweight tab client (if Chrome is running).

---

## 6. Exit Codes and Output Formatting

1. **Structured Return Values**: If your handler returns an object or array, the CLI outputs it as formatted JSON when stdout is not a TTY (e.g. piped to `jq`) or as a human-readable table in terminal sessions.
2. **Standard Output**: You can call `console.log()` directly for terminal output.
3. **Exit Codes**: Throw an error to terminate the CLI command with non-zero exit code:
   ```typescript
   if (!connected) {
     throw new Error("Database connection failed: ECONNREFUSED 127.0.0.1:5432");
   }
   ```