@bulga138/peso
v0.2.0
Published
Prompt Engineering Smart Optimizer — OpenCode plugin
Readme

PESO
Prompt Engineering Smart Optimizer
An OpenCode plugin that enhances prompts using a configurable small/cheap model before they reach your main (expensive) model.
How it works
User types prompt
↓
PESO plugin (chat.message hook)
↓ short prompt? → intent detection (fix/explain/refactor/…) → expand
↓ classifies prompt (rule-based, zero cost)
↓ Agent Compass: reads agent permissions → sets intensity
↓ 10-stage pipeline + 26 VILA-Lab techniques (model-tier-aware)
↓ style directives → system prompt; user prompt stays clean
↓ if use_llm: calls small model via SDK for domain-specific rewrite
↓ quality gate: keeps winner of (original, pipeline, llm)
↓ injects context (git, tools, MCP tools)
↓ mutates prompt → main model receives enhanced version
↓ UI feedback line appended (score delta, techniques count, domain)Modes
| Mode | Behavior |
| --------- | ---------------------------------------------------------- |
| on | Transparent — all prompts enhanced automatically (default) |
| passive | Only enhances when agent explicitly calls the peso tool |
| off | Fully disabled |
Set via PESO_MODE=passive env at startup, or toggle at runtime with the peso-toggle tool.
Agent Compass
PESO reads real agent permissions from the SDK to determine enhancement intensity:
| Agent Profile | Permissions | Intensity | | ------------------- | ---------------------- | --------- | | Plan (read-only) | edit:deny, bash:deny | Light | | Build (full access) | edit:allow, bash:allow | Full | | Explore (search) | edit:deny, bash:ask | None | | General | mixed | Medium |
Installation
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["@bulga138/peso"]
}Configuration
Model Resolution
In plugin mode, PESO uses the OpenCode SDK to resolve the model — no API keys or base URLs needed:
| Priority | Source | Example |
| -------- | ------------------------------------- | ----------------------------------------------- |
| 1 | PESO_MODEL env var | export PESO_MODEL=groq/llama-3.1-8b-instant |
| 2 | SDK: small_model in opencode.json | "small_model": "anthropic/claude-haiku-4-5" |
| 3 | SDK auto-detection | OpenCode picks cheapest model for your provider |
| 4 | SDK: model in opencode.json | Falls back to main model |
| 5 | Hardcoded fallback | opencode/zen (free, always available) |
Note: In plugin mode (the default), all auth and routing is handled by the OpenCode SDK via
client.session.prompt(). ThePESO_API_KEYandPESO_BASE_URLenv vars only apply to the standalone CLI fallback path.
Example opencode.json
{
"$schema": "https://opencode.ai/config.json",
"model": "anthropic/claude-sonnet-4-5",
"small_model": "anthropic/claude-haiku-4-5"
}PESO will automatically use claude-haiku-4-5 for enhancement work.
Config File (peso.json)
PESO loads config from two locations (deep-merged):
~/.config/peso/peso.json— global defaults<project>/peso.json— project overrides
{
"mode": "passive",
"shortPromptThreshold": 15,
"toolPriorities": {
"prefer": ["read", "glob", "grep", "serena_find_symbol"],
"avoid": ["task", "webfetch", "websearch"]
},
"techniques": {
"enabled": "all",
"disabled": ["emotional-stimuli"]
},
"techniquePacks": {
"enabled": "all",
"disabled": []
},
"context": {
"injectGit": true,
"injectMcpTools": true,
"maxChangedFiles": 10
},
"options": {
"baseURL": "{env:ANTHROPIC_URL}",
"apiKey": "{env:ANTHROPIC_AUTH_TOKEN}"
}
}Tool priorities tell the model which tools are cheap (prefer) vs expensive (avoid). This gets injected as <prefer-tools> and <avoid-tools> in the context block, nudging the model to use read/glob/grep before spawning a task subagent.
toolPriorities.mode:
"manual"(default) — only tools listed inprefer/avoidare hinted"mcp-first"— all MCP tools auto-added toprefer(favors MCP over native OpenCode tools)
Run peso-config to see all available tools and set up your priorities.
techniquePacks (optional): controls which globally-installed technique packs are active for this project. Packs are .js files placed in ~/.config/peso/packs/. See Extensible Techniques below.
Environment Variables
| Variable | Purpose | Default |
| --------------- | ----------------------------------------------- | --------------- |
| PESO_MODE | Set mode at startup: on, passive, off | on |
| PESO_AUTO | Set to 0 to disable (same as PESO_MODE=off) | — |
| PESO_MODEL | Override model for enhancement | SDK auto-detect |
| PESO_API_KEY | API key for CLI fallback path only | — |
| PESO_BASE_URL | Base URL for CLI fallback path only | — |
In plugin mode,
PESO_API_KEYandPESO_BASE_URLare not needed — the SDK handles auth.
Tools Provided
peso
Full enhancement pipeline. Classifies the prompt, applies research-backed techniques, optionally calls the small model for a complete rewrite.
Use the peso tool to enhance: "fix the login bug"Arguments:
prompt(required): The prompt to enhancemode(optional):auto|code|general|creative|researchuse_llm(optional): Whether to call the small model (default: true)
peso-score
Score a prompt 0-10 without modifying it. Shows rule violations and dimension breakdown.
peso-debug
Run the full pipeline with trace output: classification, techniques applied, before/after scores, agent compass vector, LLM call result.
peso-toggle
Switch PESO mode at runtime:
peso-toggle passive # only enhances when agent calls peso tool
peso-toggle on # transparent enhancement (default)
peso-toggle off # fully disabled
peso-toggle # show current modepeso-config
Show current configuration: SDK-resolved model, local fallback model, API key status, agent compass table with per-agent intensities.
Performance
PESO uses aggressive caching to minimize overhead:
| Data | Strategy | Cost on cache hit |
| ------------------------------- | --------------------------------- | ----------------- |
| CLI tools (git, node, etc.) | Session-scoped (never re-checked) | 0 |
| Git branch | .git/HEAD mtime check | 1 stat call |
| Git changed files | .git/index mtime check | 1 stat call |
| Git recent commit | .git/HEAD mtime check | 1 stat call |
| Agent list | Cached after first SDK call | 0 |
| MCP/plugin tool IDs | Cached after first SDK call | 0 |
Typical per-message overhead: <1ms (no shell forks, no network) unless git state actually changed.
Context Injection
PESO injects a <peso:context> block into enhanced prompts:
<peso:context>
<date>2026-05-07</date>
<cwd>/Users/you/project</cwd>
<git-branch>feat/my-feature</git-branch>
<git-changed-files>src/index.ts, src/utils.ts</git-changed-files>
<available-tools>git, bun, node, npm, npx, curl, jq</available-tools>
<mcp-tools>bash, read, glob, grep, edit, write, task, webfetch, peso, ...</mcp-tools>
<project-instructions>true</project-instructions>
</peso:context><mcp-tools>lists all MCP + plugin tools from the SDK (not just CLI binaries)<project-instructions>signals when CLAUDE.md / .cursorrules exist (avoids redundant injections)<freshness-warning>added when prompt references "latest", "current", or future dates
What it enhances
Rule-based (free, always runs):
- Position sensitivity: critical instructions moved to first 15%
- Nesting depth check (max 4 levels)
- Instruction ratio optimization (40-50%)
- Duplicate rule consolidation
- Priority statement injection
- 26 VILA-Lab principled techniques (auto-selected by domain and model tier)
Model-tier-aware filtering
PESO detects the active model and skips techniques that add noise for capable models:
| Tier | Models | Behavior |
| ---------- | ----------------------------------- | -------------------------------------------------------------------- |
| frontier | Opus, GPT-4o, o1/o3, Gemini 2.5 Pro | Minimal injection — only task-specific techniques (verify, examples) |
| standard | Sonnet, GPT-4-turbo | Same as frontier — style directives go to system prompt only |
| small | Haiku, GPT-4o-mini, Gemini Flash | Full injection — includes step-by-step, chain-of-thought, decompose |
Style/constraint directives (constraints, brevity, output-length, scope-limit, language-spec, positive-framing) always go to the system prompt, never the user prompt. This keeps user prompts clean and avoids wasting input tokens on every message.
Reasoning nudges (step-by-step, emotional-stimuli, chain-of-thought, decompose) only fire for small models where they measurably help
LLM-based (costs small-model tokens):
- Full prompt rewrite preserving intent, using a domain-specific system prompt (code/research/creative/general)
- Quality gate: scores the original, pipeline output, and LLM rewrite — keeps the highest-scoring version. Falls back to the original if both enhancements score lower.
- Context-aware restructuring
Short-prompt expansion
Prompts of 6 words or fewer are matched against a set of verb-first intent patterns before entering the pipeline:
| Input | Expanded to |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| fix login | Fix the issue with login. Identify the root cause, explain what is wrong, and provide the corrected code. |
| refactor auth | Refactor auth. Improve readability and reduce complexity while maintaining the same behaviour. Show before and after. |
| explain middleware | Explain how middleware works. Cover the key logic, data flow, and any non-obvious behaviour. |
Recognised verbs: fix, explain, refactor, add, remove, test, debug, update, implement, review. Single-word non-verb prompts (e.g. hello) are still skipped.
Inline feedback
After each transparent enhancement (mode on), PESO appends a UI-visible, LLM-hidden feedback line:
✦ peso: 5.8→8.1 (+2.3) | 4 techniques | code/mediumThis line uses the ignored: true SDK part flag — it appears in the OpenCode UI but is never sent to the model.
Extensible Techniques
You can add your own technique packs without modifying PESO's source. Packs are installed globally and each project controls which are active.
1. Create a pack file
// ~/.config/peso/packs/security.js
export default {
name: 'security-pack',
version: '1.0.0',
techniques: [
{
id: 'security-review',
name: 'Security Review Nudge',
description: 'Flags security concerns for auth/token prompts',
domains: ['code'],
applies: prompt => /auth|login|password|token|secret/i.test(prompt),
inject: prompt =>
prompt + '\n\nIMPORTANT: Review for security vulnerabilities (injection, XSS, auth bypass, secrets exposure).',
},
],
};2. Drop it in the global packs directory
mkdir -p ~/.config/peso/packs
cp security.js ~/.config/peso/packs/PESO auto-discovers all .js files in ~/.config/peso/packs/ at startup. No registration needed — just drop the file.
3. Control per project
By default, all discovered packs are loaded. Use the project's peso.json to filter:
{
"techniquePacks": {
"enabled": "all",
"disabled": ["noisy-pack"]
}
}| Config | Effect |
| ----------------------------------------- | ------------------------------------------------------ |
| "enabled": "all" | Load all discovered packs (default) |
| "enabled": ["security-pack"] | Load only named packs |
| "disabled": ["noisy-pack"] | Exclude specific packs (takes precedence over enabled) |
| "disabled": ["security-pack/xss-check"] | Disable a single technique within a pack |
The global ~/.config/peso/peso.json can also set techniquePacks.disabled to block packs across all projects.
Security note: Pack files are executed as real JavaScript modules via dynamic
import(). Only load packs from sources you trust.
Inspirations
| Source | Contribution | | ------------------------------------------------------------------------------------------- | ------------------------------------------ | | mtayfur/opencode-prompt-enhancer | Plugin pattern, workspace context | | diegohb gist | Argument intelligence | | lim-hyo-jeong/Prompt-Enhancer | 26 VILA-Lab principles | | meta-introspector dotfiles | 10-stage pipeline, scoring | | ruhanirabin/vscode-prompt-enhancer | Template system | | DeepMind OPRO | Step-by-step breathing (small models only) | | Microsoft Research | Emotional stimuli (small models only) | | Stanford/Anthropic | Position sensitivity | | Anthropic Prompting Best Practices (2026) | Model-tier-aware technique filtering |
