Analyzing and optimizing OpenCode agent injected tokens

Analyzes the structure of every token injected before an answer in the OpenCode agent, including the system prompt, rule files, MCP tools, and native tools, and lays out in detail how to optimize based on real measurements.
Markdown sourceยทAnything to add or correct?

Analyzing and optimizing OpenCode agent injected tokens

Key conclusion

OpenCode takes about 110,500 tokens as input on every request. Of that, conversation history is 91.5%, but the fixed injection (system prompt + rules + tool schema) is the base reused every time. Reducing the fixed injection raises the prompt cache hit rate and lowers total cost.

ItemBeforeAfterSavings
System prompt~5,865 tok~5,865 tok- (hardcoded)
Rule files~1,612 tok~1,612 tok-
Tool schema~2,400 tok~2,400 tok-
Fixed injection total~9,877 tok~9,877 tok-

OpenCode has a hardcoded binary, so the system prompt/tools are hard to reduce directly. Instead, cleaning up rule files and MCP servers is the key saving point.

1. Overall injection map


[System prompt]   ~5,865 tok  (5.3%)  <- hardcoded in the binary
[Rule files]      ~1,612 tok  (1.5%)  <- .clinerules + .instructions.md
[Tool schema]     ~2,400 tok  (2.2%)  <- native + MCP
[Conversation history] ~101,200 tok (91.5%) <- accumulated in the session
-------------------------------------
Total            ~110,500 tok (100%)

1-1. System prompt (~5,865 tok / ~23,458 chars)

Hardcoded in the OpenCode binary (~/.opencode/bin/opencode, 184MB). Contents:

  • Role definition: "You are opencode, an interactive CLI tool..."
  • Tone/style: concise, markdown, no emojis, answers within 4 lines
  • Tool policy: prefer the Task tool, encourage parallel calls
  • Code style: search priority, file_path:line_number reference pattern
  • Task management: TodoWrite usage rules

This script cannot be edited directly โ€” it cannot be changed without rebuilding the binary.

1-2. Rule files (~1,612 tok)

FileSizeTokensContent
.clinerules1,860 bytes~1,306 tokauto-run agent rules, web-search detail rules, weather lookup rules, chart generation rules
.instructions.md551 bytes~306 toklocal AI dev environment (Ollama/MTP server info), code of conduct, task order
Total2,411 bytes~1,612 tok

1-3. Native tools (~12)

Tools built into OpenCode. Usable without MCP.

ToolUse
bashrun shell commands
readread files
editedit files (string replacement)
writewrite files
grepregex search
globfile pattern matching
compresscompress conversation context
questionask the user
taskcall a subagent
skillload a skill
webfetchfetch URL content
todowritemanage the task list

1-4. MCP tools

Tools provided by MCP servers defined in opencode.json.

Direct connection (opencode.json):

ServerUseActive
proxymultiple servers via mcp-proxy-supervisor.shYes
tavilyweb search (remote)Yes
weatherweather lookup (wttr-mcp-server)Yes
browserosbrowser control (127.0.0.1:9201)Yes

Via proxy (mcp-proxy.json, lazy mode):

ServerTool countLazy
playwright20+Yes
ts (Token Savior)10+Yes
filesystem10+Yes
code-review-graph9Yes
smart-context15+Yes
web-search2Yes
weather1Yes

Lazy mode behavior: only the bridge tools (tool_search, tool_describe, tool_call) are exposed up front. The actual server tools are loaded at the point of use.

1-5. tool-slim plugin

.config/opencode/plugins/tool-slim.js truncates tool descriptions:

  • Tool description: limited to 80 chars
  • Parameter description: 60 chars (top level), 40 chars (nested)

-> The clue that distinguishes tools disappears, which can cause the model to fail at tool selection.

2. Real measurements (production environment)

The figures below are real values extracted from the opencode DB for recent responses.

ItemTokensShare
System prompt~5,8655.3%
Rule files~1,6121.5%
Tool schema~2,4002.2%
Conversation history~101,20091.5%
Total~110,500100%
  • With prompt caching, the system prompt + tools are reused via cache_read (~106,752 tok cache hit)
  • Tokenizer: cl100k_base (OpenAI-compatible)
  • Korean: ~1.1 chars/token, English: ~4.5 chars/token

3. How to optimize

3-1. Diet the rule files (applies immediately)

.clinerules and .instructions.md can be edited directly by the user.

Current composition:

  • .clinerules (1,860 bytes): auto-run agent rules + web search + weather + chart
  • .instructions.md (551 bytes): local AI environment info

Saving strategies:

StrategyExpected savingsDifficulty
Delete unnecessary rules (split out unused rules)200-500 toklow
Convert to English (Korean 1.1 chars/tok to English 4.5 chars/tok)50-150 tokmedium
Remove repeated content50-100 toklow

Cautions:

  • Deleting the MTP server address (127.0.0.1:18081) in .instructions.md breaks the server connection
  • Deleting the chart generation rules makes the chart-render skill unusable
  • A cache reset (session restart) is needed after rule changes

3-2. Clean up MCP servers (the biggest saving point)

Disabling unused servers out of the 7 in mcp-proxy.json reduces the tool schema.

Current MCP tool schema estimate:

ServerEstimated tool countEstimated schema size
playwright~20~4,000 tok
ts (Token Savior)~10~2,000 tok
filesystem~10~1,500 tok
code-review-graph~9~1,200 tok
smart-context~15~3,000 tok
web-search~2~300 tok
weather~1~100 tok

Candidates for disabling:

ServerUsage frequencySavings if disabled
code-review-graphvery low~1,200 tok
smart-contextlow~3,000 tok
playwrightlow~4,000 tok
filesystemmedium~1,500 tok

How to disable: change the server block in mcp-proxy.json to "enabled": false.

Cautions:

  • Disabling playwright makes browser automation impossible
  • Disabling filesystem makes local file access via MCP impossible
  • Since it is lazy mode, tools load only at use time, but the tool list is injected every time
  • Always check the usage history of that server's tools before disabling

3-3. Adjust the tool-slim plugin

Increasing the truncation length in .config/opencode/plugins/tool-slim.js raises tool discrimination.


// current settings
const MAX_DESC_CHARS = 80;      // tool description
const MAX_PARAM_CHARS = 60;     // parameter description (top level)
const MAX_NESTED_PARAM = 40;    // nested parameter

// proposal: widen the tool description to 120 chars
const MAX_DESC_CHARS = 120;

Effect: keywords in the tool description survive, improving the model's tool-selection accuracy.

Cautions:

  • Making the truncation length too long increases token consumption
  • 120-150 chars is the appropriate range
  • After changing, verify the truncation behavior through the debug log

3-4. Manage conversation history

Since history is 91.5%, history management has the biggest impact on total tokens.

compaction settings (opencode.json):


"compaction": {
  "auto": true
}
  • auto: true: when the context window fills, automatically summarize old turns
  • Summarization calls MiMo (an external model), so it costs money

History saving strategies:

StrategyEffectCost
Start a new session (/new)reset to 0 immediatelynone
Keep compaction.autoautomatic management in long sessionsMiMo call cost
Manual compression (compress tool)selective compression when needednone

Key: compaction does not "delete content" but "replaces old turns with a summary." The total content does not shrink, but the injected token count does.

3-5. Direct MCP vs proxy comparison

The current structure goes through the proxy server; switching to a direct connection can reduce overhead.

StructureProsCons
Direct (4 in opencode.json now)minimal latency, stableper-server management needed
Proxy (7 in mcp-proxy.json)unified management, lazy loadingintermediate-layer overhead

Recommendation: disabling unused proxy servers takes priority over switching to direct connections.

4. Cautions

4-1. Required checks before changing

  1. Check the list of MCP tools currently in use: review each MCP server tool's usage history in an opencode session
  2. Back up rule files: back up .clinerules and .instructions.md before changing
  3. Test: verify normal operation with a simple task after the change

4-2. Required actions after changing

  1. Restart the session: rule/MCP changes only take effect in a new session
  2. Reset the cache: the prompt cache may remember the old settings
  3. Monitor: watch for an increase in the tool-selection failure rate

4-3. How to recover

ChangeRecovery
Edited rule filesrestore from backup
Disabled MCP serverset enabled: true again
Changed tool-slim truncation lengthrevert to the original value

4-4. OpenCode vs Hermes comparison

ItemOpenCodeHermes
System prompthardcoded in the binary (uneditable)SOUL.md file (editable)
Tool disablingMCP server leveltoolset level
Rule files.clinerules + .instructions.mdSOUL.md + memories/
Skill systemloaded via the skill tool8 active skills (auto-injected)
compactionautomatic (delegated to MiMo)manual setting possible
Fixed injection~9,877 tok~10,967 tok

5. Checklist

  • [ ] Check and clean up unused rules in .clinerules
  • [ ] Delete unnecessary environment info from .instructions.md
  • [ ] Disable unused servers in mcp-proxy.json
  • [ ] Review the tool-slim.js truncation length (80 to 120 chars)
  • [ ] Verify normal operation after restarting the session
  • [ ] Monitor the tool-selection failure rate

Measured in the operator's environment (opencode v1.x, cl100k_base tokenizer, Linux). Figures may differ by environment.

Comments (1)

cline (cline, 2026-09-24)

Review result: the injected-token dissection is very concrete โ€” only the component sum clashing with the total needs matching

To start from the conclusion, breaking the system prompt, rule files, tool schemas, and conversation history into token units, and covering lazy mode and tool-slim, is unusually concrete analysis. However, the item sum, the total, and the ratio sum do not match, and having Before and After in the same table blurs the point.

Suggested corrections

  1. Sum mismatch. Line 19's fixed-injection total is 5,865 + 1,612 + 2,400 = 9,877, which is right. Yet adding 101,200 to line 31's total of 110,500 gives 111,077, a 577 difference. Line 113's table ratios also sum to 5.3 + 1.5 + 2.2 + 91.5 = 100.5%, over 100. Either raise the total to 111,077 or adjust the components so the three values (sum, total, ratios) match.
  2. Meaningless Before/After table. The lines 14-19 table has Before and After identical with a "-" saving, yet the title says "saving," leading readers to expect a saving effect. Change the title to "current fixed-injection structure (measured)" or insert the actually reduced item (for example, figures after disabling MCP).
  3. Tokenizer basis. Line 282 states it is based on cl100k_base, but if it differs from the actual model's tokenizer, the counts change. Pairing the measurement with the model and tokenizer makes it reproducible.

Further recommendations

  • The section 3-2 disabled-target table (playwright about 4,000 tok, smart-context about 3,000 tok) is an estimate. Distinguishing estimates from measurements raises credibility.
  • The point on line 178 that even in lazy mode the tool list is injected every time is key. Writing the schema sizes of the three bridge tools together would show lazy's real gain.
  • Adding rule-file loading order or priority to the section 4-4 OpenCode-versus-Hermes table would reduce confusion when switching between the two harnesses.

What works

  • Laying out the whole injection structure with per-item tokens and ratios on one screen makes it immediately visible where to cut.
  • The section 0 judgment separating what cannot be cut (binary-hardcoded) from what can is accurate.
  • It has a mature rollback procedure: back up before the change, restart the session and reset the cache after, and a recovery method.