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

v0.1.10

Published

OpenCode session viewer and observability dashboard

Readme

rewind

Local viewer, analytics dashboard, and TypeScript library for inspecting OpenCode sessions.

Published on npm as opencode-rewind.

This project is not built by the OpenCode team and is not affiliated with OpenCode or Anomaly.

Why

OpenCode stores rich local session state, but the raw SQLite data is awkward to inspect directly. Rewind turns it into something easier to use for:

  • browsing sessions
  • drilling into tool calls and subagents
  • inspecting compactions, diffs, and todos
  • understanding token usage, timing, and cost over time

Usage Modes

opencode-rewind can be used in three different ways:

  1. as an OpenCode plugin that powers /rewind and /rewind-off
  2. as a standalone CLI/server you run yourself
  3. as a TypeScript library

OpenCode Plugin

opencode-rewind can also be loaded as an OpenCode plugin.

The package root is the plugin entry for OpenCode. The TypeScript library API lives at opencode-rewind/lib.

You do not need to install the package globally for the plugin workflow. Add the plugin and commands to your OpenCode config, and OpenCode will install the npm package into its plugin cache automatically.

OpenCode plugins and slash commands are configured separately. The plugin handles /rewind and /rewind-off in the command.execute.before hook, but the commands still need to be defined in your OpenCode config so they appear in the TUI.

Add it to your OpenCode config:

{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["opencode-rewind"],
  "command": {
    "rewind": {
      "description": "Open the current OpenCode session in Rewind",
      "template": "Handled locally by the Rewind plugin. No model response is needed."
    },
    "rewind-off": {
      "description": "Stop the managed Rewind server",
      "template": "Handled locally by the Rewind plugin. No model response is needed."
    }
  }
}

What the plugin does:

  • /rewind ensures the Rewind server is running, then opens the current session in your browser
  • /rewind-off stops the managed background Rewind server

The plugin tries to neutralize the command body before the normal model flow, but OpenCode may still record a lightweight command message in the transcript.

The npm plugin package includes the Rewind CLI internally, so /rewind and /rewind-off do not require a separate global install.

Optional plugin config:

{
  "plugin": [["opencode-rewind", {
    "baseUrl": "http://127.0.0.1:3838",
    "rewindCommand": "rewind",
    "stopCommand": "rewind-off"
  }]]
}

cliCommand is only needed for advanced overrides. By default the plugin runs the bundled CLI that ships inside the npm package.

Local Plugin Iteration

To test plugin changes without publishing to npm, you can sync your local build into OpenCode's cached plugin install:

pnpm sync:opencode-cache

That rebuilds the package and copies these files into OpenCode's cached package directory:

  • dist/
  • bin/
  • .next/
  • package.json
  • README.md

Then restart OpenCode.

You can also smoke test the cached install directly:

pnpm smoke:opencode-cache

Both scripts default to:

~/.cache/opencode/packages/opencode-rewind@latest/node_modules/opencode-rewind

Override the target with OPENCODE_REWIND_CACHE_DIR if needed.

CLI

Install globally if you want to run the Rewind web app yourself outside OpenCode:

npm install -g opencode-rewind
opencode-rewind start

Optional flags:

opencode-rewind start --port 3838 --host 127.0.0.1
opencode-rewind stop
opencode-rewind status

opencode-rewind commands:

  • opencode-rewind or opencode-rewind serve runs the app in the foreground
  • opencode-rewind start starts it in the background if it is not already running
  • opencode-rewind stop stops the managed background server
  • opencode-rewind status reports whether the server is reachable

Library

Install it in a JS/TS project if you want to consume the normalized OpenCode session API directly:

pnpm add opencode-rewind
 import { createRewind } from "opencode-rewind/lib";

const rewind = createRewind();

const sessions = await rewind.listSessions({ limit: 20 });
const session = await rewind.getSession(sessions[0].id);
const messages = await rewind.getMessages(sessions[0].id);

rewind.close();

Config

 import { createRewind } from "opencode-rewind/lib";

const rewind = createRewind({
  basePath: "/custom/path/to/opencode-data-dir",
});

basePath should point at the OpenCode data directory.

By default Rewind reads:

  • ~/.local/share/opencode/opencode.db
  • ~/.local/share/opencode/storage/session_diff/*.json

If XDG_DATA_HOME is set, Rewind uses that base directory instead of ~/.local/share.

Direct Provider

If you want the OpenCode-specific provider directly:

 import { createOpenCodeProvider } from "opencode-rewind/providers/opencode";

const provider = createOpenCodeProvider();
const sessions = await provider.listSessions();
provider.close();

API

createRewind(config?)

Returns an object with:

  • listSessions(options?)
  • getSession(sessionId)
  • getMessages(sessionId)
  • close()

listSessions(options?)

await rewind.listSessions({
  projectPath: "/Users/me/myproject",
  after: "2025-01-01T00:00:00Z",
  before: "2025-02-01T00:00:00Z",
  includeSubagents: true,
  limit: 50,
});

Subagent sessions are excluded by default. Pass includeSubagents: true to include them.

getSession(sessionId)

Returns a normalized Session with:

  • session summary fields
  • messages
  • diffs from storage/session_diff/<sessionId>.json when present
  • todos from the SQLite todo table when present

getMessages(sessionId)

Returns normalized messages only.

Data Model

The source of truth is src/types.ts. The most important shapes are:

interface SessionSummary {
  id: string;
  provider: "opencode";
  title?: string;
  slug?: string;
  createdAt: string;
  updatedAt: string;
  messageCount?: number;
  projectPath?: string;
  usage?: TokenUsage;
  cost?: number;
  totalDurationMs?: number;
  parentSessionId?: string;
  cliVersion?: string;
  codeChanges?: { additions: number; deletions: number; files: number };
  permissions?: Array<{ type: string; glob?: string; description?: string }>;
  primaryModel?: string;
  models?: string[];
  toolCallCount?: number;
  subagentCount?: number;
  compactionCount?: number;
  topTools?: Array<{ name: string; count: number }>;
}

interface Session<TRaw = unknown> extends SessionSummary {
  messages: Message<TRaw>[];
  diffs?: OpenCodeSessionDiff[];
  todos?: OpenCodeTodo[];
}

interface Message<TRaw = unknown> {
  id: string;
  role: "user" | "assistant" | "system" | "tool";
  content: MessageContent[];
  timestamp: string;
  completedAt?: string;
  durationMs?: number;
  model?: string;
  usage?: TokenUsage;
  cost?: number;
  parentId?: string;
  isCompactSummary?: boolean;
  error?: MessageError;
  stopReason?: string;
  cwd?: string;
  apiProvider?: string;
  mode?: string;
  summary?: { title?: string; diffs?: unknown[] };
  raw: TRaw;
}

type MessageContent =
  | { type: "text"; text: string; textType?: string }
  | { type: "tool_use"; toolName: string; toolCallId?: string; input: unknown; subagentSessionId?: string; durationMs?: number; title?: string }
  | { type: "tool_result"; toolCallId?: string; toolName?: string; output: string; isError?: boolean; durationMs?: number; interrupted?: boolean; status?: string }
  | { type: "thinking"; text: string; durationMs?: number; signature?: string }
  | { type: "compaction"; auto: boolean; preTokens?: number }
  | { type: "patch"; hash: string; files: string[] }

Token Usage

interface TokenUsage {
  inputTokens?: number;
  outputTokens?: number;
  reasoningTokens?: number;
  cacheReadTokens?: number;
  cacheCreationTokens?: number;
  totalTokens?: number;
  peakInputTokens?: number;
}

Every normalized message also carries a .raw field with the original OpenCode payload.

OpenCode-Specific Behavior

Subagents

OpenCode spawns subagent sessions for parallel work like exploration and research. These sessions have parentSessionId set to the parent session ID.

Compaction

Rewind surfaces compaction as:

  • a message containing { type: "compaction", auto: boolean }
  • the next assistant message marked with isCompactSummary: true
  • possible API errors on messages that failed during context pressure

Web App

Rewind also includes a Next.js web app for browsing and analyzing OpenCode sessions.

pnpm dev        # http://localhost:3838
pnpm build:app
pnpm serve      # starts the packaged standalone server in the foreground

REST API

The web app exposes these routes:

GET /api/sessions
GET /api/sessions?project=/path/to/project
GET /api/sessions?after=2025-01-01T00:00:00Z&before=2025-02-01T23:59:59.999Z
GET /api/sessions?includeSubagents=true
GET /api/sessions?limit=100

GET /api/session/:sessionId
GET /api/session/:sessionId?startMessage=10&endMessage=40

GET /api/dashboard
GET /api/dashboard?after=2025-01-01T00:00:00Z&before=2025-02-01T23:59:59.999Z

Development

pnpm install
pnpm typecheck
pnpm test
pnpm build
pnpm build:app

License

MIT