Skip to main content

Natural-language linting: write your rules in English, let an LLM enforce them.

Project description

houserules

Natural-language linting. Write your rules in English, let an LLM enforce them.

Today: Python source only (*.py), Google Gemini the only provider.

Some conventions are too subjective for a regex or an AST — "comments should explain why, not narrate what the code does," "user-facing errors should explain what went wrong and how to recover." Write those rules in plain English and houserules enforces them with an LLM.

A detector model flags violations; a verifier pass re-checks each one and drops the false positives. It's advisory by default: reports findings, exits 0, never blocks. Set mode: strict to exit 1 on findings.

Data, privacy & cost

Each run sends your rule text plus the full numbered source of the files it checks to Google's Gemini API. With --base, that's the files containing changed lines — still whole files, not just the changed lines.

On Gemini's unpaid tier, inputs may be used to improve Google's products and may be reviewed by humans; paid-tier inputs are not. Read the Gemini API terms before pointing it at anything sensitive.

Cost and latency are unmeasured so far. Expect roughly a per-PR token estimate in the low thousands and a few seconds to low-tens-of-seconds of latency per run — a ballpark, not a benchmark.

Install

pip install houserules

Create a .env file with a Gemini API key. In a source checkout, start from the tracked example:

cp .env.example .env

The CLI finds the nearest .env from the current directory upward. An already exported GEMINI_API_KEY takes precedence over the file.

Configure

Generate a starter .houserules from your repo's own conventions:

houserules init

...or drop one in by hand. houserules needs a .houserules file at your repo root (JSON or YAML; .houserules.json, .houserules.yaml, and .houserules.yml also work). See .houserules.example.yaml for a full example.

If you pass a single explicit directory path and do not override discovery with --config, houserules walks from the current directory through that target and uses the deepest config it finds. That lets houserules examples/basic-demo/ load examples/basic-demo/.houserules.yaml.

model: gemini-3.1-flash-lite
mode: advisory
paths:
  - src
rules:
  - id: comments-explain-why
    description: >
      Comments should explain intent, rationale, or non-obvious constraints—not
      restate what the code makes clear.
  - id: actionable-error-messages
    description: >
      User-facing error messages should explain what went wrong and how to
      recover without exposing implementation details.

Keep mechanically checkable conventions such as TODO markers, import order, and unused variables in Ruff. Use houserules for conventions that require context or judgment.

The examples/basic-demo/ directory shows the same idea in a runnable miniature. Its README has the exact command and sample findings.

Run

houserules                     # lint the configured default paths (verified)
houserules src/ tests/         # lint specific paths
houserules --skip-verification # detector only, no second-pass verifier
houserules --mode strict       # exit 1 if anything is found
houserules --base main         # lint only lines changed since a git ref
houserules --dry-run           # plan work and count model calls, no API calls

Without GEMINI_API_KEY in the environment or a .env file, houserules prints an error and exits 2 — a missing key is a configuration error, not a quiet skip. For CI, gate the job on a same-repo if: condition so fork pull requests (which have no access to the secret) don't fail; see docs/github-actions.md.

How it works

flowchart LR
    A["📝 Rules + 📄 source"] --> B["🔍 Detector"] --> C["✅ Verifier"] --> D["📢 Report"]
  1. Rules + source go in — your plain-English rules and the files to check.
  2. Detector flags candidate violations.
  3. Verifier (on by default) re-checks each one and drops the false positives.
  4. Report what survives — terminal diagnostics or inline PR annotations.

A surviving finding renders as one path:line:column: rule-id message line:

src/app.py:42:5: comments-explain-why Remove the comment; it restates the assignment below.

(PR annotation screenshot: follow-up.)

Scope to git-changed lines with --base.

Run on pull requests

Lint each PR's changed lines and surface findings as inline annotations on the diff. Copy-paste setup: docs/github-actions.md.

Full command, flag, config, and exit-code reference: docs/cli.md.

Use as a library

The framework depends only on python-dotenv and PyYAML, and is importable directly:

from houserules import Rule, StyleLintConfig, run_advisory_lint

Develop

make install   # uv sync
make test      # pytest
make lint      # ruff

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

houserules-0.1.1.tar.gz (46.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

houserules-0.1.1-py3-none-any.whl (41.7 kB view details)

Uploaded Python 3

File details

Details for the file houserules-0.1.1.tar.gz.

File metadata

  • Download URL: houserules-0.1.1.tar.gz
  • Upload date:
  • Size: 46.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for houserules-0.1.1.tar.gz
Algorithm Hash digest
SHA256 8d17c661c20209fff23c1cfd7c8020116edbdadf76f5ac89478703f64bb20916
MD5 80e81336459baa36230c6977dc54468d
BLAKE2b-256 2b5244cf190e421338857c15fdb3e0e99f18442973fadb6fb84ebb7e5e66dcd2

See more details on using hashes here.

File details

Details for the file houserules-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: houserules-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 41.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for houserules-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8bd107cdf9042cfb899864ce3981322e4c9a2c1c85edffa7b1d665a2bda60eac
MD5 9ce6d486729acd0e95939e1503790560
BLAKE2b-256 06ae38bd4cc93749e11a80bd9e44c1d1832c0b691d520f09763284185910c35c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page