---
title: 플러그인
description: OpenCode를 확장하기 위해 자신만의 플러그인을 작성하세요.
---

플러그인은 다양한 이벤트와 사용자 정의 행동으로 후킹하여 opencode를 확장 할 수 있습니다. 플러그인을 사용하여 새로운 기능을 추가하거나, 외부 서비스와 통합하거나, opencode의 기본 동작을 수정할 수 있습니다.

예를 들어, 커뮤니티에 의해 생성 된 [plugins](/docs/ecosystem#plugins)를 확인하십시오.

---

## 플러그인 사용

플러그인을 로드하는 두 가지 방법이 있습니다.

---

### 로컬 파일에서

플러그인 디렉토리에 JavaScript 또는 TypeScript 파일을 배치합니다.

- `.opencode/plugins/` - 프로젝트 레벨 플러그인
- `~/.config/opencode/plugins/` - 글로벌 플러그인

이 디렉토리의 파일은 시작 시 자동으로 로드됩니다.

---

### npm에서

config 파일에 npm 패키지를 지정합니다.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"]
}
```

일반 패키지 및 스코프 npm 패키지 모두 지원됩니다.

[ecosystem](/docs/ecosystem#plugins)에서 사용할 수 있는 플러그인을 찾아보세요.

---

### 플러그인이 설치되는 방법

**npm 플러그인**은 시작시 Bun을 사용하여 자동으로 설치됩니다. 패키지와 그 의존성은 `~/.cache/opencode/node_modules/`에 캐시됩니다.

**로컬 플러그인**은 플러그인 디렉토리에서 직접 로드됩니다. 외부 패키지를 사용하려면 구성 디렉토리 내에 `package.json`을 작성해야 하거나([의존성](#의존성) 참조), 플러그인을 npm에 게시하고 [config에 추가](/docs/config#plugins)해야 합니다.

---

### 로드 순서

플러그인은 모든 소스에서 로드되며 모든 후크는 순서대로 실행됩니다. 로드 순서는 다음과 같습니다:

1. 글로벌 구성 (`~/.config/opencode/opencode.json`)
2. 프로젝트 구성 (`opencode.json`)
3. 글로벌 플러그인 디렉토리 (`~/.config/opencode/plugins/`)
4. 프로젝트 플러그인 디렉토리 (`.opencode/plugins/`)

중복된 이름과 버전의 npm 패키지는 한 번만 로드됩니다. 하지만 로컬 플러그인과 npm 플러그인의 이름이 비슷하더라도 둘 다 별도로 로드됩니다.

---

## 플러그인 만들기

플러그인은 하나 이상의 플러그인 함수를 내보내는 **JavaScript/TypeScript 모듈**입니다. 각 함수는 context 객체를 수신하고 hooks 객체를 반환합니다.

---

### 의존성

로컬 플러그인 및 사용자 정의 도구는 외부 npm 패키지를 사용할 수 있습니다. config 디렉토리에 `package.json`을 추가하고 필요한 의존성을 명시하십시오.

```json title=".opencode/package.json"
{
  "dependencies": {
    "shescape": "^2.1.0"
  }
}
```

opencode는 시작 시 `bun install`을 실행하여 이를 설치합니다. 이후 플러그인 및 도구에서 가져올 수 있습니다.

```ts title=".opencode/plugins/my-plugin.ts"
import { escape } from "shescape"

export const MyPlugin = async (ctx) => {
  return {
    "tool.execute.before": async (input, output) => {
      if (input.tool === "bash") {
        output.args.command = escape(output.args.command)
      }
    },
  }
}
```

---

### 기본 구조

```js title=".opencode/plugins/example.js"
export const MyPlugin = async ({ project, client, $, directory, worktree }) => {
  console.log("Plugin initialized!")

  return {
    // Hook implementations go here
  }
}
```

플러그인 함수가 받는 인자:

- `project`: 현재 프로젝트 정보.
- `directory`: 현재 작업 디렉토리.
- `worktree`: git worktree 경로.
- `client`: AI와 상호 작용을 위한 opencode SDK 클라이언트.
- `$`: 명령어를 실행하기 위한 Bun의 [shell API](https://bun.com/docs/runtime/shell).

---

### TypeScript 지원

TypeScript 플러그인의 경우 플러그인 패키지에서 타입을 가져올 수 있습니다.

```ts title="my-plugin.ts" {1}
import type { Plugin } from "@opencode-ai/plugin"

export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => {
  return {
    // Type-safe hook implementations
  }
}
```

---

### 이벤트

플러그인은 아래 예제 섹션에서 볼 수 있듯이 이벤트를 구독할 수 있습니다. 사용 가능한 이벤트 목록은 다음과 같습니다.

#### 명령어 이벤트

- `command.executed`

#### 파일 이벤트

- `file.edited`
- `file.watcher.updated`

#### 설치 이벤트

- `installation.updated`

#### LSP 이벤트

- `lsp.client.diagnostics`
- `lsp.updated`

#### 메시지 이벤트

- `message.part.removed`
- `message.part.updated`
- `message.removed`
- `message.updated`

#### 권한 이벤트

- `permission.asked`
- `permission.replied`

#### 서버 이벤트

- `server.connected`

#### 세션 이벤트

- `session.created`
- `session.compacted`
- `session.deleted`
- `session.diff`
- `session.error`
- `session.idle`
- `session.status`
- `session.updated`

#### Todo 이벤트

- `todo.updated`

#### 셸 이벤트

- `shell.env`

#### 도구 이벤트

- `tool.execute.after`
- `tool.execute.before`

#### TUI 이벤트

- `tui.prompt.append`
- `tui.command.execute`
- `tui.toast.show`

---

## 예제

opencode를 확장하기 위해 사용할 수 있는 플러그인 예제입니다.

---

### 알림 보내기

특정 이벤트가 발생할 때 알림을 전송:

```js title=".opencode/plugins/notification.js"
export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => {
  return {
    event: async ({ event }) => {
      // Send notification on session completion
      if (event.type === "session.idle") {
        await $`osascript -e 'display notification "Session completed!" with title "opencode"'`
      }
    },
  }
}
```

macOS에서 AppleScript를 실행하기 위해 `osascript`를 사용하고 있습니다. 여기서는 알림을 보내는 데 사용합니다.

:::note
opencode 데스크톱 앱을 사용하는 경우 응답이 준비되어 있거나 세션 오류가 있을 때 시스템 알림을 자동으로 보낼 수 있습니다.
:::

---

### .env 보호

opencode가 `.env` 파일을 읽지 못하도록 방지:

```javascript title=".opencode/plugins/env-protection.js"
export const EnvProtection = async ({ project, client, $, directory, worktree }) => {
  return {
    "tool.execute.before": async (input, output) => {
      if (input.tool === "read" && output.args.filePath.includes(".env")) {
        throw new Error("Do not read .env files")
      }
    },
  }
}
```

---

### Inject 환경 변수

모든 shell 실행(AI 도구 및 사용자 terminal)에 환경 변수 주입:

```javascript title=".opencode/plugins/inject-env.js"
export const InjectEnvPlugin = async () => {
  return {
    "shell.env": async (input, output) => {
      output.env.MY_API_KEY = "secret"
      output.env.PROJECT_ROOT = input.cwd
    },
  }
}
```

---

### 사용자 정의 도구

플러그인은 opencode에 사용자 정의 도구를 추가할 수 있습니다:

```ts title=".opencode/plugins/custom-tools.ts"
import { type Plugin, tool } from "@opencode-ai/plugin"

export const CustomToolsPlugin: Plugin = async (ctx) => {
  return {
    tool: {
      mytool: tool({
        description: "This is a custom tool",
        args: {
          foo: tool.schema.string(),
        },
        async execute(args, context) {
          const { directory, worktree } = context
          return `Hello ${args.foo} from ${directory} (worktree: ${worktree})`
        },
      }),
    },
  }
}
```

`tool` helper는 opencode가 호출할 수 있는 사용자 정의 도구를 만듭니다. Zod 스키마 함수를 받고 다음을 포함하는 도구 정의를 반환합니다:

- `description`: 도구가 하는 일
- `args`: 도구의 인수에 대한 Zod 스키마
- `execute`: 도구가 호출될 때 실행되는 함수

사용자 정의 도구는 내장 도구와 함께 opencode에서 사용할 수 있습니다.

:::note
플러그인 도구가 내장 도구와 같은 이름을 사용하면 플러그인 도구가 우선순위를 갖습니다.
:::

---

### 로깅

구조화된 로깅을 위해 `console.log` 대신 `client.app.log()`를 사용하십시오:

```ts title=".opencode/plugins/my-plugin.ts"
export const MyPlugin = async ({ client }) => {
  await client.app.log({
    body: {
      service: "my-plugin",
      level: "info",
      message: "Plugin initialized",
      extra: { foo: "bar" },
    },
  })
}
```

레벨: `debug`, `info`, `warn`, `error`. [SDK 문서](https://opencode.ai/docs/sdk)를 참고하세요.

---

### Compaction 훅

세션이 압축될 때 포함되는 컨텍스트를 사용자 지정할 수 있습니다:

```ts title=".opencode/plugins/compaction.ts"
import type { Plugin } from "@opencode-ai/plugin"

export const CompactionPlugin: Plugin = async (ctx) => {
  return {
    "experimental.session.compacting": async (input, output) => {
      // Inject additional context into the compaction prompt
      output.context.push(`
## Custom Context

Include any state that should persist across compaction:
- Current task status
- Important decisions made
- Files being actively worked on
`)
    },
  }
}
```

`experimental.session.compacting` 훅은 LLM이 연속 요약을 생성하기 전에 실행됩니다. 기본 압축 프롬프트가 놓칠 수 있는 도메인별 컨텍스트를 주입하는 데 사용하세요.

또한 `output.prompt`를 설정하여 압축 프롬프트를 완전히 대체할 수도 있습니다:

```ts title=".opencode/plugins/custom-compaction.ts"
import type { Plugin } from "@opencode-ai/plugin"

export const CustomCompactionPlugin: Plugin = async (ctx) => {
  return {
    "experimental.session.compacting": async (input, output) => {
      // Replace the entire compaction prompt
      output.prompt = `
You are generating a continuation prompt for a multi-agent swarm session.

Summarize:
1. The current task and its status
2. Which files are being modified and by whom
3. Any blockers or dependencies between agents
4. The next steps to complete the work

Format as a structured prompt that a new agent can use to resume work.
`
    },
  }
}
```

`output.prompt`가 설정되면 기본 압축 프롬프트를 완전히 대체합니다. 이 경우 `output.context` 배열은 무시됩니다.
