Problem
Skillshare syncs the same agent .md file verbatim to all targets (OpenCode, Copilot, Cursor), but each target now enforces incompatible frontmatter schemas for agent tool permissions. This causes hard crashes or silent breakage.
| Target |
Key |
Type |
Example |
| OpenCode ≥1.17 |
permission: |
object |
permission:\n read: allow\n bash: allow |
| Copilot |
tools: |
array |
tools: [read, bash, agent] |
| Cursor |
tools: |
array |
tools: [read, bash, agent] |
OpenCode rejects the array format outright:
Configuration is invalid at manager.agent.md
↳ Expected object | undefined, got ["read","search","execute","agent","mcp-atlassian/*"] tools
Copilot has no permission: field in its schema — only tools: as an array is recognized. The Copilot changelog (v1.0.69) confirms: "Support comma-separated tools in custom agent frontmatter" — non-negotiable array format.
Fixing the source to permission: {object} silently breaks Copilot and Cursor. There is currently no single format that works across all three targets.
Evidence
- OpenCode v1.17.13: validation rejects array under
tools: key — expects object or absent
- Copilot API schema (
AgentInfo.tools): "type": "array", "items": { "type": "string" } — no permission field exists
- MCP server tool naming also diverges: Copilot uses
mcp-atlassian while OpenCode uses glob patterns like mcp-atlassian/*
Proposed Solution
Add per-target frontmatter transformation during skillshare sync agents. The canonical source stays in one format, and skillshare generates the correct format per target.
Option A: Config-driven field mapping
targets:
copilot:
agents:
path: ~/.copilot/agents
frontmatter:
map:
permission: tools # rename field
permission.*: flatten # object → array (keys become values)
cursor:
agents:
path: ~/.cursor/agents
frontmatter:
map:
permission: tools
permission.*: flatten
opencode:
agents:
path: ~/.config/opencode/agents
# no transformation — use source format as-is
Option B: Pre-sync hook script
targets:
copilot:
agents:
path: ~/.copilot/agents
frontmatter:
transform: ~/.config/skillshare/transforms/opencode-to-copilot.py
Option C: Extension-based (reuse existing extras mechanism)
Move agents to extras: config and use per-target extensions (already supported for commands/rules). Requires agents to be managed as extras rather than native agent targets.
Alternatives Considered
- Maintain separate agent files per target — works but defeats single-source-of-truth; every edit requires updating N copies.
- Pick lowest-common-denominator format — Copilot's
tools: [array] ignores OpenCode's richer permission model (read: allow vs read: full).
- Wait for CLI standardization — unlikely; each tool ships its own schema independently.
Scope
Likely touches: agent sync pipeline, config parsing, frontmatter transformer.
Open Questions
- Which option (A/B/C) fits skillshare's architecture best?
- Should transformations be composable (field rename + flatten + strip unsupported keys)?
- Should the transform run at sync time (A/B) or at collect time (C)?
- How to handle MCP tool naming divergence (
mcp-atlassian vs mcp-atlassian/*)?
Problem
Skillshare syncs the same agent
.mdfile verbatim to all targets (OpenCode, Copilot, Cursor), but each target now enforces incompatible frontmatter schemas for agent tool permissions. This causes hard crashes or silent breakage.permission:permission:\n read: allow\n bash: allowtools:tools: [read, bash, agent]tools:tools: [read, bash, agent]OpenCode rejects the array format outright:
Copilot has no
permission:field in its schema — onlytools:as an array is recognized. The Copilot changelog (v1.0.69) confirms: "Support comma-separated tools in custom agent frontmatter" — non-negotiable array format.Fixing the source to
permission: {object}silently breaks Copilot and Cursor. There is currently no single format that works across all three targets.Evidence
tools:key — expects object or absentAgentInfo.tools):"type": "array", "items": { "type": "string" }— nopermissionfield existsmcp-atlassianwhile OpenCode uses glob patterns likemcp-atlassian/*Proposed Solution
Add per-target frontmatter transformation during
skillshare sync agents. The canonical source stays in one format, and skillshare generates the correct format per target.Option A: Config-driven field mapping
Option B: Pre-sync hook script
Option C: Extension-based (reuse existing extras mechanism)
Move agents to
extras:config and use per-target extensions (already supported for commands/rules). Requires agents to be managed as extras rather than native agent targets.Alternatives Considered
tools: [array]ignores OpenCode's richer permission model (read: allowvsread: full).Scope
Likely touches: agent sync pipeline, config parsing, frontmatter transformer.
Open Questions
mcp-atlassianvsmcp-atlassian/*)?