Back to Brain Lab Skill · Convert to Copilot · convert-to-copilot/
Skill Claude

Convert to Copilot

convert-to-copilot/

4 views 0 downloads

Port a Claude Code agent, with its command and skills, to one GitHub Copilot agent. Maps tools, models and sub-agent calls, validates the result and ships scripts for both directions.

Convert to Copilot: Brain Lab skill for Claude Code

Port a Claude Code agent, with its command and skills, to one GitHub Copilot agent that works the same way.

Why use it

  • Your team uses both Claude Code and GitHub Copilot, and every agent has to be written twice.
  • Copilot has no skills or commands: a straight copy loses the knowledge and the triggers the agent depends on.
  • Hand-ported agents drift, wrong tool aliases (fetch instead of web), dead file paths, task tracking that fails silently.

What it does

  • Merges the agent + its launch command into one .github/agents/{name}.agent.md, with the command's trigger phrases in the description.
  • Splits every skill into .copilot_utils/{name}/context/ (what to use) and trees/ (how to decide), and rewrites each skill reference to a file path.
  • Maps tools, models and frontmatter: WebFetch → web, TaskCreate → manage_todo_list, opus → Claude Opus 4.5, drops color / memory / isolation / skills / allowed-tools.
  • Converts sub-agent calls to handoffs (VS Code) or runSubagent() (GitHub Copilot).
  • Validates the result, every referenced path exists, aliases are correct, body under 30,000 characters, and prints a conversion report.
  • Ships scaffold scripts for both directions (claude-to-copilot, copilot-to-claude) and a full worked example.

Benefits

  • Write the agent once. Claude Code stays the source; Copilot gets a faithful port.
  • No lost knowledge. Skills become referenced context files, not a pasted wall of text.
  • Correct on the first run. The tool and model tables catch the aliases that break Copilot agents.
  • Reviewable. Each phase writes its output to .copilot-convert-results/, so you can see every decision.

Install

Download this skill and copy the convert-to-copilot folder to .claude/skills/convert-to-copilot/ in your project, or to ~/.claude/skills/convert-to-copilot/ to use it in every project. Claude Code finds it on its own; you can also call it with /convert-to-copilot.

Part of the Agent Engineering bundle. To get the whole set as a Claude Code plugin: /plugin marketplace add endorphin-ai/hasbrains-agent-kit, then /plugin install agent-engineering@hasbrains-agent-kit.

Source: endorphin-ai/hasbrains-agent-kit. License: MIT.

Files (17)

Files

copilot-to-claude.sh
#!/usr/bin/env bash
# copilot-to-claude.sh — scaffold Copilot agent → Claude Code structure
# Sourced by convert-agents.sh. Requires lib-extract.sh to be sourced first.
# After scaffolding, run /convert-from-copilot in Claude Code for content transformation.

copilot_to_claude() {
  local agent_file="$AGENT_FILE"
  local dst="${CLAUDE_DIR:-$HOME/.claude}"
  local name; name=$(basename "$agent_file"); name="${name%.agent.md}"; name="${name%.md}"
  local utils_dir=".copilot_utils/${name}"

  echo -e "${B}=== Copilot → Claude: ${name} ===${NC}\n"

  [[ ! -f "$agent_file" ]] && echo -e "${R}❌ Not found: $agent_file${NC}" && exit 1
  if [[ ! -d "$utils_dir" ]]; then
    echo -e "${Y}⚠️  No ${utils_dir}/ found — scaffolding agent + command only${NC}"
  fi

  # --- Agent placeholder ---
  mkdir -p "$dst/agents"
  local agent_out="$dst/agents/${name}.md"
  if [[ -f "$agent_out" ]]; then
    echo -e "${Y}⚠️  $agent_out exists — skipped (delete to regenerate)${NC}"
  else
    {
      echo "---"
      echo "name: ${name}"
      echo "description: \"$(extract_fm "$agent_file" "description")\""
      echo "model: inherit"
      echo "color: blue"
      echo "memory: project"
      echo "isolation: worktree"
      echo "---"
      echo ""
      echo "<!-- SCAFFOLD: Body needs content transformation."
      echo "     Run /convert-from-copilot ${agent_file} in Claude Code to complete. -->"
      echo ""
      cat "$agent_file"
    } > "$agent_out"
    echo -e "  ${G}✅${NC} → agents/${name}.md  (scaffold — /convert-from-copilot to finish)"
  fi

  # --- Command ---
  mkdir -p "$dst/commands"
  local sname; sname=$(short_name "$name")
  local arg_hint; arg_hint=$(extract_fm "$agent_file" "argument-hint")
  cat > "$dst/commands/${sname}.md" << CMDEOF
---
description: "Launch ${name}. Usage: /${sname} ${arg_hint:-<input>}"
argument-hint: "${arg_hint:-<input>}"
allowed-tools: ["Bash(git:*)", "Bash(gh:*)"]
---

Run ${name} on \$ARGUMENTS.

Input: \$ARGUMENTS

Task(
  description="${name}: \$ARGUMENTS",
  subagent_type="${name}",
  isolation="worktree",
  prompt="Execute the full workflow for: \$ARGUMENTS"
)
CMDEOF
  echo -e "  ${G}🔗${NC} → commands/${sname}.md"

  # --- Context/trees → skills ---
  if [[ -d "$utils_dir" ]]; then
    declare -A skill_map
    for f in "$utils_dir/context"/*.md "$utils_dir/trees"/*.md; do
      [[ -f "$f" ]] || continue
      local bn; bn=$(basename "$f" .md)
      # Skip template files — they go to assets/
      [[ "$bn" == *-templates ]] && continue
      # Strip known suffixes to get skill name
      local key; key=$(echo "$bn" | sed 's/-examples$//' | sed 's/-reference$//')
      skill_map["$key"]="$f"
    done

    for skill in "${!skill_map[@]}"; do
      local src="${skill_map[$skill]}"
      local sd="$dst/skills/$skill"
      mkdir -p "$sd/references" "$sd/assets" "$sd/trees" "$sd/scripts"

      if [[ ! -f "$sd/SKILL.md" ]]; then
        local lc=0; [[ -f "$src" ]] && lc=$(wc -l < "$src")
        {
          echo "---"
          echo "name: ${skill}"
          echo "description: \"This skill provides knowledge about ${skill} for the ${name} agent. Load when the agent needs ${skill} capabilities.\""
          echo "---"
          echo ""
          echo "# ${skill}"
          echo ""
          if [[ $lc -le 100 && -f "$src" ]]; then
            cat "$src"
          elif [[ -f "$src" ]]; then
            echo "See \`references/detail.md\` for full content."
          fi
        } > "$sd/SKILL.md"

        if [[ $lc -gt 100 && -f "$src" ]]; then
          cp "$src" "$sd/references/detail.md"
          echo -e "     ${B}📁${NC} ${lc} lines → references/detail.md"
        fi
        echo -e "  ${G}📄${NC} → skills/${skill}/SKILL.md  [${lc} lines]"
      else
        echo -e "  ${Y}⚠️${NC}  skills/${skill}/SKILL.md exists — skipped"
      fi

      # Templates → assets/
      local tmpl="$utils_dir/context/${skill}-templates.md"
      if [[ -f "$tmpl" ]]; then
        cp "$tmpl" "$sd/assets/${skill}-template.md"
        echo -e "     ${G}📦${NC} → assets/${skill}-template.md"
      fi

      # Trees file → trees/
      local tree="$utils_dir/trees/${skill}.md"
      if [[ -f "$tree" && ! -f "$sd/trees/${skill}.md" ]]; then
        cp "$tree" "$sd/trees/"
        echo -e "     ${G}🌳${NC} → trees/${skill}.md"
      fi
    done

    # Scripts → match to skill by filename similarity, fallback to agent-memory
    if [[ -d "$utils_dir/scripts" ]]; then
      for f in "$utils_dir/scripts"/*; do
        [[ -f "$f" ]] || continue
        local sn; sn=$(basename "$f" | sed 's/\.[^.]*$//')
        local placed=false
        for skill in "${!skill_map[@]}"; do
          if echo "$sn" | grep -qi "$skill" || echo "$skill" | grep -qi "$sn"; then
            cp "$f" "$dst/skills/$skill/scripts/"
            echo -e "  ${G}🔧${NC} $(basename "$f") → skills/${skill}/scripts/"
            placed=true; break
          fi
        done
        if ! $placed; then
          mkdir -p ".claude/agent-memory/${name}/scripts"
          cp "$f" ".claude/agent-memory/${name}/scripts/"
          echo -e "  ${Y}⚠️${NC}  $(basename "$f") → agent-memory/${name}/scripts/ (no skill match)"
        fi
      done
    fi

    # Memory → agent-memory/
    if [[ -d "$utils_dir/memory" ]]; then
      mkdir -p ".claude/agent-memory/${name}"
      cp "$utils_dir/memory"/*.md ".claude/agent-memory/${name}/" 2>/dev/null || true
      echo -e "  ${G}📝${NC} → .claude/agent-memory/${name}/"
    fi
  fi

  echo -e "\n${B}Scaffold complete.${NC}"
  echo -e "${Y}Next: /convert-from-copilot ${agent_file}${NC}  in Claude Code to finish.\n"
}