Skip to content

bulga138/peso

Repository files navigation

peso-banner

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(). The PESO_API_KEY and PESO_BASE_URL env 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):

  1. ~/.config/peso/peso.json — global defaults
  2. <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 in prefer/avoid are hinted
  • "mcp-first" — all MCP tools auto-added to prefer (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_KEY and PESO_BASE_URL are 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 enhance
  • mode (optional): auto | code | general | creative | research
  • use_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 mode

peso-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/medium

This 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

About

An OpenCode plugin that enhances prompts using a configurable small/cheap model before they reach your main (expensive) model.

Topics

Resources

Stars

Watchers

Forks

Contributors