@lifangjin/opencode-session-title-pluginFilter irrelevant system-prompt injections from opencode session title generation to save tokens
0
735
35 in 7 days
36.3
Multi-signal model
1 month ago
2026-07-21
Install and configure
opencode.jsonWrites to this project's opencode.json — applies to this repository only.
opencode.json
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["@lifangjin/opencode-session-title-plugin@0.0.6"]
}Writes to ~/.config/opencode/opencode.json — applies to every project.
~/.config/opencode/opencode.json
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["@lifangjin/opencode-session-title-plugin@0.0.6"]
}If you want to modify the plugin locally, install it into the project and reference the local path.
shell
pnpm add -D @lifangjin/opencode-session-title-pluginopencode loads npm dependencies through its embedded runtime on startup and caches them locally — no manual global install needed.
English | 简体中文
Filter irrelevant system-prompt injections from opencode session title generation to save tokens.
Why
Every new opencode session triggers a background LLM call that generates a short title. The call uses opencode's built-in title agent, whose prompt is a fixed ~2KB string ending in </examples>:
You are a title generator. You output ONLY a thread title. Nothing else.
...
Other plugins (@cortexkit/opencode-magic-context, oh-my-opencode-slim, project AGENTS.md, skill guidance, MCP instructions, ...) hook experimental.chat.system.transform and append project memory, session history, skill listings, and other context to every LLM call - including title generation. That context is useless for producing a 50-character title and wastes thousands of tokens on every new session.
This plugin detects title-generation calls and strips the system prompt back to just PROMPT_TITLE, so the small model only sees what it actually needs.
How it works
The plugin hooks experimental.chat.system.transform:
Detection: When any system string contains the full sentence
"You are a title generator. You output ONLY a thread title. Nothing else."(the first line of opencode'sPROMPT_TITLE), the hook identifies this as a title-generation call. The full sentence is required — shorter markers like"You are a title generator"match cross-references in other agents' system prompts and cause false positives.Extraction: The hook extracts the pure
PROMPT_TITLEfrom the matched system entry — everything fromTITLE_MARKERto</examples>(inclusive). Content prepended by other plugins (orchestrator prompts, project memory, etc.) is discarded.Mutation: The system array is replaced in-place with
[pureTitle](mutation-mode hook).Toast: Token savings are calculated immediately (
originalTokens - filteredTokens) and a TUI toast is shown instantly — no polling, no waiting for the title to be generated.
Detection is content-based because experimental.chat.system.transform receives { sessionID, model } (no agent name). The title agent's prompt is a constant in opencode core (packages/core/src/plugin/agent.ts), so the marker is stable.
Note:
experimental.chat.messages.transformis not used. That hook only fires inSessionPrompt.runandSessionCompaction.process, not inLLM.run/ensureTitle— so it never executes for title-generation calls.
Install
As a published package
// ~/.config/opencode/opencode.json
{
"plugin": [
"@lifangjin/opencode-session-title-plugin@latest"
]
}
With options
{
"plugin": [
["@lifangjin/opencode-session-title-plugin@latest", { "debug": true }]
]
}
From source (local dev)
{
"plugin": [
["/path/to/opencode-session-title-plugin", { "debug": true }]
]
}
Build: bun install && bun run build
Options
| Option | Type | Default | Description |
|---|---|---|---|
debug |
boolean |
false |
Write detection/filtering details to ~/.local/share/opencode/log/session-title-filter.log and stderr. Also dumps full system entries to timestamped .txt files (max 10 retained). |
enabled |
boolean |
true |
Master switch. Set false to detect-only (no mutation). |
notify |
boolean |
true |
Show a TUI toast immediately after calculating token savings. |
Toast
When notify is on (default), the plugin shows a toast immediately after filtering — no polling, no delay:
Session title filter
Title call saved 3018 tokens
Token savings are calculated with gpt-tokenizer: the hook's model field selects the encoding (cl100k_base for GPT-4/3.5, o200k_base for GPT-4o/o1/o3), giving exact counts for OpenAI models and a close approximation (±5%) for other providers. Duplicate toasts from LLM retries are suppressed for 60 seconds per session.
Using a cheaper model for title generation
This plugin only filters the system prompt. Which model opencode calls for title generation is controlled by opencode itself.
opencode's title-agent model priority (source: SessionPrompt.ensureTitle in packages/opencode/src/session/prompt.ts):
agent.title.model- set on the built-intitleagent via config (highest priority)small_model- global lightweight model config- main session model - the fallback (most expensive)
To pin a cheap model for title generation only, add it to opencode.json:
{
"agent": {
"title": {
"model": "aimatespace/sensenova-deepseek-v4-flash"
}
}
}
This pairs naturally with this plugin: the cheap model sees only PROMPT_TITLE (plugin strips the rest), so token cost per title drops to near zero.
Verification
Start a new opencode session. With debug: true, check the log file at ~/.local/share/opencode/log/session-title-filter.log:
[session-title-filter] plugin v0.0.4 loaded, enabled: true notify: true
[session-title-filter] system[0]: len=16973 head="..." tail="...</examples>\n"
[session-title-filter] title call: model: sensenova-deepseek-v4-flash entries: 1 titleIndex: 0 originalText.len: 16973 originalTokens: 3521
[session-title-filter] filtered: pureTitle.len: 2095 pureTitle.head: "You are a title generator. You output ONLY..." filteredTokens: 503 savedTokens: 3018
[session-title-filter] notify: toast shown, savedTokens: 3018
filteredTokens should be around 500 (the size of PROMPT_TITLE). If it is much larger, other plugins are still injecting into the same system string — open an issue with the log output.
Compatibility
- opencode with
@opencode-ai/plugin>= 1.4.0 - Hook used:
experimental.chat.system.transformonly - The detection marker (
"You are a title generator. You output ONLY a thread title. Nothing else.") is tied to opencode's built-inPROMPT_TITLE. If opencode changes the title-agent prompt, updateTITLE_MARKERinsrc/index.ts.
License
MIT