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

@toninho09/opencode-continue

v0.2.0

Published

opencode plugin: /continue resumes the interrupted (ESC-aborted) run without adding a new message

Readme

@toninho09/opencode-continue

An opencode plugin that adds a /continue command: it resumes an interrupted run (aborted with ESC) without adding a new message to the session and without the model ever noticing the interruption.

Useful when you interrupt the agent mid-task and want it to redo the aborted response as if the interruption had never happened — no orphaned partial text, no "[Tool execution was interrupted]" in the context, no "continuing from where I left off" meta-commentary, and no polluting the history with messages like "continue" or "go on".

Requirements

  • A recent opencode version (plugin API >= 0.6.0).

Installation

Add the plugin to your opencode.json (project or global):

{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["@toninho09/opencode-continue"]
}

Or install from this repository (local checkout):

{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["/path/to/opencode-continue/src/index.ts"]
}

Restart opencode after saving the config. That's it — the plugin self-registers (the /continue command appears automatically, no need to create a command file).

Usage

/continue
  • A run was started and interrupted with ESC → the plugin removes the interrupted tail from the session (the aborted assistant message, with its partial text and interrupted tools) and the agent regenerates the full response from the last completed step (or from the original prompt) — for the model and for the transcript, it's as if the interruption never existed. File edits already made are not undone.
  • Session busy → warns and does nothing.
  • Last run already completed → warns and does nothing (idempotent).
  • Session with no user prompt → warns and does nothing.

How it works

  1. A config hook registers the /continue command.
  2. When /continue runs, a command.execute.before hook validates the session (idle, has a user prompt, last run unfinished), identifies the interrupted tail after the last real user prompt — assistant messages with an error (the aborted response) and the plugin's own old neutral messages — and deletes them from the session via DELETE /session/:id/message/:messageID (an endpoint that does NOT revert file changes). Completed steps of the turn (tool calls with results) are preserved: the model naturally resumes after them. If deletion fails (server without the endpoint), the removed IDs are hidden from the context via the experimental.chat.messages.transform hook.
  3. Finally, the hook replaces the command's own parts, in place, with a single empty, ignored text part. The command creates that message (effectively invisible) and runs the agent loop. Since opencode filters ignored/empty parts out of the provider conversion (MessageV2.toModelMessagesEffect), the model receives the clean history — ending at the last completed step or at the original prompt — and regenerates the response from scratch, with no trace of the interruption.

The original user message is never rewritten nor re-sent — neither in the UI (its time.created is preserved, nothing jumps around) nor to the model (the text does not go into the context again).

The mechanism mirrors opencode's own loop exit condition (SessionPrompt.runLoop): a run without a valid finish = work pending; a clean finish = nothing to continue.

Known limitations

  • No-op cases: busy session, already-completed run, or a session with no prompt cancel the command with a throw — the TUI shows the generic "failed to send command" toast in those cases (alongside the plugin's explanatory toast). On the normal path (an interrupted run) there is no error at all.
  • Continuation model: the resume uses the session's current model/agent (not necessarily the ones from the aborted run).
  • Tool re-execution: the response is regenerated from the last completed step — tools from the aborted step may run again (file edits remain; the model sees the current state of the files).
  • Name collision: on opencode versions where /continue or /resume resolve to the session picker before custom commands, register one of the alternate names the plugin also intercepts: retry, go or again (e.g. .opencode/command/retry.md with any template). The hook intercepts those names automatically.
  • The "real" solution would be a native /session/:id/continue endpoint exposing SessionPrompt.loop() — this plugin is the 100% plugin-API way until then.

Development

bun install
bun run typecheck

License

MIT © toninho09