Skip to content

Per-target agent frontmatter format transformation (opencode v1.17 permission: vs copilot/cursor tools:) #241

Description

@thinhngotony

Problem

Skillshare syncs the same source agent file to all CLI targets (opencode, copilot, cursor), but each target now has an incompatible frontmatter format for defining agent tool permissions.

Format incompatibility

Target Key Type Example
OpenCode ≥1.17 permission: object permission:\n read: allow\n bash: allow\n mcp-atlassian: allow
Copilot tools: array of strings tools: [read, bash, agent, mcp-atlassian]
Cursor tools: array of strings (same as copilot) tools: [read, bash, agent]

Impact

After upgrading OpenCode to v1.17.13, the old tools: [array] format causes a hard validation error:

Configuration is invalid at manager.agent.md
↳ Expected object | undefined, got ["read","search","execute","agent","mcp-atlassian/*"] tools

Fixing the source to the new permission: {object} format silently breaks Copilot and Cursor, since they only recognize tools: as a string array.

Evidence

  • OpenCode v1.17.13: validation rejects array under tools: key — expects object or absent
  • Copilot API schema (AgentInfo.tools in api.schema.json): "type": "array", "items": { "type": "string" } — no permission field exists
  • Copilot changelog: "Support comma-separated tools in custom agent frontmatter" (v1.0.69, non-negotiable array format)
  • The MCP server tool naming also diverges: copilot uses e.g. mcp-atlassian while older opencode used glob patterns like mcp-atlassian/*

Proposed solution

Skillshare should support per-target frontmatter transformation so the canonical source file can be in one format and skillshare generates the correct format per target during sync. Possible approaches:

  1. Per-target field mapping in skillshare config (.skillshare.yml) — define how to translate fields like permission:tools: per target
  2. Pre/post-sync hooks — user-provided scripts that transform files before/after sync
  3. Canonical internal representation — skillshare normalizes on ingest and serializes per-target

Workaround (current state)

Users are forced to:

  • Only sync agents to one target and manually maintain copies for others, OR
  • Pick the lowest-common-denominator format (copilot/cursor's tools: [array]) and accept that opencode will break, OR
  • Stop using skillshare for agent sync entirely

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions