CLI Reference

h2h ("hush to hush") is the official CLI for HushSpec policy management. It provides 11 subcommands covering validation, testing, formatting, auditing, signing, and emergency controls.

Installation

Install from crates.io with Cargo:

shell
cargo install hushspec-cli

Or download a prebuilt binary from GitHub Releases.

Verify the installation:

shell
h2h --version

h2h validate

Validate policy files against the HushSpec schema. Checks YAML syntax, structural validation, and optionally resolves extends references.

shell
h2h validate <files...> [--format text|json] [--strict]

Flags

  • --format, -f - Output format: text (default) or json
  • --strict - Also verify that extends references resolve correctly

Example

shell
# Validate a single policy
h2h validate policy.yaml

# Strict mode with JSON output
h2h validate --strict --format json policy.yaml

Exit codes: 0 = all valid, 1 = validation errors, 2 = file not found.

h2h test

Run evaluation test suites against policies. Test fixtures define expected decisions for specific actions and verify the policy produces them.

shell
h2h test [files...] [--fixtures <dir>] [--policy <file>] [--format text|tap|json]

Flags

  • --fixtures - Directory containing .test.yaml fixture files
  • --policy, -p - Policy file to test against (overrides the policy embedded in fixtures)
  • --format, -f - Output format: text (default), tap, or json

Example

shell
# Run all fixtures in a directory
h2h test --fixtures ./tests/

# Test a specific policy against fixtures
h2h test --policy policy.yaml --fixtures ./tests/

# TAP output for CI integration
h2h test --fixtures ./tests/ --format tap

h2h init

Scaffold a new policy project. Creates a .hushspec/ directory with a policy file and starter test fixtures.

shell
h2h init [--preset <preset>] [--dir <path>]

Flags

  • --preset - Security preset: default, strict, or permissive
  • --dir - Directory to create .hushspec/ in (defaults to current directory)

Example

shell
# Scaffold with the default preset
h2h init

# Scaffold with strict preset in a specific directory
h2h init --preset strict --dir ./my-project

h2h lint

Run static analysis and best-practice checks on policy files. Detects empty rule blocks, overlapping patterns, shadowed exceptions, overly broad wildcards, regex complexity, and more.

shell
h2h lint <files...> [--format text|json] [--fail-on-warnings]

Flags

  • --format, -f - Output format: text (default) or json
  • --fail-on-warnings - Exit 1 if any warnings are reported (not just errors)

Example

shell
# Lint a policy
h2h lint policy.yaml

# Strict linting in CI (fail on warnings)
h2h lint --fail-on-warnings policy.yaml

Lint codes: L001 empty rule block, L002 overlapping patterns, L003 shadowed exception, L004 overly broad wildcard, L005 empty blocklist with default allow, L006 regex complexity, L007 disabled rule, L008 duplicate pattern, L009 missing secret patterns, L010 unreachable allow.

h2h diff

Compare two policies and show effective decision changes. Generates probes from both policies and evaluates them to detect tightened, relaxed, escalated, or demoted decisions.

shell
h2h diff <old> <new> [--format text|json]

Flags

  • --format, -f - Output format: text (default) or json

Example

shell
# Compare two policy versions
h2h diff policy-v1.yaml policy-v2.yaml

# JSON output for programmatic analysis
h2h diff --format json old.yaml new.yaml

h2h fmt

Format policy files into canonical form. Sorts list entries, normalizes field ordering, and ensures consistent quoting.

shell
h2h fmt <files...> [--check] [--diff] [--format text|json]

Flags

  • --check - Check formatting without modifying files (exit 1 if changes needed)
  • --diff - Show what would change without modifying files
  • --format, -f - Output format: text (default) or json

Example

shell
# Format in place
h2h fmt policy.yaml

# Check formatting in CI
h2h fmt --check policy.yaml

# Preview changes without writing
h2h fmt --diff policy.yaml

h2h audit

Display governance metadata and run advisory checks. Inspects policy metadata fields (author, approver, classification, lifecycle state, expiry) and reports their presence. Audit is advisory - it always exits 0.

shell
h2h audit <file> [--format text|json]

Flags

  • --format, -f - Output format: text (default) or json

Example

shell
# Audit a policy
h2h audit policy.yaml

# Machine-readable audit report
h2h audit --format json policy.yaml

Checks performed: has author, has approver, has approval date, classification set, lifecycle state set, policy version set, expiry date set, restricted approval check.

h2h panic

Manage emergency panic mode (deny-all kill switch). Creates or removes a sentinel file that causes all evaluate() calls to return deny.

shell
h2h panic activate [--sentinel <path>]
h2h panic deactivate [--sentinel <path>]
h2h panic status [--sentinel <path>]

Subcommands

  • activate - Create the sentinel file, activating deny-all mode
  • deactivate - Remove the sentinel file, restoring normal evaluation
  • status - Check whether panic mode is currently active

Flags

  • --sentinel - Path to the sentinel file (defaults to .hushspec_panic in the current directory)

Example

shell
# Activate panic mode
h2h panic activate --sentinel /tmp/hushspec.panic

# Check status
h2h panic status

# Deactivate
h2h panic deactivate

h2h sign

Sign a policy file with an Ed25519 private key. Produces a detached .sig file containing the signature, content hash, key ID, and timestamp.

shell
h2h sign <policy> --key <keyfile> [--key-id <id>] [--signer <identity>] [--output <path>]

Flags

  • --key, -k - Path to the Ed25519 private key file
  • --key-id - Key identifier (defaults to a truncated hash of the public key)
  • --signer - Human-readable signer identity (e.g. email address)
  • --output, -o - Output path for the .sig file (defaults to <policy>.sig)

Example

shell
# Sign a policy
h2h sign policy.yaml --key h2h.key

# Sign with signer identity
h2h sign policy.yaml --key h2h.key --signer "ops@example.com"

h2h verify

Verify a policy file's detached Ed25519 signature. Checks the content hash and cryptographic signature against the provided public key.

shell
h2h verify <policy> --key <pubkey> [--sig <sigfile>]

Flags

  • --key, -k - Path to the Ed25519 public key file
  • --sig, -s - Path to the detached .sig file (defaults to <policy>.sig)

Example

shell
# Verify a signed policy
h2h verify policy.yaml --key h2h.pub

# Verify with explicit signature file
h2h verify policy.yaml --key h2h.pub --sig policy.yaml.sig

h2h keygen

Generate a new Ed25519 keypair for policy signing. Creates h2h.key (private, mode 0600) and h2h.pub (public) in the output directory.

shell
h2h keygen [--output-dir <dir>]

Flags

  • --output-dir - Directory to write key files to (defaults to the current directory)

Example

shell
# Generate keys in current directory
h2h keygen

# Generate keys in a specific directory
h2h keygen --output-dir ./keys

Common Workflows

Validating and linting before commit

Run both validate and lint as a pre-commit check to catch schema errors and policy anti-patterns early:

shell
h2h validate --strict .hushspec/policy.yaml && \
h2h lint --fail-on-warnings .hushspec/policy.yaml && \
h2h fmt --check .hushspec/policy.yaml

Running conformance tests

Use test fixtures to verify your policy produces the expected decisions:

shell
# Initialize a new project with starter tests
h2h init --preset default

# Run the tests
h2h test --fixtures .hushspec/tests/

# Run tests with TAP output for CI
h2h test --fixtures .hushspec/tests/ --format tap

Policy diffing for PR review

Compare the base branch policy against the PR branch to understand how decisions change:

shell
# Diff the policies
h2h diff main:.hushspec/policy.yaml pr:.hushspec/policy.yaml

# JSON output for automated review comments
h2h diff --format json old-policy.yaml new-policy.yaml

Emergency panic mode

When you need to immediately deny all agent actions:

shell
# Activate: all evaluate() calls now return deny
h2h panic activate --sentinel /var/run/hushspec.panic

# Check current status
h2h panic status --sentinel /var/run/hushspec.panic

# Deactivate: resume normal policy evaluation
h2h panic deactivate --sentinel /var/run/hushspec.panic