Docs

Everything you need to run Ironheights locally. The full reference lives in the GitHub README.

Install

Ironheights requires Node.js 20 or newer.

npx ironheights scan ./path/to/skill

Or install the command. ih is the same command.

npm install -g ironheights
ironheights scan ./path/to/skill

Get it only from npm, GitHub releases, or this site. Releases on npm are published with a provenance signature.

60-second quickstart

npx ironheights doctor
npx ironheights scan ~/.openclaw/workspace/skills/some-skill
npx ironheights baseline create
npx ironheights verify

Commands

ironheights scan <path> [--all] [--json] [--sarif <file>] [--md <file>] [--html <file>] [--format text|json|html]
                    [--since-baseline [file]] [--stdin | --text <text>] [--fail-on <severity>] [--config <file>]
                    [--allow-skipped] [--no-color] [--quiet]
ironheights fetch <owner>/<slug>[@<version>] [--out <dir>]
ironheights safe-install <owner>/<slug>[@<version>] [--dir <skills-dir>] [--accept-review]
ironheights advisories update|show
ironheights baseline create|update|show [--key <file>]
ironheights verify [--key <file>]
ironheights quarantine <skill>
ironheights quarantine restore <id>
ironheights guard status|policy|log
ironheights coexist [--json] [--fail-on <severity>] [--openclaw-config <file>] [--repo <dir>]
ironheights audit-config [--json] [--sarif <file>] [--openclaw-config <file>]
ironheights review <path> [--llm-url <url>] [--llm-model <name>] [--dry-run]
ironheights rules list
ironheights rules show <id>
ironheights doctor
ironheights bench <corpusDir> [--external <file.json>]

Scans make no network call. The commands that do are fetch and safe-install (clawhub.ai), advisories update (ironheights.dev), and scan --llm or review (a model server you choose). Each prints its URL first. See the features page for what each one does and where it stops.

Fetch and safe-install

fetch downloads a ClawHub skill over HTTPS into a staging folder and scans it without running anything. safe-install then copies it into your skills folder only when the verdict is no-findings (or review with --accept-review); block and incomplete are never installed. An existing copy is backed up and restored if the new copy fails.

npx ironheights fetch <owner>/<slug>
npx ironheights safe-install <owner>/<slug>@<version> --dir ~/.openclaw/workspace/skills

Sign your baseline

Create a key file with the script in the baseline signing doc, keep it mode 0600, then sign and check the baseline with it. A mismatch is reported as a tampered baseline (critical IH-INT-001, exit code 2).

npx ironheights baseline create --key ~/.ironheights/baseline.key
npx ironheights verify --key ~/.ironheights/baseline.key

Advisory feed

advisories update downloads and verifies a signed feed, and scan and fetch then report IH-ADV-001 offline for a skill the cached feed lists. The feed is not published yet, so until it is, advisories update has nothing to download and scans report nothing from it. Details are in the advisory feed doc.

Guard plugin

The guard watches OpenClaw tool calls for credential reads, download-and-execute commands, undeclared or high-risk hosts, and writes to agent identity files and skill folders. The default mode is monitor, which logs and does not block. It is not a sandbox. Read the guard doc for the policy file, enforce mode and the threat model.

openclaw plugins install --link /path/to/ironheights --force
openclaw plugins enable ironheights-guard
npx ironheights guard status

Run next to other security tools

coexist (alias doctor coexist) looks for other security tools on this machine and reports where they overlap with Ironheights. It reads files only, runs none of the other tools, makes no network call and writes nothing. Each tool it lists shows the file that gave it away. Read the coexistence doc for the design and the list of known tools.

npx ironheights coexist
npx ironheights coexist --json --fail-on medium
npx ironheights coexist --repo <path-to-project>

It reads:

  • OpenClaw config: plugin and hook entries, plugins.allow and plugins.deny, MCP servers
  • Plugin manifests and the entry file of a plugin, searched for a before_tool_call hook
  • Skill folders and the name line of each SKILL.md, and internal hook folders
  • Known state folders of other tools
  • PATH, for scanner commands such as skill-scanner and gitleaks (looked up, never run)
  • CI and pre-commit files in a project folder you name
Coexistence checks
IdCheckSeverityWhen it fires
IH-COEX-001Two tool-call guardsmedium, low or infoThe Ironheights guard and another plugin both register before_tool_call. A block ends the chain, so the higher priority decides.
IH-COEX-002Ironheights blocks the other toolmedium in enforce, info in monitorThe guard is in enforce mode and a detected tool needs something it blocks, such as an unlisted cloud host or a write to the skills folder.
IH-COEX-003Two owners of the same filesmedium or infoA tool that restores or removes files is present and an Ironheights baseline or guard watches the same agent files.
IH-COEX-004Config rewritinglowA tool that edits OpenClaw config or file permissions is present. Ironheights never writes openclaw.json.
IH-COEX-005Shared state pathsmediumIronheights state sits inside, or contains, a folder another tool uses.
IH-COEX-006Double network useinfoTwo or more detected tools contact ClawHub or a vendor cloud. A tool that uploads skill content is named.
IH-COEX-007Scheduled scansinfoA detected tool runs on a schedule. Run the Ironheights scan at a different minute.
IH-COEX-008Instruction overlaplowSeveral skills tell the agent to scan or vet installs, so the model may run each and pick one answer.
IH-COEX-009Traffic-intercepting proxyinfoA loopback HTTP_PROXY or HTTPS_PROXY, or a monitoring proxy, is set. Ironheights network commands do not read those variables by default.
IH-COEX-010False trustmediumYour Ironheights config ignores, suppresses or allowlists a path that carries the name of a security tool.
IH-COEX-011Plugin allowlistlowplugins.allow does not list ironheights-guard, or plugins.deny lists it, so the guard will not load.

Exit code 0 unless a finding reaches --fail-on, then 1; 64 is a usage error. --json follows a published schema. The guard plugin takes a priority setting (default 80, from -1000 to 1000); OpenClaw runs higher numbers first and a block ends the chain. Detection is heuristic: a renamed or unlisted tool is not found, a name can be copied, and no findings is not proof that tools will not interfere.

Audit your OpenClaw config

audit-config (alias doctor audit) reads your local OpenClaw config and reports IH-CFG-001 to IH-CFG-009. It is offline and read-only, and it does not replace openclaw security audit.

npx ironheights audit-config --json --fail-on high

Exit codes

0 no findings, 1 review, 2 block, 3 incomplete (a file was skipped, or .git or node_modules was not entered, and the scanned files did not reach review or block), 64 usage or config error, 70 internal error, a failed network request, or a rejected signature. --fail-on low|medium|high|critical returns 0 when every finding is below that severity and no file was skipped.

A file over limits.maxFileBytes (1 MiB by default), and any other file the scan could not read, is named in the report as a warning. The verdict is then incomplete with exit code 3. Pass --allow-skipped to accept the skipped files: the warning stays, and the exit code is the finding verdict (0, 1 or 2) again. JSON output has skippedFileCount and skippedDirectories on the document and on each skill, and SARIF stores them in the run properties. ignoreDirs in config, each entry a path and a reason of at least 8 characters, acknowledges .git or node_modules so they stay listed but no longer make the scan incomplete. dist/ is scanned. Every scan also prints an A to F grade; a scan that skipped anything is graded incomplete.

Config

Ironheights reads ironheights.config.json from the current directory, then ~/.ironheights/ironheights.config.json. Unknown keys are an error.

{
  "skillDirs": ["~/.openclaw/workspace/skills"],
  "agentFiles": ["~/.openclaw/workspace/AGENTS.md"],
  "allowDomains": ["docs.example.com"],
  "ignoreGlobs": ["**/*.map"],
  "ignoreDirs": [{ "path": "node_modules", "reason": "packages are not skill instructions" }],
  "ruleOverrides": { "IH-NET-001": { "enabled": true, "severity": "low" } },
  "failOn": "high",
  "limits": { "maxFileBytes": 1048576, "maxFiles": 2000, "maxDepth": 10 },
  "thresholds": { "block": 80, "review": 15 },
  "suppressions": [{ "ruleId": "IH-NET-001", "path": "docs/**", "reason": "documented example hosts" }]
}

A skill can list the hosts it contacts under metadata.ironheights.allowDomains in its SKILL.md frontmatter. IH-NET-001 skips those hosts and their subdomains for that skill only; another skill that calls the same host still reports. Bundled OpenClaw skills do not declare their hosts yet, so scan --all on a stock install still reports their API hosts.

OpenClaw locations

OpenClaw skill locations
SourcePath
Workspace skills<workspace>/skills
Project agent skills<workspace>/.agents/skills
Personal agent skills~/.agents/skills
Managed skills~/.openclaw/skills
Workshop skills~/.openclaw/agents/<agent>/agent/workshop-skills
Bundled skills<openclaw package>/skills
Custodian skills<openclaw package>/custodian-skills
Plugin skillsreal paths linked from ~/.openclaw/plugin-skills
Extra directoriesskills.load.extraDirs in ~/.openclaw/openclaw.json

The default workspace is ~/.openclaw/workspace. Set IRONHEIGHTS_HOME to keep the baseline and quarantine somewhere else.