tools — manage whole Tool plugins

The customer-facing command group for whole Tool plugins (ADR-0041): packages

declaring package.json#opensipTools.kind: "tool" that contribute entire

subcommands to the CLI. Seven subcommands — no flag aliases, no tool

singular:

opensip tools list
opensip tools list --available [--lang <language>]
opensip tools doctor
opensip tools validate <spec>
opensip tools create <tool-id>
opensip tools install <spec> [--global|--project]
opensip tools uninstall <name-or-id> [--global|--project] [--purge-data]
opensip tools data-purge <tool-id>

tools is the only way to install/uninstall a whole Tool plugin — the

former plugin add/remove --domain tool path was retired (the per-tool plugin

group is now scoped to a pack-supporting tool's own extension packs, not whole

Tool plugins). tools is implemented over the same host directories and npm

helpers the pack path uses.

A note you should read first: code execution

**tools validate and tools install execute the candidate package's

module.** Validating a package is trusting it to execute. Two mitigations —

which are mitigations, not promises:

hooks (the classic supply-chain vector) never fire;

a crash boundary (a hanging or env-mutating candidate cannot corrupt

the CLI), not a security boundary (same user privileges).

tools list is the read-only exception: it never imports a tool runtime —

every row comes from manifest file reads and the current run's recorded

provenance.

tools list

The effective tool inventory: bundled tools, user-global installs

(~/.opensip-cli/plugins/tool/), and project-local installs

(<project>/opensip-cli/.runtime/plugins/tool/).

| Column | Meaning |

|---|---|

| tool | The tool's stable id (from its manifest). |

| version | Manifest version. |

| source | bundled, global, or project. |

| trust | Why the row is admitted or denied: bundled, managed-install, project-config, env, user-global, or denied. |

| policy | Effective local trust-policy outcome when available: allow, allow-with-conditions, or deny. |

| commands | Command names the manifest declares. |

| [manifest-only] | Present on disk but not loaded by this run (e.g. a broken runtime — listing never imports, so it still lists). |

| [shadowed] | A global row whose tool id is overridden by a project-local install (project wins, matching discovery order). |

--global / --project filter to one install scope. --json puts the rows

under .data.tools.

tools list --available

tools list --available switches from the installed/effective inventory to the

first-party External Tool Adapter catalog. This is the discovery path for teams

that already use scanners such as Gitleaks, Semgrep, Ruff, golangci-lint,

cargo-deny, Bandit, pip-audit, PMD, Dependency-Check, Cppcheck, OSV-Scanner, or

Trivy and want those findings in OpenSIP's sessions, HTML report, JSON/SARIF,

and baseline ratchet.

opensip tools list --available
opensip tools list --available --lang python
opensip tools list --lang c++ --json

The catalog is bundled into the CLI as a generated projection of the shipped

adapter manifests, so it works offline and before any adapter is installed.

Rows include the npm package to install, primary command, language coverage,

network posture, and whether that adapter is already installed in the effective

tool set. --lang <language> implies --available; language values are

canonicalized (c++, cxx, and cpp all match C/C++ coverage), and

language-agnostic adapters match every filter.

A successful pristine opensip init

projects the relevant, not-yet-installed subset of this catalog after its

Try it commands. Multi-language projects receive the stable union of all

language matches plus each language-agnostic adapter once. The footer is advice

only: init does not prompt for or install an adapter. Use

opensip tools list --available whenever you need the complete catalog.

Install the adapter package, then run that adapter's own doctor command before

the first scan:

opensip tools install @opensip-cli/tool-gitleaks
opensip gitleaks doctor
opensip gitleaks --json --gate-save

The adapter package does not install the native scanner binary. Keep managing

gitleaks, semgrep, ruff, trivy, and the other scanner executables through

your normal OS/package-manager path, or pin the binary with

binaries.<tool>.path / OPENSIP_<TOOL>_BIN. See

External tool adapters for the full

adapter table and prerequisites; ADR-0141

records the scanner-binary ownership boundary.

tools doctor

Shows buffered bootstrap diagnostics for the current CLI run. This is the host

diagnostic surface for "which tools loaded, which were denied, and why?" It is

different from an adapter-specific opensip <tool> doctor, which probes that

scanner's native binary, version, network posture, and cache prerequisites.

opensip tools doctor
opensip tools doctor --json

tools validate <spec>

Runs the SAME admission pipeline the CLI's bootstrap admits every tool

through (one validator — a package that validates clean is a package the CLI

will load), plus the storage and config contracts. Sections:

| Section | What it checks |

|---|---|

| manifest | A conformant package.json#opensipTools manifest loads. |

| compatibility | apiVersion is declared and in range (the same gate bundled tools pass). |

| runtime-load | The module imports (child-process probe). |

| tool-shape | The module exports a valid tool. |

| manifest-runtime-coherence | Manifest id + command surface match the runtime. |

| external-output-modes | External manifest command shells do not request host-only output modes such as live-view. |

| config-contract | A manifest that declares config has a runtime Tool.config; its namespace equals the tool id. |

| storage-contract | No DDL strings, no schema-mutation pragmas, no direct datastore-file paths (ADR-0042 Tier A). |

| import-boundaries | No datastore-private schema/migration imports, no migration runners. |

<spec> is an npm spec, a tarball, or a local directory. npm/tarball specs

stage into a throwaway temp host. A local directory validates in place by

default; pass --install-deps to stage it with its dependencies resolved so

the runtime sections can actually load it. Without --install-deps, runtime

sections that fail on unresolved imports report as skipped and the

verdict is incomplete — an unverified runtime is never a pass.

Exit codes: 0 = passed; 2 = failed or incomplete.

tools create <tool-id>

Scaffolds a project-local Tool under opensip-cli/tools/<id>/. <tool-id> is

kebab-case and becomes the primary subcommand name. Generated sidecars include

identity and stableId so they pass the real manifest validator.

| Template | Flag | Output |

|----------|------|--------|

| minimal-js (default) | _(none)_ | Sidecar + dependency-free index.mjs |

| ts-local | --template ts-local | Typed package (src/, package.json, tests) |

Pass --force to overwrite scaffold files when the directory already exists.

tools create writes the scaffold and adds the tool id to tools.trusted; it

does not install dependencies or build. Structured nextSteps in --json

output point at validation and the first run command.

opensip tools create my-audit
opensip tools create my-audit --template ts-local
opensip tools create my-audit --force

Project-local tools remain deny-by-default unless the project config lists their

tool id under tools.trusted. tools create adds that entry for the scaffolded

tool. See

Create your first tool and

ADR-0076.

tools install <spec>

Atomic stage → validate → activate:

packed from the staged dir, so the bytes that run are exactly the

bytes that validated (never a re-resolve of the original spec).

A failed install leaves no discoverable tool behind. Default scope is

global (available in every project for this user); --project installs

into this project's runtime tool host instead.

Installed npm tools are deny-by-default when found ambiently in node_modules.

A successful tools install persists a managed trust record for the selected

scope and returns structured nextSteps (and renders them in text mode) with

the first command to try, for example:

opensip audit-sec

OPENSIP_CLI_ALLOW_INSTALLED_TOOLS remains available as an override for manual

experiments or incident response, but it is not part of the normal install path.

tools uninstall <name-or-id>

Accepts a tool id or an npm package name; resolves the identity from

manifest scans and shows what it resolved before removing. Rules:

--purge-data (project scope only — runtime data lives per project) also

runs the data purge below after a successful uninstall.

Successful uninstall removes the matching managed trust record. It does not edit

committed tools.trusted; that field is for tracked project-local authored tools.

tools data-purge <tool-id>

Deletes one tool's rows from the project datastore — rows, never tables

(the SQLite schema is host-owned and shared). Input must be non-empty and must

not use the reserved host-plane prefix. Registered aliases and stable/layout

identities resolve to one deduplicated owned-key set before any repository call:

host-plane namespace (ADR-0146).

The reserved identity is an internal cleanup detail, not a Tool-addressable

command path; passing it directly is rejected without querying a repository.

Reports bounded aggregate counts per store. Works for any ordinary tool id,

including bundled tools (purging fit history is legitimate). First-party ids

are accepted in either form (fit/fitness, sim/simulation). Unknown but

valid ids still execute one parameterized cleanup set.

Surface note: this is a flat data-purge subcommand (the spec drafted a

nested tools data purge; the host's command machinery is deliberately one

group level deep).

Trust tier, policy, and provenance

tools list and tools validate surface trust tier and install provenance

metadata where available. The local trust-policy plane evaluates those facts at

bootstrap and install time. Default mode preserves existing local trust behavior

and records conditioned decisions when provenance is missing or failed. Strict

mode denies unverified non-bundled Tool loads/installs unless an unexpired exact

exception exists. Bundled first-party tools remain trusted TCB verified by the

release provenance lane.

Use opensip policy explain installed-tool:<id> --action load --json or

opensip policy audit --json to inspect the same decisions outside the install

path.

See also

— how to build a package that contributes a full command surface.

the surface, the storage contract, and the config-namespace warning.