ESC
其他 8 分钟阅读

claudish-to-english:

claudish-to-english:

来源:GitHub

claudish-to-english

A Claude Code plugin that shows a plain-English rewrite of each assistant message, produced by a local LLM via ollama. It is display-only: Claude’s own reasoning and the saved transcript keep the original text — only what you read on screen changes.

An optional second hook rewrites Markdown files into plain English when they are written or edited (opt-in, off by default).

Status: working prototype. Every hook fails open — if anything goes wrong (ollama down, timeout, missing dependency), you simply see Claude’s original text. The plugin can never swallow or corrupt an answer.


Requirements (read this first)

This plugin shells out to a local model. Nothing works until these are in place:

RequirementWhyInstall
ollama, runningDoes the rewriting, locallybrew install ollama then ollama serve
A pulled modelThe actual rewriterollama pull gemma4:26b-mlx (~17 GB; choose the model that fits into your memory)
jqParses hook JSONships with macOS; else brew install jq
curlTalks to ollamaships with macOS

Warm the model once after ollama serve (the first call is a slow cold load):

ollama run gemma4:26b-mlx "hi"

If the local model isn’t ready, the plugin does nothing to your text — Claude’s output shows normally, unchanged. That is by design, not a bug. It skips (fails open) when ollama is down, the request times out, or the model isn’t pulled. The first time that happens in a session it tells you why: the display hook appends a one-line notice on screen, and the Markdown hook shows a systemMessage. So a silent skip is never a mystery (once per session; set CLAUDISH_NOTICE=0 to silence it).

Pick a model you actually have. The default is gemma4:26b-mlx. Pull it (as above), or pull a smaller/faster model and point the plugin at it by setting CLAUDISH_MODEL to that model’s exact ollama tag in your env (see Configuring the plugin). If CLAUDISH_MODEL names a model you have not pulled, every rewrite is skipped — with the one-time notice above.


Install

Directly from this repository (also serves its own marketplace):

/plugin marketplace add gvzdv/claudish-to-english
/plugin install claudish-to-english@gvzdv-plugins

After review by the Anthropic team, the plugin will be available to install from the community marketplace:

/plugin marketplace add anthropics/claude-plugins-community
/plugin install claudish-to-english@claude-community

If the install summary says Run /reload-plugins to activate., run that command.

Try before installing (loads it for one session, no install):

claude --plugin-dir /path/to/claudish-to-english

Run /reload-plugins after edits; if it doesn’t load, check the /plugin Errors tab.


Configuring the plugin

All behavior is controlled by CLAUDISH_* environment variables (full list in Configuration below). When you install from a marketplace, set them in Claude Code’s env block in settings.json — do not edit the plugin’s own hooks/hooks.json, which lives in the read-only plugin cache (~/.claude/plugins/cache/…) and is overwritten on every update.

For a personal, all-projects setup, use ~/.claude/settings.json:

{
  "env": {
    "CLAUDISH_MODEL": "gemma4:26b-mlx",
    "CLAUDISH_MODE": "append"
  }
}

The hooks are subprocesses Claude Code spawns, so they inherit these. A few things to know:

  • Restart Claude Code after editing env. The value is captured at launch, so a running session keeps the old one.
  • env does not merge across scopes. The highest-precedence settings file that defines env supplies the entire block — it isn’t combined with lower scopes. Precedence: managed → local → project → user. Keep all your CLAUDISH_* vars in whichever file wins.
  • Scopes: ~/.claude/settings.json (all your projects) · .claude/settings.json (shared with a repo, checked in) · .claude/settings.local.json (just you, just this repo).

Quick one-off without editing a file — hooks inherit the launching shell:

CLAUDISH_MODEL=llama3.2:3b claude

To confirm the hook is firing, set CLAUDISH_DEBUG=1 and watch "$TMPDIR"/claudish-to-english/debug.log.


How the display hook works

Claude Code fires the MessageDisplay event once per streamed chunk, not once per message. Each fire is a separate process carrying message_id, index, a final flag, and this chunk’s delta (a text fragment, not the whole message). So the hook buffers every delta to a temp file (keyed by message_id) and only calls the model on the final chunk, once the whole message is known:

chunk 0 (final:false) ─┐
chunk 1 (final:false) ─┤ append each delta to $TMPDIR/claudish-to-english/<session>/<message>/<index>.part
chunk 2 (final:false) ─┘  → emit nothing (append) or "" (replace)
chunk 3 (final:true)  ──► reconstruct full message → call ollama once → show the rewrite
                          → delete the buffer

On that final chunk it also reads the original user question from the transcript and passes it to the model as context only — to keep the rewrite on-topic. The model is told never to answer or repeat the question; it only rewrites the assistant’s message.

Display modes

CLAUDISH_MODEOn screenNotes
append (default)Original streams normally, then a 💬 In plain English: block is appended.Safest. No streaming loss; if the LLM fails you just don’t get the extra block.
replaceOnly the simplified version (original chunks suppressed while streaming).Experimental. Appears all at once after LLM latency; on failure it re-shows the full original.

Markdown file rewrite (optional second hook)

A PostToolUse hook (rewrite-md.sh) rewrites Markdown files into plain English when they are written or edited. Unlike the display hook, this changes bytes on disk.

Opt-in by directory. It does nothing unless CLAUDISH_MD_DIR is set, and it only touches *.md files whose resolved path is inside that directory. Every other README, CLAUDE.md, or doc you edit is left alone.

CLAUDISH_MD_MODEResultNotes
sibling (default)Writes NAME.plain.md next to NAME.md.Non-destructive; the original is never touched.
overwriteReplaces NAME.md in place.Adds a <!-- claudish-to-english:rewritten --> marker so a re-write is skipped (idempotent). A weak model can degrade real docs — use with care.

In both modes: YAML frontmatter is split off and re-attached verbatim, fenced code is left to the model instruction, short files are skipped, and the write is atomic. Fail-open here means the file is left exactly as the agent wrote it.

Large files are slow. gemma4:26b-mlx (the default) rewrites at roughly 60 tokens/s, so a long plan or spec can take 30–120s. This hook allows up to CLAUDISH_MD_TIMEOUT (150s) inside a 180s PostToolUse hook budget; if a rewrite still times out you get the one-time notice above — raise those limits, or set CLAUDISH_MODEL to a smaller model.

Enable it for one directory, in sibling mode (the safe default), the same way as every other setting — the env block of your settings.json:

{
  "env": {
    "CLAUDISH_MD_DIR": "/ABS/PATH/docs/plain",
    "CLAUDISH_MD_MODE": "sibling"
  }
}

In overwrite mode the marker comment is written after any YAML frontmatter, so the frontmatter stays on line 1 where parsers expect it.


Configuration (env vars)

VarDefaultMeaning
CLAUDISH_ENABLED1Master switch. 0 = pass everything through.
CLAUDISH_MODEappendappend or replace (display hook).
CLAUDISH_MODELgemma4:26b-mlxollama model name.
CLAUDISH_OLLAMAhttp://localhost:11434ollama base URL.
CLAUDISH_MIN_CHARS200Skip messages/files whose prose (code stripped) is shorter than this.
CLAUDISH_STUB01 = deterministic stub instead of the model (for testing display mechanics).
CLAUDISH_TIMEOUT45LLM client timeout for the display hook (seconds). Keep it below that hook’s timeout (60s).
CLAUDISH_MD_TIMEOUT150LLM client timeout for the Markdown file hook (seconds). Higher on purpose — a large model rewriting a long doc is slow. Keep it below the PostToolUse hook timeout (180s).
CLAUDISH_DEBUG01 = write a debug log to $TMPDIR/claudish-to-english/.
CLAUDISH_NOTICE11 = show a one-time, once-per-session notice when a rewrite is skipped because ollama is unreachable, the call timed out, or the model isn’t pulled (display hook appends it on screen; Markdown hook uses a systemMessage). 0 = stay fully silent (pure fail-open).
CLAUDISH_MD_DIR(unset)Markdown hook opt-in. Only *.md under this directory is rewritten. Unset = the Markdown hook does nothing.
CLAUDISH_MD_MODEsiblingsibling (NAME.plain.md) or overwrite (in place).
CLAUDISH_MD_SUFFIXplainSibling infix: NAME.<suffix>.md.

In hooks/hooks.json the display hook (MessageDisplay) has a 60s timeout and the Markdown hook (PostToolUse) has a 180s timeout — the file hook is higher because a large model rewriting a long document can take a couple of minutes. CLAUDISH_TIMEOUT and CLAUDISH_MD_TIMEOUT keep the LLM call itself bounded below those ceilings, so it fails open cleanly instead of being killed mid-write.

Quick kill switch: set CLAUDISH_ENABLED=0, or disable the plugin.

Reasoning models

The request sends "think": false. Models with a hidden reasoning phase otherwise spend most of their time generating reasoning tokens you never see — much slower for identical output quality on this simple task. Keep it off.


Privacy / egress

The rewriter runs entirely locally against ollama, so no conversation content leaves your machine. If you ever point CLAUDISH_OLLAMA at a remote/hosted endpoint, that context (which can include file contents from tool results) would be sent off-box — don’t do that unless you understand and accept it.


Layout

claudish-to-english/
├── .claude-plugin/
│   ├── plugin.json         # plugin manifest
│   └── marketplace.json    # so the repo can be added as a marketplace directly
├── hooks/
│   └── hooks.json          # MessageDisplay -> rewrite.sh ; PostToolUse -> rewrite-md.sh
├── rewrite.sh              # display-rewrite hook
├── rewrite-md.sh           # markdown-file rewrite hook (opt-in)
├── LICENSE
└── README.md

License

MIT — see LICENSE.