Back to Blog

From Amp's Blog to My First Plugin

·4 min read
AIOpenCodePlugins

I read Amp's blog post about replacing compaction with handoff. The idea seemed cool and I've been meaning to learn how OpenCode plugins work anyway—seemed like a good excuse to try.

The result: a session handoff plugin for OpenCode. New session, context carried over.

Is it as good as Amp's? No. Does it work? Mostly. But I'll keep working on it.


Learning the Plugin System

OpenCode's plugin SDK is surprisingly simple. A plugin is just a function that returns tools:

const HandoffPlugin: Plugin = async (ctx) => {
  return {
    tool: {
      session_handoff: {
        /* ... */
      },
      read_session: {
        /* ... */
      },
    },
  };
};

The ctx object gives you a client for OpenCode's API. Session management, TUI controls, the works. I spent an evening just poking at what was available.

The docs were sparse, so I read the SDK source. session.create, session.promptAsync, session.messages, session.todo. Everything I needed was there.


What I Built

Say handoff or handoff <goal> and:

  1. The AI summarizes the current state (1-3 sentences)
  2. Plugin grabs your todos, agent config, model settings
  3. If you said handoff implement the tests, "implement the tests" becomes the goal
  4. Creates a new session titled "Handoff: [previous title]"
  5. Sends the handoff prompt to the new session and opens the picker

The new session knows what you were doing, what you want to do next, which model you were using, and what's left on your todo list.


The Handoff Prompt

I wanted it minimal. Earlier versions dumped too much context and ate into the fresh window.

Now it looks like this:

## Session Handoff

Building auth flow for the user dashboard. Login works,
session persistence implemented, currently fixing token refresh.

**Goal:** implement the logout endpoint

**Todos:** 3/5 done
- In progress: Fix token refresh race condition
- Pending: Add logout endpoint, Write integration tests

**Files:** src/auth/session.ts, src/api/routes.ts

**Next:** 1. Add mutex for token refresh 2. Test concurrent requests

---
Previous: `ses_abc123` · Use `read_session` if you need more context.

~100-200 tokens. The goal tells the new session exactly what you want to work on. If the AI needs more detail later, there's a read_session tool that pulls the last 20 messages from the previous session.


What I Learned Along the Way

Model and agent config isn't where you'd expect. I assumed there'd be a session config endpoint. Nope. The model (providerID, modelID) and agent (mode) live on individual assistant messages. You read the last message to find out what was active. Not obvious from the SDK types, but it works.

The TUI API is limited. I wanted the plugin to switch to the new session automatically. OpenCode has tui.openSessions (opens the picker) but no way to select a session programmatically. The endpoint exists in the codebase but returns connection refused. So you have to manually pick the handoff session from the list.


Installation

Add to ~/.config/opencode/opencode.json:

{
  "plugin": ["opencode-session-handoff"]
}

Restart OpenCode. Say handoff for a simple handoff, or handoff fix the failing tests to set a goal for the next session. The plugin auto-updates when new versions are released.


What's Next

Auto-handoff is the next likely improvement. Update: The goal parameter is now live! Say handoff <goal> and the plugin passes your intent to the new session.

Next up might be auto-handoff when context gets full. The plugin already has a config placeholder:

{
  "auto_handoff_threshold": 80
}

When context usage hits 80%, trigger handoff automatically. PR welcome if you beat me to it.


GitHub · npm