intervoice
What it does: A markdown-only Claude Code plugin (no MCP server, no build step) that drives Claude’s prose from a single global multi-register voice profile at ${XDG_CONFIG_HOME:-~/.config}/intervoice/voice-profile.md (symlinked from dotfiles; INTERVOICE_PROFILE overrides). A bash resolver (scripts/resolve-register.sh) extracts the ’## Foundation’ section (shared rules + hard bans) merged with one selected ’## Register N’ section (Team/Internal/External/Open Source dosage), either named explicitly or inferred from the target file’s doc-type. Four skills consume that working profile: apply (rewrite content in voice, self-check hard bans like no em-dashes/no banned AI-tell vocab), compare (score text + itemize hard-ban violations vs dosage mismatches, read-only), analyze (turn samples into Foundation/register prose, optionally via the Sonnet voice-analyzer close-reading agent), optimize (token-trim the profile without dropping rules). One router command (/intervoice). Explicitly replaces the deprecated interfluence (which routed per-file by glob).
Rationale: The design is genuinely good and the engineering is careful: the Foundation-as-hard-bans + register-as-dosage model is the right abstraction (it captures the real shape of how people write differently by context, which the README argues well), the resolver is clean/tested with sane exit codes, skills are tightly scoped with progressive disclosure and a self-check step, and security hygiene is strong (corpus gitignored so personal data never enters the repo; index split into pure-float .npz loaded allow_pickle=False + JSONL text sidecar to dodge unsafe deserialization). This is not a keep, though, because the plugin is running its weakest documented pipeline while a better one sits finished-but-disconnected in the same repo. The team already did the SOTA research, already chose retrieve->rewrite->self-critique, already built and verified the retriever, and already filed the beads (sylveste-7pn to wire it, sylveste-q4m for the LUAR upgrade) — then stranded the work mid-build. The fix is wiring + one self-refine pass, not a rethink, so this is ‘improve’ rather than ‘modernize’ (the modern paradigm is already designed in-repo, just unconnected) and not ‘keep’ (real, actionable, already-scoped capability gap with the gap explicitly acknowledged in the plugin’s own docs). Secondary, low-effort: the README/AGENTS.md actively claim ‘the resolver is the only script’ and ‘edit-feedback loop deliberately not carried over,’ which now contradicts the shipped retrieval scaffold — the docs understate what the plugin contains and should be reconciled.
SOTA gap: The validated retrieve -> rewrite -> self-critique pipeline (few-shot style-nearest exemplars + a reflection/verification pass) is built but not wired in. The repo contains a complete, tested stylometric retrieval layer (style_features.py, build_index.py, retrieve.py with greedy-MMR diversity and a pluggable —scorer seam, plus a 734-sample gitignored corpus index) AND the project’s own research doc (docs/research/2026-05-31-llm-style-transfer-soa.md) concluding the naive single-pass ‘rules + rewrite’ the apply skill currently does is ‘the weakest method in the literature.’ But grep across skills/commands/agents for retrieve.py / exemplar / self-critique / STAYKATE / LUAR returns zero hits: apply never calls the retriever and never runs a self-refine pass. This maps directly to the SOTA reflection+verification-loop finding (structured, tool-grounded critique beats free-form rewriting) and the embedding-gated few-shot-exemplar finding. The deeper frontier gap is the planned LUAR/StyleDistance learned style embedding (bead sylveste-q4m) to replace the stylometric proxy and double as an automatic voice-fidelity cosine metric — i.e. a closed eval loop on ‘does this still sound like the author’ rather than relying on the model’s self-judgment.
Redundancy: Low to none. interfluence is the deprecated predecessor that this plugin cleanly replaces (AGENTS.md notes both must not be installed together — interfluence’s PostToolUse:Edit hook double-logs). No functional overlap with active plugins: intersearch and interknow/qmd provide embedding/search infra but over docs/knowledge corpora, whereas intervoice’s retrieval is purpose-built stylometric (style axis, not topic) over the user’s own gitignored personal prose. interscribe enforces CLAUDE.md/AGENTS.md doc boundaries (structure), not authorial voice (prose register). No merge candidate.
Actions:
- Wire retrieve.py into skills/apply/SKILL.md (bead sylveste-7pn): before rewriting, call
python3 scripts/retrieve.py --target <path> -k 4 --diversityfor dynamic style exemplars, combine with 2-3 static most-representative samples (STAYKATE recipe from the repo’s own research doc), include them as few-shot in the rewrite, then add ONE Self-Refine pass critiquing the draft against the resolved profile + hard bans before presenting. ~2 LLM calls + the existing script. - Upgrade the —scorer seam from stylometric proxy to a learned style embedding (LUAR/StyleDistance, bead sylveste-q4m) and reuse it as a voice-fidelity metric: cosine(rewrite, corpus-centroid) printed by compare and used as a structured, tool-grounded gate in apply’s self-critique — turning self-judgment into a measurable eval loop (the SOTA reflection+verification finding). Reject any refine iteration that drops voice cosine.
- Reconcile docs with shipped code: README.md (‘No MCP server… access is a Read plus a register resolver’, ‘edit-feedback loop deliberately not carried over’) and AGENTS.md (‘the resolver is the only script’) now understate the plugin — document the corpus/retrieval scaffold, the corpus rebuild command, and the gitignored-personal-data contract so the next session does not mistake the retriever for dead code.
- Apply the corpus-grounded profile corrections already identified (bead sylveste-l3a): make the em-dash hard ban density-based not presence-based (corpus baseline is 0.9/10k, nonzero), add burstiness preservation as a first-class apply goal (stdev 13.0 is the strongest human signal LLMs flatten), and prune/replace the unattested ‘favorite words’ list; remind the user to commit dotfiles after, since the profile is a symlink.