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-ember

v0.4.1

Published

Keep an LLM prompt cache warm across breaks, guard cold rewrites before you pay for them, and score what a break actually cost. An opencode plugin.

Readme

opencode-ember

CI

Keep an LLM prompt cache warm across a break, guard a cold rewrite before you pay for it, and see exactly what the break cost.

A port of cache-tax to opencode. One self-contained plugin file, no runtime dependencies.

Why "ember": a banked fire you keep smoldering while you are away.

What it does

  • The cache stays warm by default. Every top-level session (not subagent sessions) stays armed while opencode runs; after the cache tier has almost lapsed, the plugin sends one request over a fork of the session. The fork shares the session's model, agent, tools and system prompt, so its prefix is byte-identical and only appends: the provider answers from cache and the TTL refreshes. No heartbeat messages ever enter the real conversation. /keepwarm off stops it for the session and turns the default off.
  • /ember guard warn (default) shows the price and sends anyway. When the TTL has lapsed and the context is large, a graceful warning is shown while the message sends. /ember guard refuse hard blocks cold sends and shows an informative error in the turn, preventing accidental rewrites until you switch to warn or /clear.
  • /ember keeps score. Warm or cold, context size, cold-rewrite price, the break-even (how many pings cost one cold write, and the idle that covers), keepwarm state, guard mode, and this session's cold writes.
  • ember gain reports history. Every warm heartbeat and every paid cold write is bucketed per day (kept warm for up to 90 days), and the ember gain terminal binary reports total heartbeats, tokens kept warm, the kept-warm value against ping spend and realized cold writes, net savings, a warming-yield meter, and a per-day impact table — in the spirit of rtk gain. ember discover is an alias; ember gain --json dumps the raw buckets.

Requirements

  • opencode (server plugins, chat.message + command.execute.before hooks; tested on 1.18.x).
  • A provider with prefix caching. Anthropic is the best-supported; pricing tables for Fable/Opus/Sonnet/Haiku are built in.

Install

From this repo (recommended)

git clone https://github.com/ozandogrultan/opencode-ember.git
cd opencode-ember
./install.sh

Then restart opencode — plugins are loaded at startup only.

install.sh also links the report binary as ~/.local/bin/ember (set EMBER_BIN_DIR to choose another directory), so ember gain works from any shell. It requires bun on PATH; an alternative is npm install -g . from the repo, or copy gain.ts somewhere on your PATH. /ember gain inside opencode tells you to use the binary instead.

install.sh asks opencode for its own config directory (opencode debug paths) and copies ember.ts into <config>/plugins/, backing up any existing file.

Manually

Copy ember.ts to one of:

  • ~/.config/opencode/plugins/ember.ts — all projects (global)
  • <project>/.opencode/plugins/ember.ts — one project

From npm

{ "plugin": ["opencode-ember"] }

in opencode.json, then restart opencode.

Usage

/keepwarm [6h|90m] [every 2m] [ttl 1h] | always | status | off
/ember [guard warn|refuse]
ember gain | discover [--json]     # the report, from any shell

| command | effect | | --- | --- | | /keepwarm | refresh always-on warming (or arm six hours if the default is off) | | /keepwarm 90m | a window of your own (2h30m, 6h, …) | | /keepwarm always | keep this and future sessions armed until closed (already the default) | | /keepwarm 6h every 2m | override the ping period (floor 1m) | | /keepwarm 6h ttl 1h | assume the 1-hour cache tier | | /keepwarm status | the status line | | /keepwarm off | stop, forget the window, turn the default off | | /ember | the card | | /ember guard warn | show the price and send (default) | | /ember guard refuse | hard block cold sends | | ember gain | terminal report over collected history (alias ember discover) |

Warming belongs to each session. By default it renews as long as opencode is running; explicitly timed windows end after their duration. A second session gets its own timer, and a resumed session restores its setting. A session resumed after the cache tier already expired cannot be rescued retroactively: its first turn is cold by definition, and warming resumes from that point. Run /keepwarm off to disable the default and warm only on request.

The 5-minute tier (read this)

opencode marks cache_control without a ttl, i.e. the 5-minute tier, so pings land at ~4 minutes, not the original mod's 50. If your provider actually holds an hour, run /keepwarm 6h ttl 1h (or set EMBER_TTL_SECONDS=3600) for a ~54-minute cadence.

Economically that matters: on a 200k-token context a cache read is ~$0.05 and a cold write ~$4, so ~80 pings cost one cold write. Warm a one-hour break and you win; warm a whole working day on the 5-minute tier and you are near break-even.

Always-on warming can keep paying for cache reads beyond six hours while the session remains open. Turn it off with /keepwarm off or use an explicit duration if you would rather bound the cost per session.

It will not invalidate your cache

  • Pings reuse the session's exact model, agent, tools and system prompt and send a constant one-line prompt. They only append.
  • After every ping the plugin checks the usage: if it wrote at least a tenth of what it read, it concludes the cache was already gone and stops itself rather than hammering a cold cache. A ping that reports no cache numbers at all is treated as inconclusive instead: it retries once and stops only after two consecutive zero-activity readbacks, so one flaky usage report cannot kill the heartbeat. A transient ping error also retries once before stopping.
  • Pings only run while the last request is still inside the cache tier. A session resumed after the tier expired (process restart, sleep, long break) waits for your next turn instead of cold-rewriting the fork itself.
  • An explicitly timed window expires without editing or clearing the session.

Configuration

| env var | default | meaning | | --- | --- | --- | | EMBER_TTL_SECONDS | 300 | assumed cache tier | | EMBER_MIN_CONTEXT | 50000 | cold-guard context floor, tokens | | EMBER_MIN_PING_SECONDS | 60 | ping floor |

Prices and the reporting caveats (read this too)

Dollar figures come from a small built-in table in ember.ts (PRICES: cache read, cache write and output rates per model family). Two consequences:

  • Every figure is an estimate. Prices are hard-coded list rates for the Anthropic/OpenAI families the plugin knows; they do not follow your provider, plan, negotiated rates, or prompt-fee changes. Treat every dollar value in /ember and /ember gain as an approximation, not an invoice.
  • Unpriced models read $0.00. Models without a matching row — e.g. custom OpenAI-compatible ids like gpt-5.5 or provider relays — report no cost, so the kept-warm value, ping spend, cold-write cost, net savings and the warming yield meter all run understated (or read $0.00) for them. Raw counters — heartbeat counts, tokens kept warm, idle time held warm, cold-write counts — stay accurate regardless. Add a row to PRICES in ember.ts if you want dollar accuracy for such a model.

State lives in ~/.local/share/opencode/ember.json and is stamped with a version. Multiple opencode processes (one per workspace/cmux session) share the file: every write re-reads it and merges, so a process writing its own session's window never drops sessions armed elsewhere. Heartbeat and cold-write history is bucketed per day and trimmed to the last 90 days for /ember gain. A state file written before warming was on by default is upgraded silently: its always: false was the old default rather than a choice, so it is ignored once and the new default applies. Delete the file to reset.

Testing

Free (no model call):

opencode debug config | grep -A2 -E '"keepwarm"|"ember"'   # loaded?
/keepwarm status     # "keepwarm off"
/keepwarm 6h         # arms
/ember               # card
/ember guard warn    # switch guard
ember gain           # the report (CLI)
/keepwarm off

Cold guard, for about one small call — launch with a 5-second pseudo-TTL and a 1-token floor, send a message, wait 6s, send another (blocked):

EMBER_TTL_SECONDS=5 EMBER_MIN_CONTEXT=1 opencode

Prove a ping shares the cache (one cache read) — in a warm session with real context:

/keepwarm 1h every 1m

Wait a minute, then run /ember. Its last-ping cache read should be close to your context size: that is the proof the fork hit the main cache. Successful pings are silent; failures and stops still show a toast. If the ping reports no cache activity, the provider may not cache this prefix or report cache usage, so keepwarm stops rather than paying for unverified pings. Stop notices appear briefly in the TUI (five seconds); /keepwarm status or /ember shows the reason afterward.

How it works

chat.message + chat.params (cold guard), event (token/price tracking, timers) and command.execute.before (the two commands, aborted before any model call). Pings go through session.fork → session.prompt → session.delete.

Credits

Ported from karanb192/claude-code-mods → cache-tax. The design, the price arithmetic and the safety rules are theirs; this is the opencode translation.

Contributing

See CONTRIBUTING.md for the check suite and commit conventions, AGENTS.md for the design rules, and CHANGELOG.md for what changed.

License

MIT © Ozan Dogrultan