opencode-amp-like-handoff
v0.2.0
Published
Amp-like new-session handoff plugin for OpenCode
Maintainers
Readme
opencode-amp-like-handoff
Amp-like new-session handoff plugin for OpenCode.
What it does
When an AI coding session accumulates enough context that starting fresh would be more efficient, /handoff distills the relevant context into a new session — avoiding the costly "file archaeology" phase where the AI re-discovers files, decisions, and patterns from scratch.
- Registers a
/handoff <goal>command that triggers a structured context-transfer workflow - The model analyzes the current conversation, extracts context relevant to the stated goal, and identifies the most important files (targeting 8–15, up to 20 for complex work)
- Creates a new session with the handoff prompt as an editable draft — the user reviews it, edits if needed, and sends when ready
- Files are referenced as
@filemarkers in the draft (e.g.,@src/plugin.ts); their contents are auto-injected when the user sends the message - File contents match OpenCode's Read tool format (5-digit zero-padded line numbers,
<file>tags), so the AI treats them identically to files it read itself - Binary files are detected by extension and byte analysis, and silently skipped
- Records the source session ID so the new session knows where it came from
- Provides
read_sessionto pull conversation transcript from the source session on demand - Logs all operations via
app.logfor observability
Usage
/handoff <your next goal>Example:
/handoff Refactor the auth module to use JWT instead of sessionsWhen invoked, the model:
- Reads the current conversation to infer task status
- Extracts decisions, constraints, user preferences, technical patterns, blockers, and exact next steps relevant to the stated goal
- Identifies 8–15 relevant files (source files, dependencies, tests, configs)
- Calls
handoff_sessionwith a focused continuation prompt and file list - A new session opens with the handoff as an editable draft — review it, make changes, and press Enter to send
- When the message is sent, the
chat.messagehook automatically parses@filereferences, reads file contents from disk, and injects them as synthetic parts matching the Read tool format
In the new session, read_session is available to pull message history from the source session on demand if more detail is needed.
Tools
handoff_session
Creates a new session with the handoff prompt as an editable draft. File contents are auto-loaded when the user sends the message.
| Argument | Type | Required | Description |
|---|---|---|---|
| prompt | string | yes | The generated handoff prompt with context and goals. Must be non-empty. |
| files | string[] | no | File paths to load into the new session context (8–15 recommended). Leading @ is stripped automatically. Duplicates and blank entries are ignored. |
Success response:
{
ok: true,
sourceSessionId: string, // ID of the session that initiated the handoff
files: string[], // deduplicated list of file paths
message: string // confirmation message
}Error response:
{ ok: false, error: string }Errors are returned (not thrown) for: empty prompt, or failure to create the draft session.
read_session
Reads conversation transcript from a previous session. Returns a formatted markdown transcript with ## User and ## Assistant sections.
| Argument | Type | Required | Description |
|---|---|---|---|
| sessionId | string | yes | The full session ID (e.g., sess_01jxyz...). Must be non-empty. |
| limit | number | no | Maximum number of messages to read. Clamped to 1–500. Defaults to 100. |
Success response:
{
ok: true,
sessionId: string,
count: number,
transcript: string // formatted markdown transcript
}Error response:
{ ok: false, error: string }How it works
Editable draft workflow
Unlike a direct session.create() + session.prompt() approach that auto-injects context without user review, this plugin uses an editable draft workflow:
handoff_sessioncallstui.executeCommand({ command: "session_new" })to create a new session and navigate to it- After a short delay (200ms for the TUI to mount), it calls
tui.appendPrompt()to populate the prompt input with the handoff text - The user sees the full handoff prompt as editable text — they can modify, remove, or add context before sending
Automatic file injection
When the user sends the handoff message, the chat.message hook:
- Detects messages containing "Continuing work from session" (the marker placed by the handoff tool)
- Parses
@filereferences using theFILE_REGEXpattern - Reads each file from disk, skipping binary files and unreadable paths
- Formats content with 5-digit zero-padded line numbers and
<file>tags, matching OpenCode's Read tool output - Injects synthetic text parts into the session via
session.prompt({ noReply: true })— the AI sees them as if it called the Read tool itself
Each session is tracked in a processedSessions set to prevent duplicate injection. The set is cleaned up via the event hook when sessions are deleted.
File format
Files are formatted to match OpenCode's Read tool output:
Called the Read tool with the following input: {"filePath": "/abs/path/to/file.ts"}
<file>
00001| import { foo } from "./bar"
00002|
00003| export function hello() {
00004| return "world"
00005| }
00006|
(End of file - total 6 lines)
</file>- Lines are zero-padded to 5 digits with a
|separator - Lines longer than 2000 characters are truncated
- Files longer than 2000 lines show only the first 2000
Project structure
src/
plugin.ts — Main plugin: hooks, handoff template, session lifecycle
tools.ts — HandoffSession and ReadSession tool definitions
files.ts — Binary detection, Read tool format, @file reference parsingInstall locally
Place this plugin in a plugins directory supported by OpenCode:
.opencode/plugins/opencode-amp-like-handoff/— project-level (checked into the repo)~/.config/opencode/plugins/opencode-amp-like-handoff/— user-level (applies to all projects)
Example directory tree:
.opencode/
plugins/
opencode-amp-like-handoff/
package.json
tsconfig.json
src/
plugin.ts
tools.ts
files.tsOpenCode picks up the plugin automatically on startup. If the plugin directory contains a package.json, OpenCode runs bun install to resolve dependencies before loading.
Development
# Install dependencies
bun install
# Type-check without emitting output
bun run typecheckTypeScript configuration: strict mode, bundler module resolution, ESNext target. The plugin runs directly as TypeScript via Bun — no build step required.
License
MIT
