Create your first Tool

A Tool plugin adds a whole subcommand to opensip-cli. Use this path when your work is not a fitness check, simulation scenario, or graph adapter.

This guide scaffolds a tracked project-local Tool under opensip-cli/tools/ using

opensip tools create. It is the fastest way to understand the contract before you

package a Tool for npm.

Project-local tools are executable code, deny-by-default, and **not

sandboxed** after you allowlist them. Do not use wildcard trust unless you trust

every project-local tool in the repo.

1. Scaffold the tool

Minimal JS (default smoke path)

Zero npm dependencies — ideal for a quick allowlist/run check:

opensip tools create hello-tools

This writes opensip-cli/tools/hello-tools/opensip-tool.manifest.json and

index.mjs.

Typed local package (ts-local)

For TypeScript authoring with createTool() from @opensip-cli/core:

opensip tools create hello-tools --template ts-local

This adds package.json, tsconfig.json, src/index.ts, tests, and a README.

The sidecar points at ./dist/index.js, so build before validate/run:

cd opensip-cli/tools/hello-tools
pnpm install
pnpm run build
pnpm test

2. Sidecar manifest shape

Generated manifests include identity and stableId (required by the real

sidecar validator):

{
  "kind": "tool",
  "id": "hello-tools",
  "identity": { "name": "hello-tools" },
  "stableId": "8f1e2d3c-4b5a-6789-0abc-def123456789",
  "name": "hello-tools",
  "version": "0.1.0",
  "apiVersion": 1,
  "main": "./index.mjs",
  "commands": [
    { "name": "hello-tools", "description": "Run hello-tools" }
  ]
}

The manifest is read before the module is imported. Runtime metadata.id must

match stableId; metadata.name and command names must match the manifest.

3. Runtime entry

minimal-js emits a dependency-free plain object. ts-local emits:

import { createTool } from '@opensip-cli/core';

export const tool = createTool({
  identity: { name: 'hello-tools' },
  metadata: {
    id: '<stableId-from-manifest>',
    version: '0.1.0',
    description: 'Project-local typed tool',
  },
  primaryCommand: {
    description: 'Run hello-tools',
    commonFlags: ['json'],
    scope: 'none',
    output: 'command-result',
    handler: async () => ({
      type: 'text-lines',
      title: 'hello-tools',
      lines: ['Your project-local tool is ready.'],
    }),
  },
});

createTool() wraps defineTool() and does not add hidden lifecycle hooks.

Advanced tools can still use defineTool() directly.

4. Validate

# minimal-js
opensip tools validate opensip-cli/tools/hello-tools

# ts-local (after build + install deps in the tool dir)
opensip tools validate opensip-cli/tools/hello-tools --install-deps

Validation executes candidate code in a child process. It is a coherence check,

not a security sandbox.

5. Allowlist the project-local Tool

export OPENSIP_CLI_ALLOW_PROJECT_TOOLS=hello-tools

Use a comma-separated list for more than one Tool. Avoid '*' unless you trust

every project-local tool in the repo.

6. Run it

opensip hello-tools
opensip hello-tools --json

Logging and failures in your handler

Log run start with the scope-backed logger (writes to .runtime/logs/ when configured):

cli.logger.info({ evt: 'hello-tools.run.start', module: 'hello-tools:cli' });

When the command cannot run (missing recipe, bad path), report a failure through the host:

await cli.reportFailure({
  message: 'Recipe not found: example',
  exitCode: 2,
  jsonRequested: opts.json === true,
});

Uncaught ToolError subclasses are also rendered by the host — prefer reportFailure

when you want a custom message or structured log event.

7. See it in the Tool inventory

opensip tools list --project

The row should show the hello-tools id, project source, and hello-tools command.

8. What changes for publishable Tools

The tracked sidecar layout is ideal while authoring inside one repo. To distribute a Tool:

A publishable npm scaffold is deferred until consumption-side verification and

trust enforcement mature (see ADR-0076).

tools validate and tools install execute the candidate package module as part of validation. Install scripts are blocked and runtime probing has a timeout, but this is still code execution with your user privileges.

Where to go next

| You want to ... | Go to |

|---|---|

| Learn the full Tool contract | Full Tool plugins |

| Read the command grammar | Command surface taxonomy |

| Manage installed Tools | tools command |

| See the allowlist environment variable | Environment variables |

| Understand Tool architecture | The tool-plugin model |