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.0.tar.gz (40.3 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.0-py3-none-any.whl (36.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: houserules-0.1.0.tar.gz
  • Upload date:
  • Size: 40.3 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.0.tar.gz
Algorithm Hash digest
SHA256 4140ceb6757c7d54aa67874a0bd460e8a237638d371126adf3901223d39b834e
MD5 6db7b0b569652cfae4136925e9745978
BLAKE2b-256 dd163ef6c25c6aa58aa7caf89546330e0d36f4fa5ba33d12df27db0997af1697

See more details on using hashes here.

File details

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

File metadata

  • Download URL: houserules-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 36.6 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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6bc529a96bc55763bef0e278b198da55441c2ed71ef2101e352b695a4da626ab
MD5 b391e550d13d5088381b79f941190a62
BLAKE2b-256 1751bc908f083bc1de0d7c580d4cc5bfb0a51d26ba7e52b0181f9be69fa11669

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