npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

opencode-agentish-to-english

v1.0.0

Published

opencode plugin that rewrites verbose agent output into plain, direct, fluff-free English

Readme

agentish-to-english

Rewrites verbose agent answers into plain English — for you, not the model.

What it is

An opencode plugin that rewrites every assistant message into plain, direct, fluff-free English. After each answer, a fast model produces a terse rewrite that is appended below the original as a labeled block: 💬 In plain English: …. The original text is never touched, and the block is model-invisible — it renders in your TUI but never enters the model's context, so it costs you nothing at generation time.

The problem

AI agents write like corporate memos: preambles, outro summaries, filler, hedging, clichés ("delve", "leverage", "it's important to note", "not just X, but Y"). You read for information but pay for word count. Editing that out by hand is tedious; telling the model to "be concise" in a prompt is ignored.

How it looks

You: Why does the build fail?

Agent: I've taken a look into this, and it's important to note that the build is
       currently failing on src/config.ts line 42 due to a TypeScript error with
       the code TS2307 — ultimately, this will need to be fixed before we can
       move forward with the release.

💬 In plain English:
Build fails: src/config.ts:42 → TS2307. Fix before release.

Numbers, code, paths, warnings, and negation words survive verbatim. The rest gets compressed — usually to well under half the original length.

Features

  • Rewrites every assistant message. Completed text is buffered and rewritten in order on the next session.idle, one rewrite per message.
  • Model-invisible blocks. The rewrite is appended as an ignored text part in a separate child session — it renders for you but never enters future model context or compaction.
  • Lossless compression. Code, file paths, URLs, numbers, error codes, warnings, and negation words (not/never/no/only/except) are preserved verbatim; results are capped at 60% of the original word count.
  • Fail-open. Any failure (model down, bad model ID, timeout, provider error) is a silent no-op — your original answer always stands.
  • No extra infra. No API keys, no ollama stack, no 17 GB model download. The rewrite reuses the providers you already configured.
  • Toggles mid-session. A flag file pauses rewriting; AGENTISH_ENABLED=0 makes the plugin inert at launch.
  • Typing-friendly. A debounce window cancels rewrites that are no longer useful; a new user message never kills an in-flight rewrite.
  • No telemetry. Nothing leaves your session except the rewrite itself.

Install

Requires opencode ≥ 1.18.18.

Option A — via npm. Add the plugin to your opencode.json:

{
  "plugin": ["opencode-agentish-to-english"]
}

Option B — plugin directory. Drop src/plugin.ts from the published package into ~/.config/opencode/plugins/ (global) or .opencode/plugins/ (project).

Either way, restart opencode — the rewrite block appears under each assistant message.

Configuration

All configuration is via AGENTISH_* environment variables, set in your shell or in opencode.json's env block:

{
  "plugin": ["opencode-agentish-to-english"],
  "env": {
    "AGENTISH_MODEL": "openai/gpt-4o-mini",
    "AGENTISH_LABEL": "TL;DR:"
  }
}

| Variable | Default | Description | |---|---|---| | AGENTISH_ENABLED | 1 | Kill switch, read at launch. 0 makes the plugin inert. | | AGENTISH_MODEL | (unset) | Rewrite model override, format provider/model, e.g. openai/gpt-4o-mini. | | AGENTISH_LABEL | 💬 In plain English: | Label shown above each rewrite block. | | AGENTISH_OFF_FILE | ~/.config/opencode/agentish-off | Flag-file path. When the file exists, rewriting is paused (checked on every message). | | AGENTISH_NOTICE | 1 | One toast per session on the first skipped rewrite. 0 silences toasts. | | AGENTISH_DEBUG | 0 | Structured debug log via client.app.log (service agentish-to-english). | | AGENTISH_TIMEOUT | 300 | Rewrite timeout in seconds. On timeout the child rewrite is aborted, the child session is deleted, and the original is kept. | | AGENTISH_REASONING_EFFORT | medium | Reasoning-effort variant sent to the rewrite model on the child prompt. Empty ("") sends nothing. Only applies to models that expose a matching variant; unknown values are ignored by opencode. | | AGENTISH_MIN_CHARS | 40 | Skip rewriting messages shorter than this many characters. Set 0 to rewrite everything. | | AGENTISH_DEBOUNCE | 1500 | Milliseconds to wait after an assistant message completes before starting the rewrite. A new user message within this window cancels the pending rewrite. 0 rewrites immediately. |

Model selection chain

The rewrite model is resolved in this order:

  1. AGENTISH_MODEL (explicit override)
  2. config small_model
  3. config model
  4. the effective per-agent model (agent.<name>.model, agent name from the last user message, default build)
  5. none resolved → the message is kept as-is and one session toast explains that no rewriter model was configured.

Recommended: for a reasoning model like opencode-go/deepseek-v4-flash, set AGENTISH_MODEL=opencode-go/deepseek-v4-flash yourself. Its default thinking tier can burn seconds before emitting text; the plugin's AGENTISH_REASONING_EFFORT (default medium) requests the medium-effort tier so rewrites stay fast and compress hard instead of timing out.

How it works

  1. message.part.updated events accumulate text deltas per message (bounded buffer, cleaned up after completion).
  2. When an assistant message completes, it is enqueued for rewriting.
  3. On the next session.idle the pending queue drains one message at a time. For each message the plugin creates a separate child session (parentID = the current session), prompts it with the rewrite style rules plus the original text, waits for the reply (same AGENTISH_TIMEOUT guard), and deletes the child session — always, even on timeout or error.
  4. Only the result is appended to the parent session — a single ignored: true text part labeled 💬 In plain English:.
  5. The block is model-invisible: ignored: true parts are excluded from model-context assembly and compaction, and child-session messages are never pulled into the parent's context. The TUI renders ignored text parts normally, so you still see the rewrite under each answer.

Rewrites are lossless by construction: negations, numbers, code, paths, URLs, error codes, and warnings survive verbatim; the result is capped at 60% of the original word count.

Roadmap & known limits

  • v2 — markdown-file rewriting: rewrite tool output written to files, not just chat messages.
  • v2 — replace mode: true in-place replacement of the original block via an upstream part-edit API (no such endpoint exists in opencode's SDK today).
  • v2 — style dial: caveman / light / ultra voices.
  • Known limit: micro-messages under AGENTISH_MIN_CHARS (default 40) are skipped. Set AGENTISH_MIN_CHARS=0 to restore rewrite-everything.
  • Known limit: the rewrite is serialized per session.idle — rapid-fire turns delay later rewrites behind earlier ones.
  • Known limit: the block renders as a user-styled message (that's what makes it model-invisible); a future part-edit API could make it a true assistant-message edit.

Troubleshooting

  • No rewrite appears. Check AGENTISH_DEBUG=1 and look at the structured logs (service agentish-to-english). The most common cause is no resolved rewrite model — see the model selection chain above.
  • Want it to stop right now? touch ~/.config/opencode/agentish-off pauses rewriting on the next message; rm ~/.config/opencode/agentish-off resumes. Path is overridable with AGENTISH_OFF_FILE.
  • Want it dead at launch? Set AGENTISH_ENABLED=0.
  • Model not found toast. The resolved model ID doesn't exist on your provider. Set AGENTISH_MODEL to a valid provider/model, or fix your small_model. The session keeps working either way.

Uninstall

  1. Remove the plugin entry from opencode.json (or delete the file from ~/.config/opencode/plugins/).
  2. Restart opencode. No behavior remains.

Development

bun install         # install dev deps
bun test            # vitest unit tests (128 tests)
bun test --coverage # coverage report
bunx tsc --noEmit   # typecheck

Integration acceptance (spec AC 1–8) runs headless against a live provider:

bun run tests/acceptance/drive-acceptance.ts

This starts opencode serve on a scratch port, drives real sessions, and asserts the acceptance criteria on server-side session state. It needs a working provider/model — it uses your configured opencode auth. Evidence is written under tests/fixtures/acceptance/.

License

MIT