{"_id":"@blackbird-merula/claudishlint","name":"@blackbird-merula/claudishlint","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@blackbird-merula/claudishlint","version":"0.1.0","description":"A Pi extension that lints agent responses for 'Claudish' prose and prompts a plain-English rewrite.","type":"module","keywords":["pi-package","claudish","linter","extension"],"repository":{"type":"git","url":"git+https://github.com/blackbird-merula/claudishlint.git"},"pi":{"extensions":["./src/index.ts"]},"scripts":{"lint":"biome check .","format":"biome format --write .","test":"node --test src/claudishlint/test/*.test.ts","sanity":"node --test src/claudishlint/test/sanity.test.ts","typecheck":"tsc --noEmit"},"peerDependencies":{"@earendil-works/pi-coding-agent":"*"},"devDependencies":{"@biomejs/biome":"^2.5.11","@types/node":"^24.0.0","typescript":"^5.8.0"},"gitHead":"9c67876012c2892a1529365b1ef0d7184123e9c7","_id":"@blackbird-merula/claudishlint@0.1.0","bugs":{"url":"https://github.com/blackbird-merula/claudishlint/issues"},"homepage":"https://github.com/blackbird-merula/claudishlint#readme","_nodeVersion":"24.14.0","_npmVersion":"11.8.0","dist":{"integrity":"sha512-D3BC+Q334cgwZYQizXfskUqEGdTP2O5HFPvqKIbD/c4jVEssycTGyJZO+L5EW9LpREIvuB7SSoxlkP/wW5ah7A==","shasum":"79eba690183b88d5a015955f43e46823c7dbb5e4","tarball":"https://registry.npmjs.org/@blackbird-merula/claudishlint/-/claudishlint-0.1.0.tgz","fileCount":8,"unpackedSize":43780,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICA1B7ScQXlThUkRdhWfTyDMqZGnG2KJYMIquTdaG7t9AiEA3G0SYOjP5CZk2Qo+L3HKAMzq5l9EZuklEfDV2SMMWBI="}]},"_npmUser":{"name":"blackbird-merula","email":"blackbird.merula@proton.me"},"directories":{},"maintainers":[{"name":"blackbird-merula","email":"blackbird.merula@proton.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/claudishlint_0.1.0_1788287246642_0.42447378734086083"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-01T18:27:26.412Z","0.1.0":"2026-09-01T18:27:26.776Z","modified":"2026-09-01T18:27:27.012Z"},"maintainers":[{"name":"blackbird-merula","email":"blackbird.merula@proton.me"}],"description":"A Pi extension that lints agent responses for 'Claudish' prose and prompts a plain-English rewrite.","homepage":"https://github.com/blackbird-merula/claudishlint#readme","keywords":["pi-package","claudish","linter","extension"],"repository":{"type":"git","url":"git+https://github.com/blackbird-merula/claudishlint.git"},"bugs":{"url":"https://github.com/blackbird-merula/claudishlint/issues"},"readme":"# claudishlint\n\nClaudish is the dense, metaphor-heavy style some models slip into.\nclaudishlint is a heuristics-based linter and Pi extension designed to\ntranslate Claudish into English.\nIt detects Claudish in agent responses, provides structured feedback,\nand prompts for a fixed response.\n\n- `src/claudishlint/`. A small heuristic linter. It has no runtime\n  dependencies. It flags the structural tics and the vocabulary that mark\n  Claudish. Every finding carries feedback. The feedback tells the writer what\n  to write instead.\n- A Pi extension. Runs via hook at the end of the agent's turn. It runs the\n  linter over the finished response. When a response trips enough rules, it\n  queues a follow-up. The follow-up asks the model to rewrite the response. It\n  quotes each finding and its rule's advice. The rules the linter applies are\n  user-configurable.\n\nThe repo also ships style references and the real-data sources. The linter\nuses these sources to calibrate its heuristics.\n\n## How it works\n\n```\nagent finishes a response\n        │\n        ▼\nlint the response with claudishlint\n        │\n        ├─ pass ─► done\n        │\n        └─ rewrite ─► queue one follow-up that quotes each finding\n                      and asks the model to fix its own prose\n```\n\nThe loop runs exactly once. The extension lints the agent's final message.\nWhen the verdict is `rewrite`, it sends one follow-up re-prompt. Each\ninteraction receives a single re-prompt, so a long turn still ends after one\nfix. The extension then stops and the conversation continues. The goal is to\nremove the Claudish from a finished answer, using one clean rewrite.\n\nThe extension builds the re-prompt from the findings. Each rule carries a\n`description`. This note explains the pattern and tells the writer what to\nwrite instead. The extension quotes each finding's matched text beside that\nnote. Then it asks the model to rewrite the whole response, quoting the\nembedded Simple Language Style Guide. The model restyles. It answers nothing\nbeyond the rewrite, so every fact survives.\n\n## The linter\n\nSee [src/claudishlint/README.md](src/claudishlint/README.md) for the library itself.\nIn short:\n\n```ts\nimport { review } from \"./src/claudishlint/index.ts\"\n\nconst { verdict, findings } = review(responseText, options)\n```\n\n- `lint(text, options?)`. Run every rule over a full response, or run a\n  subset. Return sorted, non-overlapping findings.\n- `review(text, options?)`. The decision layer. It returns\n  `{ verdict, score, threshold, findings }`. `verdict` is `\"rewrite\"` or\n  `\"pass\"`. This is the \"when to re-prompt\" knob the extension calls.\n- `rules`. The rule array in `src/claudishlint/rules.ts`. Each rule has an\n  `id`, `name`, `description`, an optional `minHits`, and a `find(text)`\n  finder.\n\nThe rules cover structural tics (anaphora runs, echo triads, \"X, not Y\"\ncontrasts, chain verbs) and vocabulary derived from the\n[load-bearing](https://louisabraham.github.io/load-bearing/) corpus. These\nwords separate Claude-authored writing from everything else.\n\n## The Pi extension\n\nThe Pi extension connects the linter to an agent's turn. It subscribes to the\nend of the agent's run. It lints the final message. When `review()` returns\n`rewrite`, it sends one follow-up message. The message quotes each finding and\nits rule's `description`. It asks the model to rewrite the prose in plain\nEnglish. It works with any model Pi runs, so the fixed prose stays plain whatever\nproduced it.\n\nTo keep the re-prompt to one per interaction, the extension records that it\nhas already nudged. It uses pi's persistent entry API. A long working session\nwith many turns corrects the prose once. A later request from the user\ntriggers another correction.\n\n## User-configurable rules\n\nYou configure the gate with a JSON file. The extension reads this file from pi's\nconfig directory, `~/.pi/agent/.claudishlint.json` (or wherever `PI_CODING_AGENT_DIR`\npoints). The file maps directly onto `review()`'s options.\n\n```json\n{\n  \"strictness\": 0.8,\n  \"rules\": {\n    \"ai-vocab\": 0,\n    \"colon-triple\": 1\n  }\n}\n```\n\n- `strictness`. A float from 0 to 1. The default is `1`. `1` re-prompts on any\n  finding. `0` never re-prompts. Lower it to tolerate long, mostly-fine\n  messages. The pass/fail line becomes a density of count-aware findings per\n  1000 words. This is the knob to lower when the linter fires too often. There\n  is nothing else to configure at first.\n- `rules`. Per-rule overrides. `0` ignores a rule entirely. Its findings are\n  neither counted nor reported. `1` makes a single finwhyding of that rule block.\n  It blocks regardless of message length. Use this for words you cannot stand.\n  Rules not listed use the global `strictness`. Use this to disable rules that\n  are too noisy for your register. Use this to hard-fail on a tell that bothers\n  you more than the default.\n\nTo list every rule id and what it flags, see the `rules` array in\n`src/claudishlint/rules.ts`.\n\n## Data sources (test fixtures only)\n\nThe raw data in `data/` is used only to calibrate and sanity-check the\nlinter's heuristics. It is not part of the runtime. The extension and the\nlinter read it only during tests.\n\n- `data/claudish_pairs.jsonl`. The\n  [adamrotmil/claudish-pairs](https://huggingface.co/datasets/adamrotmil/claudish-pairs)\n  dataset. Claude Opus wrote the English/Claudish pairs. The English side is\n  the linter's \"should pass\" class. The Claudish side is an extra \"should\n  flag\" class.\n- `data/raw/load-bearing/`. A clone of the\n  [load-bearing](https://github.com/louisabraham/load-bearing) corpus. Its\n  k-means analysis of Claude-authored PR descriptions is the source of the\n  vocabulary rules. PR descriptions written from 2026-04-01 onwards form the\n  linter's positive class.\n","readmeFilename":"README.md","_rev":"1-ba5dda16e02458e8956964555b5e7907"}