# pi-english-tutor

![A pi session showing a sent message followed by a dim grammar note listing two
corrections: "dont" to "doesn't" (subject_verb_agreement) and "its" to "it's"
(spelling_typo)](docs/img/english-note.png)

A [pi](https://pi.dev) extension that checks your outgoing messages for
grammar and usage errors with a cheap second model, logs them, and shows a dim
note below the message. `/english` reads the log back as a ranked report.

No setup: install it, write, run `/english`.

## Install

1. Install the extension.
2. Write. Every message is checked from the first one.
3. Run `/english` to see your report (`--since YYYY-MM` to limit the range).

The ranked report is useful after a handful of messages. The
improving/regressing marker appears once the log spans two calendar months.

## What it does

- Checks each message in the background against a built-in taxonomy of 14
  categories — *after* it has been sent to the session model unmodified.
  Correction never delays or alters what you send.
- Appends errors to `~/.pi/english-tutor/log.jsonl`, plus a `checked` record
  for every message examined (including clean ones) so rates can be normalized
  against how much you wrote.
- `/english` ranks categories by frequency with counts, rates per 100 messages
  checked, and a month-over-month trend marker.

See [`docs/taxonomy.md`](docs/taxonomy.md) for the categories and how to
override them with your own `taxonomy.json`.

## Privacy

**Notes never reach the session model.** The `input` handler returns
`{ action: "continue" }` synchronously with your text unchanged before any
correction work starts — including when the extension is disabled or the
correction call fails. Notes are stored as `custom` session entries, which
`buildSessionContext()` excludes by design. Verify it yourself with pi's
`before_provider_request` hook.

**A second provider does see message text.** Classification sends your message
to the correction model. A message is skipped entirely — never transmitted, no
log record — if it:

- has fewer words than `skipShortMessages` (default 4),
- is longer than 2000 characters, or
- looks like code or terminal output (fenced blocks, shell prompts, stack
  traces, dense file paths, or lots of code symbols).

Live classification is the only thing that transmits text: nothing reads past
sessions, and nothing leaves the project you're typing in.

## Configuration

`~/.pi/english-tutor/settings.json`, created if absent:

```json
{
  "enabled": true,
  "correctionProvider": "openrouter",
  "correctionModel": "deepseek/deepseek-v4-flash",
  "logPath": "~/.pi/english-tutor/log.jsonl",
  "skipShortMessages": 4
}
```

Point `correctionProvider` / `correctionModel` at any pair configured in your
pi setup. Setting `"enabled": false` makes zero correction calls, writes zero
records, and renders zero notes.
