Skip to the content.

ruleman

A static analysis CLI for repositories. Point it at a declarative JSON(C) rule file and it checks things like “does this file exist” or “does this JSON file have the expected value at this key” — useful for enforcing repo-wide conventions in CI.

View on GitHub · View on npm

Install

npm install --save-dev ruleman
# or run once without installing
npx ruleman

Prebuilt native binaries are published for Linux (x64/arm64), macOS (x64/arm64), and Windows (x64) — no Rust toolchain required on install.

Quick start

npx ruleman init   # scaffolds ruleman.json
npx ruleman        # runs the checks
// ruleman.json
{
  "$schema": "https://codebase-jp.github.io/ruleman/schema.json",
  "rules": [
    {
      "type": "file",
      "severity": "error",
      "state": "present",
      "files": ["README.md", "LICENSE"]
    },
    {
      "type": "content",
      "severity": "warn",
      "format": "json",
      "file": "tsconfig.json",
      "key": "compilerOptions.strict",
      "expected": true
    }
  ]
}

Running ruleman with no arguments auto-discovers ruleman.json / ruleman.jsonc / .ruleman.json, searching the current directory and walking up — the same pattern used by eslint, prettier, and biome. Pass --config <path> to point at a specific file instead.

Config reference

Add "$schema": "https://codebase-jp.github.io/ruleman/schema.json" to any config file to get autocomplete and validation in editors that support the $schema convention (VS Code, JetBrains IDEs, etc.).

Field Type Description
$schema string Optional; points editors at the JSON Schema.
extends string[] Other ruleman config files to inherit rules from, resolved relative to this file. Cycles are detected and rejected.
rules Rule[] The checks to run, in order.

Every rule accepts a severity:

file

Named and shaped after Ansible’s file module: checks file presence via a state attribute rather than inventing a mirror rule type for the negated case.

{ "type": "file", "state": "present", "files": ["README.md"] }
{ "type": "file", "state": "absent", "files": ["yarn.lock"] }
Field Type Required Description
files string[] yes Paths to check (repo-relative).
state "present" | "absent" no "present" (default) fails if missing; "absent" fails if found.

content

Checks a value inside a structured file. Rather than a json-match rule type today and a yaml-match/toml-match type each time a new format is supported, format selects the parser and the rule type itself stays content. Named to pair with file: file checks whether a file exists, content checks what’s inside it.

state: "match" (default) fails unless key (a dot-separated path) in file equals expected; state: "mismatch" fails when it does.

{
  "type": "content",
  "format": "json",
  "file": "package.json",
  "key": "engines.node",
  "expected": ">=18"
}
Field Type Required Description
format "json" no Parser to use. "json" (default); yaml/toml planned.
file string yes Path to the file.
key string yes Dot-separated path into the parsed document.
expected any yes The value key is compared against.
state "match" | "mismatch" no "match" (default) requires equality; "mismatch" requires inequality.

extends

Share rules across repos or config files:

// ruleman.json
{
  "extends": ["./base.ruleman.json"],
  "rules": [{ "type": "file", "files": ["CHANGELOG.md"] }]
}

Rules from extended files run first, in the order listed, followed by the file’s own rules. extends paths are resolved relative to the file that declares them, and circular references are rejected with an error.

Comments and trailing commas

Config files are parsed as JSONC, so comments (//, /* */) and trailing commas are allowed.

CLI reference

ruleman [--config <path>]     # run checks (default command)
ruleman init [--force]        # scaffold a starter ruleman.json
ruleman --version
ruleman --help

Building from source

cargo build --release
./target/release/ruleman --version

License

MIT © Codebase Inc.