Skip to main content

사용자 지정 기술

스킬은 Copilot의 기능을 확장하는 재사용 가능한 프롬프트 모듈입니다. 디렉터리에서 기술을 로드하여 특정 도메인 또는 워크플로에 대해 Copilot 특수한 기능을 제공합니다.

Overview

스킬은 Copilot에 지침을 제공하는 Markdown 문서인 SKILL.md 파일을 포함하는 이름이 지정된 디렉터리입니다. 로드되면 기술의 콘텐츠가 세션 컨텍스트에 삽입됩니다.

기술을 통해 다음을 수행할 수 있습니다.

  • 재사용 가능한 모듈로 도메인 전문 지식 패키지
  • 프로젝트 간에 특수한 동작 공유
  • 복잡한 에이전트 구성 정리
  • 세션당 기능 사용/사용 안 함

기술 불러오기

세션을 만들 때 기술을 포함하는 디렉터리를 지정합니다.

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

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

// Copilot now has access to skills in those directories
await session.sendAndWait({ prompt: "Review this code for security issues" });
Python
from copilot import CopilotClient, PermissionDecisionApproveOnce

async def main():
    client = CopilotClient()
    await client.start()

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

    # Copilot now has access to skills in those directories
    await session.send_and_wait("Review this code for security issues")

    await client.stop()
Go
package main

import (
    "context"
    "log"
    copilot "github.com/github/copilot-sdk/go"
    "github.com/github/copilot-sdk/go/rpc"
)

func main() {
    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-4.1",
        SkillDirectories: []string{
            "./skills/code-review",
            "./skills/documentation",
        },
        OnPermissionRequest: func(req copilot.PermissionRequest, inv copilot.PermissionInvocation) (rpc.PermissionDecision, error) {
            return &rpc.PermissionDecisionApproveOnce{}, nil
        },
    })
    if err != nil {
        log.Fatal(err)
    }

    // Copilot now has access to skills in those directories
    _, err = session.SendAndWait(ctx, copilot.MessageOptions{
        Prompt: "Review this code for security issues",
    })
    if err != nil {
        log.Fatal(err)
    }
}
.NET
using GitHub.Copilot;
using GitHub.Copilot.Rpc;

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

// Copilot now has access to skills in those directories
await session.SendAndWaitAsync(new MessageOptions
{
    Prompt = "Review this code for security issues"
});
Java
import com.github.copilot.CopilotClient;
import com.github.copilot.rpc.*;
import java.util.List;

try (var client = new CopilotClient()) {
    client.start().get();

    var session = client.createSession(
        new SessionConfig()
            .setModel("gpt-4.1")
            .setSkillDirectories(List.of(
                "./skills/code-review",
                "./skills/documentation"
            ))
            .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
    ).get();

    // Copilot now has access to skills in those directories
    session.sendAndWait(new MessageOptions()
        .setPrompt("Review this code for security issues")
    ).get();
}

기능 비활성화

다른 사람을 활성 상태로 유지하면서 특정 기술을 사용하지 않도록 설정합니다.

TypeScript
const session = await client.createSession({
    skillDirectories: ["./skills"],
    disabledSkills: ["experimental-feature", "deprecated-tool"],
});
Python
from copilot.session import PermissionHandler

session = await client.create_session(
    on_permission_request=PermissionHandler.approve_all,
    skill_directories=["./skills"],
    disabled_skills=["experimental-feature", "deprecated-tool"],
)
Go
package main

import (
    "context"
    copilot "github.com/github/copilot-sdk/go"
    "github.com/github/copilot-sdk/go/rpc"
)

func main() {
    ctx := context.Background()
    client := copilot.NewClient(nil)

    session, _ := client.CreateSession(ctx, &copilot.SessionConfig{
        SkillDirectories: []string{"./skills"},
        DisabledSkills:   []string{"experimental-feature", "deprecated-tool"},
        OnPermissionRequest: func(req copilot.PermissionRequest, inv copilot.PermissionInvocation) (rpc.PermissionDecision, error) {
            return &rpc.PermissionDecisionApproveOnce{}, nil
        },
    })
    _ = session
}
session, _ := client.CreateSession(context.Background(), &copilot.SessionConfig{
    SkillDirectories: []string{"./skills"},
    DisabledSkills:   []string{"experimental-feature", "deprecated-tool"},
})
.NET
using GitHub.Copilot;
using GitHub.Copilot.Rpc;

public static class SkillsExample
{
    public static async Task Main()
    {
        await using var client = new CopilotClient();

        var session = await client.CreateSessionAsync(new SessionConfig
        {
            SkillDirectories = new List<string> { "./skills" },
            DisabledSkills = new List<string> { "experimental-feature", "deprecated-tool" },
            OnPermissionRequest = (req, inv) =>
                Task.FromResult(PermissionDecision.ApproveOnce()),
        });
    }
}
var session = await client.CreateSessionAsync(new SessionConfig
{
    SkillDirectories = new List<string> { "./skills" },
    DisabledSkills = new List<string> { "experimental-feature", "deprecated-tool" },
});
Java
import com.github.copilot.rpc.*;
import java.util.List;

var session = client.createSession(
    new SessionConfig()
        .setSkillDirectories(List.of("./skills"))
        .setDisabledSkills(List.of("experimental-feature", "deprecated-tool"))
        .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
).get();

기술 디렉터리 구조

각 기술은 파일을 포함하는 명명된 하위 디렉터리입니다.SKILL.md

skills/
├── code-review/
│   └── SKILL.md
└── documentation/
    └── SKILL.md

skillDirectories 옵션은 부모 디렉터리(예: ./skills)를 가리킵니다. CLI는 즉시 하위 디렉터리의 모든 SKILL.md 파일을 검색합니다.

SKILL.md 형식

SKILL.md 파일은 선택적 YAML 프런트매터가 있는 markdown 문서입니다.

---
name: code-review
description: Specialized code review capabilities
---

# Code Review Guidelines

When reviewing code, always check for:

1. **Security vulnerabilities** - SQL injection, XSS, etc.
2. **Performance issues** - N+1 queries, memory leaks
3. **Code style** - Consistent formatting, naming conventions
4. **Test coverage** - Are critical paths tested?

Provide specific line-number references and suggested fixes.

프런트매터 필드:

  • name: 기술의 식별자입니다(disabledSkills와 함께 사용하여 이를 선택적으로 비활성화하는 데 사용됨). 생략하면 디렉터리 이름이 사용됩니다.
  • description: 기술이 수행하는 일에 대한 간단한 설명입니다.

markdown 본문에는 기술이 로드될 때 세션 컨텍스트에 삽입되는 지침이 포함되어 있습니다.

구성 옵션

SessionConfig 기술 필드

언어FieldTypeDescription
Node.jsskillDirectoriesstring[]기술을 로드하기 위한 디렉터리
Node.jsdisabledSkillsstring[]사용하지 않도록 설정하는 기술
Pythonskill_directorieslist[str]기술을 로드하기 위한 디렉터리
Pythondisabled_skillslist[str]사용하지 않도록 설정하는 기술
GoSkillDirectories[]string기술을 로드하기 위한 디렉터리
GoDisabledSkills[]string사용하지 않도록 설정하는 기술
.NETSkillDirectoriesList<string>기술을 로드하기 위한 디렉터리
.NETDisabledSkillsList<string>사용하지 않도록 설정하는 기술

모범 사례

  1. 도메인별로 구성 - 관련 기술 그룹화(예: skills/security/, skills/testing/)

  2. 프런트매터 사용 - 명확성을 위해 YAML 프런트매터 포함 namedescription 포함

  3. 문서 종속성 - 기술에 필요한 도구 또는 MCP 서버에 유의하세요.

  4. 격리된 기술 테스트 - 기술을 결합하기 전에 기술 작동 확인

  5. 상대 경로 사용 - 환경에서 기술을 이식 가능한 상태로 유지

다른 기능과 결합

기술 + 사용자 지정 에이전트

에이전트 skills 필드에 나열된 기술은 즉시 미리 로드됩니다. 시작 시 에이전트의 컨텍스트에 전체 콘텐츠가 삽입되므로 에이전트는 기술 도구를 호출할 필요 없이 즉시 기술 지침에 액세스할 수 있습니다. 스킬 이름은 세션 수준의 skillDirectories에서 조회됩니다.

const session = await client.createSession({
    skillDirectories: ["./skills/security"],
    customAgents: [{
        name: "security-auditor",
        description: "Security-focused code reviewer",
        prompt: "Focus on OWASP Top 10 vulnerabilities",
        skills: ["security-scan", "dependency-check"],
    }],
    onPermissionRequest: async () => ({ kind: "approve-once" }),
});

참고

스킬은 옵트인 방식이므로 skills가 생략되면 스킬 콘텐츠가 주입되지 않습니다. 하위 에이전트는 부모로부터 기술을 상속하지 않습니다. 에이전트별로 명시적으로 나열해야 합니다.

기술 + MCP 서버

기술은 MCP 서버 기능을 보완할 수 있습니다.

const session = await client.createSession({
    skillDirectories: ["./skills/database"],
    mcpServers: {
        postgres: {
            type: "local",
            command: "npx",
            args: ["-y", "@modelcontextprotocol/server-postgres"],
            tools: ["*"],
        },
    },
    onPermissionRequest: async () => ({ kind: "approve-once" }),
});

Troubleshooting

기술이 로드되지 않음

  1. 경로 확인 - 기술 디렉터리 경로가 올바르고 파일이 있는 하위 디렉터리가 SKILL.md 포함되어 있는지 확인합니다.
  2. 권한 확인 - SDK가 디렉터리를 읽을 수 있는지 확인
  3. SKILL.md 형식 확인 - markdown이 올바른 형식이고 YAML 프런트매터가 유효한 구문을 사용하는지 확인합니다.
  4. 디버그 로깅 활성화 - 스킬 로딩 로그를 보려면 logLevel: "debug"으로 설정

기술 충돌

여러 기술이 충돌하는 지침을 제공하는 경우:

  • disabledSkills를 사용하여 충돌하는 기술을 제외하십시오.
  • 겹치지 않도록 기술 디렉터리 다시 구성

참고하십시오