Copilot SDK Skills and skillDirectories Configuration: A Complete Guide

TLDR: Copilot SDK skills are reusable prompt modules stored in subdirectories containing SKILL.md files, configured via the skillDirectories option on SessionConfig, and can be selectively disabled using disabledSkills (or language-specific equivalents).

The GitHub Copilot SDK extends AI capabilities through modular skills that package domain-specific expertise. Understanding how to configure skillDirectories and manage skill loading is essential for building production AI workflows. This guide explains the complete configuration schema, loading behavior, and implementation details across all supported languages based on the github/copilot-sdk source code.

What Are Copilot SDK Skills?

Skills are reusable prompt modules that extend Copilot's behavior through declarative instructions. Each skill resides in its own subdirectory within a parent skills folder and must contain a SKILL.md file. According to the source code in docs/features/skills.md, the full markdown content of this file is injected into the session context when the skill is loaded.

The optional YAML front-matter inside SKILL.md defines two key metadata fields:

  • name: The identifier used for disabling the skill
  • description: Human-readable explanation of the skill's purpose

Configuring skillDirectories Discovery

The SDK discovers skills via the skillDirectories configuration option on SessionConfig. This option accepts an array of paths pointing to parent directories (e.g., ./skills). Every immediate subdirectory containing a SKILL.md file is treated as a distinct skill.

When a session is created, the SDK eagerly loads the full markdown content of each discovered skill. This preloading ensures the LLM has immediate access to skill instructions without requiring additional tool calls during execution.

Language-Specific Configuration

The Copilot SDK maintains consistent configuration semantics across languages with idiomatic naming conventions:

Node.js / TypeScript

  • Directory field: skillDirectories: string[]
  • Disable field: disabledSkills: string[]

Python

  • Directory field: skill_directories: list[str]
  • Disable field: disabled_skills: list[str]

Go

  • Directory field: SkillDirectories: []string
  • Disable field: DisabledSkills: []string

.NET (C#)

  • Directory field: SkillDirectories: List<string>
  • Disable field: DisabledSkills: List<string>

This schema is documented in docs/features/skills.md lines 43-52.

Disabling Skills with disabledSkills

To exclude specific skills from a session, add their identifiers to the disabledSkills array (or the language-specific equivalent). The identifier matches the name field defined in the skill's SKILL.md YAML front-matter.

This approach removes the skill's instructions from the session context while leaving the directory structure and other skills intact. It provides fine-grained control without requiring changes to the filesystem layout.

Skill Loading Behavior and Inheritance

Skills are opt-in by design. They are only loaded when the skillDirectories option is explicitly provided during session creation.

Sub-agents do not inherit skills from their parent sessions unless they explicitly list the same directories in their own configuration. This isolation prevents context leakage between parent and child agent instances, as implemented in docs/features/skills.md lines 70-86.

Implementation Examples by Language

Node.js / TypeScript

import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient();
const session = await client.createSession({
  model: "gpt-5.4",
  skillDirectories: ["./skills/code-review", "./skills/documentation"],
  disabledSkills: ["experimental-feature"],
  onPermissionRequest: async () => ({ kind: "approve-once" }),
});

await session.sendAndWait({ prompt: "Review this PR for security issues" });

Python

from copilot import CopilotClient, PermissionDecisionApproveOnce

client = CopilotClient()
await client.start()

session = await client.create_session(
    model="gpt-5.4",
    skill_directories=["./skills/code-review", "./skills/documentation"],
    disabled_skills=["experimental-feature"],
    on_permission_request=lambda req, inv: PermissionDecisionApproveOnce(),
)

await session.send_and_wait("Review this PR for security issues")
await client.stop()

Go

ctx := context.Background()
client := copilot.NewClient(nil)
if err := client.Start(ctx); err != nil { log.Fatal(err) }
defer client.Stop()

session, err := client.CreateSession(ctx, &copilot.SessionConfig{
    Model: "gpt-5.4",
    SkillDirectories: []string{"./skills/code-review", "./skills/documentation"},
    DisabledSkills:   []string{"experimental-feature"},
    OnPermissionRequest: func(req copilot.PermissionRequest, inv copilot.PermissionInvocation) (rpc.PermissionDecision, error) {
        return &rpc.PermissionDecisionApproveOnce{}, nil
    },
})
if err != nil { log.Fatal(err) }

_, err = session.SendAndWait(ctx, copilot.MessageOptions{
    Prompt: "Review this PR for security issues",
})
if err != nil { log.Fatal(err) }

.NET (C#)

await using var client = new CopilotClient();
await using var session = await client.CreateSessionAsync(new SessionConfig {
    Model = "gpt-5.4",
    SkillDirectories = new List<string> { "./skills/code-review", "./skills/documentation" },
    DisabledSkills = new List<string> { "experimental-feature" },
    OnPermissionRequest = (req, inv) => Task.FromResult(PermissionDecision.ApproveOnce()),
});

await session.SendAndWaitAsync(new MessageOptions {
    Prompt = "Review this PR for security issues"
});

Summary

  • Skills are modular prompt modules requiring a subdirectory with a SKILL.md file and optional YAML front-matter defining name and description
  • Configuration: Use skillDirectories (or skill_directories/SkillDirectories) on SessionConfig to specify parent directories containing skill subfolders
  • Disabling: Add skill identifiers to disabledSkills (or language equivalent) to exclude specific capabilities without removing files
  • Loading: Skills are eagerly preloaded at session start and are opt-in only; sub-agents must explicitly configure their own skill directories
  • Cross-language support: Available in Node.js/TypeScript, Python, Go, and .NET with consistent behavior and idiomatic naming conventions

Frequently Asked Questions

What file structure is required for a Copilot SDK skill?

A valid skill requires a dedicated subdirectory containing a SKILL.md file. According to docs/features/skills.md, the SDK treats every immediate subdirectory containing this file as a distinct skill. The SKILL.md file must contain the prompt instructions to be injected into the session context, with optional YAML front-matter at the top defining the skill's name and description.

Do sub-agents automatically inherit skills from parent sessions?

No. As documented in docs/features/skills.md lines 70-86, sub-agents do not inherit skills from their parent sessions unless they explicitly list the same skillDirectories in their own configuration. This design ensures isolation between agent contexts and prevents unintended capability leakage from parent to child agents.

How do I disable a specific skill without deleting it from the filesystem?

Add the skill's identifier—defined in the YAML front-matter name field of its SKILL.md—to the disabledSkills array (or snake_case/camelCase equivalent for your language). This removes the skill's instructions from the active session while preserving the directory structure, allowing you to toggle capabilities without changing the underlying file layout.

Is there a way to auto-discover skill directories without explicit configuration?

Yes. According to CHANGELOG.md, the Copilot SDK supports the enableConfigDiscovery flag for automatic skill directory detection. However, explicit skillDirectories configuration remains the recommended approach for production environments requiring deterministic behavior and explicit control over loaded capabilities.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →