You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The system prompt's <available_skills> block includes a <location> field with the full absolute file path for every skill. This field is:
Unused by the LLM — skills are loaded via skill(name="foo"), not by path. The tool's internal registry already maps name → location during discovery, so the LLM never needs to know the path.
Extremely verbose — macOS paths like <location>/Users/yejq/Library/Application Support/com.xxx.zzz/mmmm/.opencode-config/skills/art-requirement/SKILL.md</location> average ~136 characters each.
= 141 characters, for a skill whose name (art-requirement) is the only thing the LLM needs to invoke it.
Why <location> is unnecessary
The skill loading flow:
System prompt tells the LLM: "these skills exist, here are their names + descriptions"
LLM decides to use a skill → calls skill(name="ppt-master")
The tool internally maps name → location (already known from discovery)
The tool reads SKILL.md and returns the content + a base directory hint
At no point does the LLM need the file path. The tool's internal registry already knows where every skill lives. The <location> field in the system prompt is pure context pollution.
For skills that reference relative resources (scripts/, references/), the base directory is already provided in the tool output when the skill is loaded — again, no need for the LLM to pre-know it.
Where the waste happens
In packages/opencode/src/tool/skill.ts (as documented in #13188):
And in the system prompt via Skill.fmt(list, { verbose: true }) (as documented in #22236):
Injection point
Format
Includes <location>?
System prompt body (verbose: true)
XML
Yes
Skill tool description (verbose: false)
Compact markdown
No
The verbose: false path already excludes <location>, proving it's not essential for the tool description. The system prompt just inherited it.
Proposed solutions
Option A (minimal, safe): Strip <location> from the system prompt only
Keep the verbose: true XML format but omit the <location> tag
The tool description already omits it (verbose: false)
The full location is still returned in the tool output when a skill is actually loaded (where it's genuinely useful for resolving relative resource paths)
Option B (configurable): Add an includeLocation flag to Skill.fmt()
For users with many skills (common in plugin-heavy setups), this is pure waste — 3K+ tokens that could be used for actual conversation context, tool results, or just cost savings. The fix is effectively a one-line change with zero functional impact, since the skill tool resolves name → location internally regardless of what's in the system prompt.
Description
The system prompt's
<available_skills>block includes a<location>field with the full absolute file path for every skill. This field is:skill(name="foo"), not by path. The tool's internal registry already mapsname→locationduring discovery, so the LLM never needs to know the path.<location>/Users/yejq/Library/Application Support/com.xxx.zzz/mmmm/.opencode-config/skills/art-requirement/SKILL.md</location>average ~136 characters each.pathToFileURL— spaces become%20,#becomes%23, and afile://prefix adds 7 chars on top (as documented in fix(skill): skill directory context missing or URL-encoded in system prompt and slash-command paths #33786).Token waste measurement (real-world data)
Measured from an actual system prompt dump with 84 skills:
3.2K tokens burned on every API call on paths the LLM never reads, never uses, and doesn't need.
Single sample entry:
= 141 characters, for a skill whose name (
art-requirement) is the only thing the LLM needs to invoke it.Why
<location>is unnecessaryThe skill loading flow:
skill(name="ppt-master")name→location(already known from discovery)At no point does the LLM need the file path. The tool's internal registry already knows where every skill lives. The
<location>field in the system prompt is pure context pollution.For skills that reference relative resources (
scripts/,references/), the base directory is already provided in the tool output when the skill is loaded — again, no need for the LLM to pre-know it.Where the waste happens
In
packages/opencode/src/tool/skill.ts(as documented in #13188):And in the system prompt via
Skill.fmt(list, { verbose: true })(as documented in #22236):<location>?verbose: true)verbose: false)The
verbose: falsepath already excludes<location>, proving it's not essential for the tool description. The system prompt just inherited it.Proposed solutions
Option A (minimal, safe): Strip
<location>from the system prompt onlyverbose: trueXML format but omit the<location>tagverbose: false)Option B (configurable): Add an
includeLocationflag toSkill.fmt()Option C (root cause): Use the skill name as the identifier instead of the full path
This preserves the field for any consumer that depends on its presence, without the token bloat.
Related issues
<location>in the bloat total)verbose: trueincludes<location>)pathToFileURL(confirms the encoding problem)Impact
For users with many skills (common in plugin-heavy setups), this is pure waste — 3K+ tokens that could be used for actual conversation context, tool results, or just cost savings. The fix is effectively a one-line change with zero functional impact, since the skill tool resolves
name→locationinternally regardless of what's in the system prompt.