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:
- staging installs run
npm install --ignore-scripts, so install-time
hooks (the classic supply-chain vector) never fire;
- the module import runs in a child process with a 30-second hard timeout —
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
tools install <spec>
Atomic stage → validate → activate:
- Stage into a temp host (
--ignore-scripts). - Run the full
tools validatesections against the staged bytes. - Only a
passedverdict activates — and activation installs a tarball
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:
- installed in one scope → plain
tools uninstall <id>works; - installed in both scopes → requires
--globalor--project; - bundled tools are rejected (they ship with the CLI);
- project SQLite data is never deleted by uninstall alone.
--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:
sessionsrows (per-tool payloads cascade),- baseline entries + the baseline existence marker,
- ordinary
tool_staterows for every owned identity, - the corresponding host compatibility rows stored under the reserved
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
01-cli-commands.md— the full command inventory.../50-extend/06-full-tool-plugins.md
— how to build a package that contributes a full command surface.
- ADR-0041 / ADR-0042 / ADR-0043 in
docs/decisions/— the decisions behind
the surface, the storage contract, and the config-namespace warning.