opencode-lifeline-plugin
v0.2.1
Published
OpenCode plugin that lets a smaller model phone-a-friend (stronger advisor model) when stuck
Readme
OpenCode Lifeline Plugin
An OpenCode plugin that lets a smaller/local model phone-a-friend (consult a stronger advisor model) when it gets stuck in an optimization or debugging loop. Hybrid stuck detection combines explicit experiment tracking via log_experiment with implicit heuristics (consecutive tool errors, no-progress plateau). Supports nudge mode (suggest advisor call) or ask mode (auto-call advisor).
Features
- Hybrid stuck detection: Explicit tracking via
log_experimenttool + implicit heuristics - Two action modes:
nudge(default): Injects a message suggesting the agent callphone_a_friendask: Automatically calls the advisor and injects the response
- Flexible advisor configuration:
- OpenCode-native: use any provider/model from your OpenCode registry
- External API: use any OpenAI-compatible API directly
- Session-scoped state: Tracking resets per session; no persistence across sessions
- Rate limiting: Configurable minimum runs between calls and max calls per session
- Compaction-aware context: Preserves bounded Lifeline state during OpenCode session compaction
Installation
OpenCode plugins are loaded from .opencode/plugins/<name>/ directories (project-level or global).
1. Install OpenCode
# macOS / Linux
brew install opencode-ai
# Or via npm/pnpm/bun
npm install -g opencode-ai
# Verify
opencode --version2. Create plugin directory
mkdir -p .opencode/plugins/opencode-lifeline3. Copy plugin files
# Project-level (recommended for per-project config)
cp -r src/* .opencode/plugins/opencode-lifeline/
# Or globally
cp -r src/* ~/.config/opencode/plugins/opencode-lifeline/For development, use a symlink so changes reload on restart:
ln -s $(pwd)/src ~/.config/opencode/plugins/opencode-lifeline4. Configure the plugin
Create lifeline.json in one of the following locations (first found wins):
.opencode/lifeline.json— project-level~/.config/opencode/lifeline.json— global (XDG)~/.opencode/lifeline.json— global (legacy)
{
"auto": true,
"action": "nudge",
"minRunsBetweenCalls": 5,
"triggerAfterConsecutiveFailures": 3,
"triggerAfterPlateauRuns": 6,
"maxCallsPerSession": 10,
"advisor": {
"provider": "anthropic",
"model": "claude-sonnet-4-20250514",
"maxTokens": 4096,
"temperature": 0.7
},
"implicitDetection": true,
"includeContext": true
}See lifeline.json.example for the full schema.
5. Restart OpenCode
OpenCode loads plugins at startup. Restart to pick up the new plugin.
Configuration
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| auto | boolean | true | Enable automatic stuck detection |
| action | "nudge" \| "ask" | "nudge" | nudge = suggest phone_a_friend; ask = auto-call advisor |
| minRunsBetweenCalls | number | 5 | Minimum turns between advisor calls |
| triggerAfterConsecutiveFailures | number | 3 | Trigger after N consecutive failures |
| triggerAfterPlateauRuns | number | 6 | Trigger after N runs without improvement |
| maxCallsPerSession | number | 10 | Max advisor calls per session |
| advisor.provider | string | — | OpenCode provider ID (e.g., anthropic, openai) |
| advisor.model | string | — | Model ID (e.g., claude-sonnet-4-20250514) |
| advisor.maxTokens | number | 4096 | Max tokens for advisor response |
| advisor.temperature | number | 0.7 | Temperature for advisor generation |
| advisor.apiKey | string | — | API key for external advisor calls |
| advisor.baseUrl | string | — | Base URL for external advisor (OpenAI-compatible) |
| implicitDetection | boolean | true | Enable implicit stuck detection |
| includeContext | boolean | true | Include session context in advisor prompts |
Environment variables
Advisor options can be overridden via environment variables:
export LIFELINE_ADVISOR_PROVIDER=openai
export LIFELINE_ADVISOR_MODEL=gpt-5
export LIFELINE_ADVISOR_API_KEY=sk-...
export LIFELINE_ADVISOR_BASE_URL=https://api.openai.com/v1
export LIFELINE_ADVISOR_MAX_TOKENS=4096
export LIFELINE_ADVISOR_TEMPERATURE=0.7Testing:
export LIFELINE_FAKE_RESPONSE="Test advisor response without spending tokens"Custom Tools
phone_a_friend
Manually ask the advisor for help:
phone_a_friend
question: "We've tried three parser optimizations and all failed. What should we try next?"
mode: "next_experiment"
context: "Attempts: inline cache (segfault), arena reuse (no improvement), branchless scan (slower)"
max_ideas: 4
provider: "openai"
model: "gpt-5"Modes:
ideas— brainstormingcritique— critique current approachdebug— debugging helpnext_experiment— what to try next (default)
Overrides:
provider— override the configured advisor provider for this callmodel— override the configured advisor model for this call
log_experiment
Log an experiment result for explicit tracking:
log_experiment
run: 5
metric: 142.3
status: "discard"
description: "Tried memoizing parser tokens — no improvement"Status values:
keep— improvement keptdiscard— no improvement or regressioncrash— caused a crashchecks_failed— tests/checks failed
Logs are appended to autoresearch.jsonl in the current directory.
How It Works
Explicit Detection
When the agent uses log_experiment to track optimization attempts, the plugin reads autoresearch.jsonl and triggers when:
- Consecutive failures: N
discard/crash/checks_failedin a row - Plateau: N runs without a
keep
Implicit Detection
Even without log_experiment, the plugin detects stuck patterns by monitoring:
- Consecutive tool errors: Repeated failures of the same tool
- No-progress plateau: Many turns without successful file edits/writes
- Run counter: Incremented on each
session.idleevent
Implicit detection only activates after a coding-relevant tool (bash, edit, write, grep, glob, read) has been used, preventing false triggers on purely conversational sessions.
Compaction Context
OpenCode can compact long sessions. Lifeline adds a bounded summary to the experimental.session.compacting hook so continuation summaries retain useful stuck-detection context.
The summary includes run counts, advisor call count, the last trigger reason, recent advisor advice, recent autoresearch.jsonl runs, and recent failed tool names. It is truncated before injection to avoid bloating the compaction prompt.
Trigger Action
nudgemode (default, recommended): Injects a context message suggesting the agent callphone_a_friend. Costs nothing until the agent decides to act.askmode: Automatically calls the advisor model and injects the response. Useful for unattended runs but consumes tokens immediately.
Development
# Type-check
npm run check
# Test with fake response (no tokens spent)
export LIFELINE_FAKE_RESPONSE="Try measuring phase timings before further code changes."License
MIT
