Docs
Everything you need to run Ironheights locally. The full reference lives in the GitHub README.
Install
Ironheights requires Node.js 20 or newer.
Or install the command. ih is the same command.
Get it only from npm, GitHub releases, or this site. Releases on npm are published with a provenance signature.
60-second quickstart
Commands
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.
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).
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.
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.
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
| Id | Check | Severity | When it fires |
|---|---|---|---|
IH-COEX-001 | Two tool-call guards | medium, low or info | The Ironheights guard and another plugin both register before_tool_call. A block ends the chain, so the higher priority decides. |
IH-COEX-002 | Ironheights blocks the other tool | medium in enforce, info in monitor | The 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-003 | Two owners of the same files | medium or info | A tool that restores or removes files is present and an Ironheights baseline or guard watches the same agent files. |
IH-COEX-004 | Config rewriting | low | A tool that edits OpenClaw config or file permissions is present. Ironheights never writes openclaw.json. |
IH-COEX-005 | Shared state paths | medium | Ironheights state sits inside, or contains, a folder another tool uses. |
IH-COEX-006 | Double network use | info | Two or more detected tools contact ClawHub or a vendor cloud. A tool that uploads skill content is named. |
IH-COEX-007 | Scheduled scans | info | A detected tool runs on a schedule. Run the Ironheights scan at a different minute. |
IH-COEX-008 | Instruction overlap | low | Several skills tell the agent to scan or vet installs, so the model may run each and pick one answer. |
IH-COEX-009 | Traffic-intercepting proxy | info | A loopback HTTP_PROXY or HTTPS_PROXY, or a monitoring proxy, is set. Ironheights network commands do not read those variables by default. |
IH-COEX-010 | False trust | medium | Your Ironheights config ignores, suppresses or allowlists a path that carries the name of a security tool. |
IH-COEX-011 | Plugin allowlist | low | plugins.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.
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.
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
| Source | Path |
|---|---|
| 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 skills | real paths linked from ~/.openclaw/plugin-skills |
| Extra directories | skills.load.extraDirs in ~/.openclaw/openclaw.json |
The default workspace is ~/.openclaw/workspace. Set IRONHEIGHTS_HOME to keep the baseline and quarantine somewhere else.