{"meta":{"title":"플러그 인 디렉터리","intro":"플러그 인은 SDK 확장(기술, 후크, MCP 서버, 사용자 지정 에이전트 및 LSP 구성)을 단일 매니페스트 뒤에 번들로 묶는 디렉터리입니다. 플러그 인 디렉터리에서 SDK를 가리키면 플러그 인이 기여하는 모든 항목이 로드되므로 모든 호스트 애플리케이션에서 확장별 배선을 작성하지 않고도 재사용 가능한 기능 팩을 제공할 수 있습니다.","product":"GitHub Copilot","breadcrumbs":[{"href":"/ko/enterprise-cloud@latest/copilot","title":"GitHub Copilot"},{"href":"/ko/enterprise-cloud@latest/copilot/how-tos","title":"방법"},{"href":"/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk","title":"코필로트 SDK"},{"href":"/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/features","title":"기능"},{"href":"/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/features/plugin-directories","title":"플러그 인 디렉터리"}],"documentType":"article"},"body":"# 플러그 인 디렉터리\n\n플러그 인은 SDK 확장(기술, 후크, MCP 서버, 사용자 지정 에이전트 및 LSP 구성)을 단일 매니페스트 뒤에 번들로 묶는 디렉터리입니다. 플러그 인 디렉터리에서 SDK를 가리키면 플러그 인이 기여하는 모든 항목이 로드되므로 모든 호스트 애플리케이션에서 확장별 배선을 작성하지 않고도 재사용 가능한 기능 팩을 제공할 수 있습니다.\n\n<!-- markdownlint-disable GHD046 GHD005 -->\n\n<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->\n\n이 가이드에서는 플러그 인 폴더 레이아웃, 디렉터리에서 플러그 인을 로드하는 방법, 플러그 인 디렉터리를 사용하는 경우와 개별 확장을 등록하는 경우 및 플러그 인 집합을 결정적으로 만드는 방법을 설명합니다.\n\n## 플러그 인 디렉터리를 사용하는 경우\n\n다음을 수행하려는 경우 플러그 인 디렉터리를 사용합니다.\n\n* **기능 번들을** 하나의 단위로 배포합니다( 예: 기술이 있는 \"TypeScript 검토자\" 팩, `preToolUse` lint를 적용하는 후크 및 검토자를 실행하는 사용자 지정 에이전트).\n* **공급업체 기능은 리포지토리에 압축** 되므로 호스트 애플리케이션의 모든 클론이 동일한 확장을 결정적으로 로드합니다.\n* 마켓플레이스에 게시하기 전에 **로컬로 플러그 인을 개발**합니다.\n* 테스트를 위해 로컬 체크 아웃을 사용하여 마켓플레이스 설치 플러그 인을 **재정의하거나 확장**합니다.\n\n단일 MCP 서버, 단일 후크 또는 단일 사용자 지정 에이전트만 추가해야 하는 경우 SDK 구성(`mcpServers`, `hooks`, `customAgents`)을 통해 인라인으로 등록할 수 있습니다. 플러그 인 디렉터리를 함께 제공하는 세 개 이상의 관련 확장이 있으면 가장 유용합니다.\n\n## 플러그 인 폴더 레이아웃\n\nCopilot CLI는 각 플러그 인 디렉터리에서 `plugin.json` 매니페스트 또는 루트 수준 `SKILL.md` 검사합니다. 최소 플러그 인은 다음과 같습니다.\n\n```text\nmy-plugin/\n├── plugin.json              # manifest (required unless using SKILL.md only)\n├── SKILL.md                 # optional: top-level skill\n├── hooks.json               # optional: hooks config\n├── .mcp.json                # optional: MCP server config\n├── agents/                  # optional: custom agents (one .md file per agent)\n│   └── code-reviewer.md\n└── skills/                  # optional: additional skills\n    └── lint-fix/\n        └── SKILL.md\n```\n\n매니페스트는 `.github/plugin.json` 또는 `.github/plugin/plugin.json`에도 있을 수 있으므로, 플러그인이 기존 리포지토리 내부에 루트 레이아웃을 변경하지 않고도 위치할 수 있습니다. 각 하위 시스템(후크, MCP, LSP, 기술, 에이전트)에는 자체 로더가 있으며 선택 사항입니다. 플러그 인에는 기여하는 부분만 필요합니다.\n\n전체 매니페스트 스키마는 CLI의 `/plugin` 슬래시 명령에서 참조되는 런타임 설명서를 참조하세요.\n\n## SDK에서 플러그 인 디렉터리 로드\n\n플러그인 디렉터리는 SDK가 Copilot CLI를 생성할 때 `--plugin-dir <path>`를 전달하여 로드됩니다. 각 언어는 런타임 연결의 추가 인수 옵션을 통해 이를 노출합니다. 플래그를 반복하여 여러 플러그 인을 로드할 수 있습니다.\n\n<div class=\"ghd-codetabs\">\n<div class=\"ghd-codetab\" data-lang=\"typescript\" data-label=\"TypeScript\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">TypeScript</div>\n\n```typescript\nimport { CopilotClient, RuntimeConnection } from \"@github/copilot-sdk\";\n\nconst client = new CopilotClient({\n  connection: RuntimeConnection.forStdio({\n    args: [\n      \"--plugin-dir\", \"./plugins/code-reviewer\",\n      \"--plugin-dir\", \"./plugins/lint-fix\",\n    ],\n  }),\n});\n\nawait client.start();\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"python\" data-label=\"Python\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Python</div>\n\n<!-- docs-validate: wrap-async -->\n\n```python\nfrom copilot import CopilotClient, StdioRuntimeConnection\n\nclient = CopilotClient(\n    connection=StdioRuntimeConnection(\n        args=(\n            \"--plugin-dir\", \"./plugins/code-reviewer\",\n            \"--plugin-dir\", \"./plugins/lint-fix\",\n        ),\n    ),\n)\nawait client.start()\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"go\" data-label=\"Go\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Go</div>\n\n```golang\nclient := copilot.NewClient(&copilot.ClientOptions{\n    Connection: copilot.StdioConnection{\n        Args: []string{\n            \"--plugin-dir\", \"./plugins/code-reviewer\",\n            \"--plugin-dir\", \"./plugins/lint-fix\",\n        },\n    },\n})\nif err := client.Start(ctx); err != nil {\n    return err\n}\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"dotnet\" data-label=\".NET\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">.NET</div>\n\n```csharp\nusing GitHub.Copilot;\n\nawait using var client = new CopilotClient(new CopilotClientOptions\n{\n    Connection = RuntimeConnection.ForStdio(args: new[]\n    {\n        \"--plugin-dir\", \"./plugins/code-reviewer\",\n        \"--plugin-dir\", \"./plugins/lint-fix\",\n    }),\n});\n\nawait client.StartAsync();\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"java\" data-label=\"Java\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Java</div>\n\n```java\nvar options = new CopilotClientOptions()\n    .setCliArgs(new String[] {\n        \"--plugin-dir\", \"./plugins/code-reviewer\",\n        \"--plugin-dir\", \"./plugins/lint-fix\",\n    });\n\nvar client = new CopilotClient(options);\nclient.start().get();\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"rust\" data-label=\"Rust\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Rust</div>\n\n```rust\nuse github_copilot_sdk::{Client, ClientOptions};\n\nlet client = Client::start(\n    ClientOptions::new().with_extra_args([\n        \"--plugin-dir\", \"./plugins/code-reviewer\",\n        \"--plugin-dir\", \"./plugins/lint-fix\",\n    ]),\n)\n.await?;\n```\n\n</div>\n\n</div>\n\n> 위의 예제에서는 SDK가 CLI를 번들로 묶을 때 기본값인 stdio 런타임 연결을 사용합니다. URL(`forUri` / `ForUri`)을 통해 외부 런타임에 연결하는 경우, 시작할 때 장시간 실행되는 CLI 서버에 `--plugin-dir`를 전달해야 합니다. SDK는 자체적으로 생성하지 않은 런타임에는 `--plugin-dir`를 전달하지 않습니다.\n\n## 신뢰할 수 있는 호스트 번들 플러그 인 디렉터리\n\n자체 신뢰할 수 있는 플러그 인을 제공하는 애플리케이션은 클라이언트 시작 옵션으로 등록할 수 있습니다. SDK는 연결을 설정하고 프로토콜을 검증한 후, `start`가 반환되기 전이자 어떠한 세션도 생성되기 전에 완전한 ordered set을 전송합니다. 경로는 절대 경로여야 합니다. 옵션을 설정하지 않거나 비워 두면 RPC 호출이 발생하지 않습니다.\n\n각 SDK의 동등한 옵션은 다음과 같습니다.\n\n| SDK                 | 시작 옵션                                                 |\n| ------------------- | ----------------------------------------------------- |\n| Node.js/ TypeScript | `builtinPluginDirectories: string[]`                  |\n| Python              | `builtin_plugin_directories=[...]`                    |\n| Go                  | `BuiltinPluginDirectories: []string{...}`             |\n| .NET                | `BuiltinPluginDirectories = [...]`                    |\n| Java                | `.setBuiltinPluginDirectories(List.of(Path.of(...)))` |\n| 러스트                 | `.with_builtin_plugin_directories([...])`             |\n\n호스트 애플리케이션에서 번들로 묶고 제어하는 플러그 인에 대한 신뢰 경계입니다. 일반 플러그 인 디렉터리를 명시적으로 로드하기 위한 CLI 프로세스 시작 인수인 이 인수와는 다릅니다 `--plugin-dir`. 시작 옵션은 프로세스 인수로 전달되지 않고 JSON-RPC 통해 전송되므로 기존 런타임에 연결할 때도 작동합니다.\n\n## 플러그 인이 기여할 수 있는 사항\n\n플러그 인 디렉터리를 로드하면 해당 확장이 클라이언트에서 만든 모든 세션에 표시됩니다. 런타임은 플러그인이 제공하는 확장을 인라인으로 등록한 모든 확장과 병합합니다:\n\n| 플러그 인 기여                                | 세션에 다음과 같이 표시          |\n| --------------------------------------- | ---------------------- |\n| 기술(`SKILL.md`, `skills/*/SKILL.md`)     |                        |\n| `session.skills.list()`의 항목; 이름으로 주입 가능 |                        |\n| 사용자 지정 에이전트(`agents/*.md`)              |                        |\n| `task(agent_type=...)` 도구를 통해 전송 가능     |                        |\n| 고리 (`hooks.json`)                       | SDK를 통해 등록된 후크와 함께 실행됨 |\n| MCP 서버(`.mcp.json`)                     |                        |\n| `session.mcp.*`을 통해 액세스할 수 있는 도구 및 리소스  |                        |\n| LSP 서버(`.lsp.json`)                     |                        |\n| `session.lsp.initialize(...)`을 통해 초기화됨  |                        |\n\n플러그 인 에이전트는 [플릿 모드](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/features/fleet-mode)의 일류 하위 에이전트입니다. 부모 에이전트는 이를 디스패치 `agent_type`할 수 있으며 런타임은 다른 하위 에이전트와 마찬가지로 후크를 실행 `subagentStart` / `subagentStop` 합니다.\n\n## 플러그 인-dir 및 마켓플레이스 플러그 인\n\n런타임에는 플러그 인을 설치하는 두 가지 방법이 있으며, 둘 다 세션과 동일하게 표시됩니다.\n\n* **Marketplace/직접 리포지토리 플러그 인** 은 CLI의 `/plugin` 슬래시 명령 또는 기본 `installedPlugins` 사용자 설정을 통해 영구적으로 설치됩니다. 그것들은 *앰비언트*이며, 동일한 사용자 구성을 사용하는 모든 세션에서 이를 인식할 수 있고 플러그인 검색 규칙의 적용을 받습니다.\n* **`--plugin-dir` 플러그 인** 은 *명시적이고 임시적입니다* . 해당 플래그를 사용하여 시작한 CLI 프로세스에만 적용됩니다. 이들은 자동 검색보다 우선하며, 동일한 캐시 경로를 가진 마켓플레이스 항목과는 중복이 제거되므로 양쪽에서 모두 참조하더라도 동일한 플러그인이 두 번 로드되지 않습니다.\n\nSDK 기반 애플리케이션의 경우 일반적으로 `--plugin-dir`가 올바른 선택입니다. 애플리케이션은 컴퓨터별 사용자 상태에 의존하지 않고 플러그인 세트를 자체적으로 제어할 수 있기 때문입니다.\n\n## 플러그인 집합을 결정론적으로 만들기\n\n호스트 머신에 다른 플러그인(마켓플레이스 또는 개인용)이 설치되어 있을 수 있는 경우, 자동 플러그인 검색을 억제하려면 런타임 환경에서 `COPILOT_PLUGIN_DIR_ONLY=true`를 설정하세요.\n`--plugin-dir`를 통해 전달한 디렉터리만 로드됩니다.\n\n<details open>\n<summary>\n<strong>Node.js/ TypeScript</strong></summary>\n\n```typescript\nprocess.env.COPILOT_PLUGIN_DIR_ONLY = \"true\";\n\nconst client = new CopilotClient({\n  connection: RuntimeConnection.forStdio({\n    args: [\"--plugin-dir\", \"./plugins/code-reviewer\"],\n  }),\n});\nawait client.start();\n```\n\n</details>\n\nCI, 헤드리스 서버 배포 및 호스트의 사용자 구성에 의존하지 않는 재현 가능한 플러그 인 집합을 원하는 모든 위치에서 사용합니다.\n\n## 로드된 플러그 인 검사\n\n세션이 만들어지면 활성 플러그 인을 나열하여 디렉터리가 올바르게 선택되었는지 확인합니다.\n\n<details open>\n<summary>\n<strong>Node.js/ TypeScript</strong></summary>\n\n```typescript\nconst plugins = await session.rpc.plugins.list();\nfor (const plugin of plugins.plugins) {\n  console.log(`${plugin.name} (${plugin.enabled ? \"enabled\" : \"disabled\"})`);\n}\n```\n\n</details>\n\n통해 로드된 `--plugin-dir` 플러그 인은 제공한 디렉터리로 설정된 캐시 경로와 함께 이 목록에 표시됩니다. Marketplace에서 설치된 항목에는 해당 레지스트리 출처 태그가 붙습니다.\n\n## Troubleshooting\n\n* **\"dir<에 >plugin.json 또는 SKILL.md 없습니다.\"** - 디렉터리가 존재하지만 플러그 인으로 한정되지 않습니다.\n  `plugin.json` 루트(또는 아래`.github/`)에 매니페스트를 추가하거나 최상위 수준을 `SKILL.md`포함합니다.\n* **플러그 인이 로드되었지만 에이전트/기술이 표시되지 않음** - 플러그 인 매니페스트가 기여하는 에이전트/기술을 선언하는지 확인하거나 암시적 레이아웃(`agents/*.md`, `skills/*/SKILL.md`)을 사용합니다. 그런 다음 다시 시작하지 않고 변경 내용을 선택하도록 호출 `session.rpc.skills.reload()` 합니다.\n* **중복 후크 실행** — 런타임은 `cache_path`를 통해 중복을 제거하지만, 동일한 디렉터리가 마켓플레이스 설치와 `--plugin-dir` 둘 다로 참조되는 경우에만 그렇습니다. 서로 다른 두 디렉터리에 동일한 플러그 인이 포함되어 있으면 둘 다 로드됩니다. 하나를 제거하거나 `COPILOT_PLUGIN_DIR_ONLY=true`를 사용하세요.\n* **`--plugin-dir` 는 외부 런타임에 연결할 때 무시됩니다** . SDK는 CLI 자체를 생성할 때만 추가 인수를 전달합니다. 외부 런타임(`forUri`/`ForUri`)의 경우 런타임 서버를 시작하는 명령줄을 전달 `--plugin-dir` 합니다.\n\n## Related\n\n* [사용자 정의 에이전트 및 하위 에이전트 오케스트레이션](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/features/custom-agents): 플러그인의 `agents/` 폴더에 포함되는 에이전트를 작성합니다.\n* [사용자 지정 기술](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/features/skills): 파일이 로드되는 방법 `SKILL.md` 및 기술 계층 순서 규칙입니다.\n* [후크를 사용한 작업](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/features/hooks): 플러그인에 의해 정의된 후크는 SDK에 등록된 후크와 함께 실행됩니다.\n* [GitHub Copilot SDK에서 MCP 서버 사용](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/features/mcp): 플러그 인 제공 MCP 서버는 인라인 등록과 동일한 방식으로 통합됩니다.\n* [플릿 모드](/ko/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/features/fleet-mode): 플러그 인 제공 에이전트는 하위 에이전트로 디스패치할 수 있습니다."}