Metadata-Version: 2.4
Name: houserules
Version: 0.1.1
Summary: Natural-language linting: write your rules in English, let an LLM enforce them.
Project-URL: Homepage, https://github.com/theycallmeswift/houserules
Project-URL: Issues, https://github.com/theycallmeswift/houserules/issues
Project-URL: Source, https://github.com/theycallmeswift/houserules
Project-URL: Documentation, https://github.com/theycallmeswift/houserules/blob/main/docs/cli.md
Author-email: Swift <swift@majorleaguehacking.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.10
Requires-Dist: python-dotenv>=1.2.2
Requires-Dist: pyyaml>=6
Description-Content-Type: text/markdown

<p align="center">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="/assets/houserules-dark.svg">
    <source media="(prefers-color-scheme: light)" srcset="/assets/houserules-light.svg">
    <img alt="houserules" src="/assets/houserules-light.svg" width="460">
  </picture>
</p>

<p align="center">Natural-language linting. Write your rules in English, let an LLM enforce them.</p>

<p align="center">Today: Python source only (<code>*.py</code>), Google Gemini the only provider.</p>

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](https://ai.google.dev/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

```bash
pip install houserules
```

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

```bash
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:

```bash
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`](https://github.com/theycallmeswift/houserules/blob/main/.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`.

```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/`](https://github.com/theycallmeswift/houserules/blob/main/examples/basic-demo/) directory shows the same
idea in a runnable miniature. Its README has the exact command and sample
findings.

## Run

```bash
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`](https://github.com/theycallmeswift/houserules/blob/main/docs/github-actions.md).

## How it works

```mermaid
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`](https://github.com/theycallmeswift/houserules/blob/main/docs/github-actions.md).

Full command, flag, config, and exit-code reference: [`docs/cli.md`](https://github.com/theycallmeswift/houserules/blob/main/docs/cli.md).

## Use as a library

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

```python
from houserules import Rule, StyleLintConfig, run_advisory_lint
```

## Develop

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