# Technical Documentation: anomalyco/opencode

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/anomalyco/opencode)

### Overview (README.md)

<p align="center">
  <a href="https://opencode.ai">
    <picture>
      <source srcset="packages/console/app/src/asset/logo-ornate-dark.svg" media="(prefers-color-scheme: dark)">
      <source srcset="packages/console/app/src/asset/logo-ornate-light.svg" media="(prefers-color-scheme: light)">
      <img src="packages/console/app/src/asset/logo-ornate-light.svg" alt="OpenCode logo">
    </picture>
  </a>
</p>
<p align="center">The open source AI coding agent.</p>
<p align="center">
  <a href="https://opencode.ai/discord"><img alt="Discord" src="https://img.shields.io/discord/1391832426048651334?style=flat-square&label=discord" /></a>
  <a href="https://www.npmjs.com/package/@opencode/cli"><img alt="npm" src="https://img.shields.io/npm/v/@opencode/cli?style=flat-square" /></a>
  <a href="https://github.com/anomalyco/opencode/actions/workflows/publish.yml"><img alt="Build status" src="https://img.shields.io/github/actions/workflow/status/anomalyco/opencode/publish.yml?style=flat-square&branch=dev" /></a>
</p>

<p align="center">
  <a href="README.md">English</a> |
  <a href="README.zh.md">简体中文</a> |
  <a href="README.zht.md">繁體中文</a> |
  <a href="README.ko.md">한국어</a> |
  <a href="README.de.md">Deutsch</a> |
  <a href="README.es.md">Español</a> |
  <a href="README.fr.md">Français</a> |
  <a href="README.it.md">Italiano</a> |
  <a href="README.da.md">Dansk</a> |
  <a href="README.ja.md">日本語</a> |
  <a href="README.pl.md">Polski</a> |
  <a href="README.ru.md">Русский</a> |
  <a href="README.bs.md">Bosanski</a> |
  <a href="README.ar.md">العربية</a> |
  <a href="README.no.md">Norsk</a> |
  <a href="README.br.md">Português (Brasil)</a> |
  <a href="README.th.md">ไทย</a> |
  <a href="README.tr.md">Türkçe</a> |
  <a href="README.uk.md">Українська</a> |
  <a href="README.bn.md">বাংলা</a> |
  <a href="README.gr.md">Ελληνικά</a> |
  <a href="README.vi.md">Tiếng Việt</a>
</p>

[](https://opencode.ai)

---

### Installation

```bash
# YOLO
curl -fsSL https://opencode.ai/v2/install | bash

# Package managers
npm i @opencode/cli@latest      # or bun/pnpm/yarn
brew install anomalyco/tap/opencode-v2 # macOS and Linux (recommended, always up to date)
brew install opencode              # macOS and Linux (official brew formula, updated less)
sudo pacman -S opencode            # Arch Linux (Stable)
paru -S opencode-beta              # Arch Linux (Latest from AUR)
mise use -g opencode               # Any OS
nix run github:anomalyco/opencode  # Nix
```

> [!TIP]
> Remove versions older than 0.1.x before installing.

### Desktop App (BETA)

OpenCode is also available as a desktop application. Download it from [opencode.ai/download](https://opencode.ai/download).

| Platform              | Download                           |
| --------------------- | ---------------------------------- |
| macOS (Apple Silicon) | `opencode-desktop-mac-arm64.dmg`   |
| macOS (Intel)         | `opencode-desktop-mac-x64.dmg`     |
| Windows               | `opencode-desktop-win-x64.exe`     |
| Linux                 | `.deb`, `.rpm`, or `.AppImage`     |

```bash
# macOS (Homebrew)
brew install --cask opencode-desktop
```

#### Installation Directory

The install script respects the following priority order for the installation path:

1. `$OPENCODE_INSTALL_DIR` - Custom installation directory
2. `$XDG_BIN_DIR` - XDG Base Directory Specification compliant path
3. `$HOME/bin` - Standard user binary directory (if it exists or can be created)
4. `$HOME/.opencode/bin` - Default fallback

```bash
# Examples
OPENCODE_INSTALL_DIR=/usr/local/bin curl -fsSL https://opencode.ai/v2/install | bash
XDG_BIN_DIR=$HOME/.local/bin curl -fsSL https://opencode.ai/v2/install | bash
```

### Agents

OpenCode includes two built-in agents you can switch between with the `Tab` key.

- **build** - Default, full-access agent for development work
- **plan** - Read-only agent for analysis and code exploration
  - Denies file edits by default
  - Asks permission before running bash commands
  - Ideal for exploring unfamiliar codebases or planning changes

Also included is a **general** subagent for complex searches and multistep tasks.
This is used internally and can be invoked using `@general` in messages.

Learn more about [agents](https://opencode.ai/docs/agents).

### Documentation

For more info on how to configure OpenCode, [**head over to our docs**](https://opencode.ai/docs).

### Contributing

If you're interested in contributing to OpenCode, please read our [contributing docs](./CONTRIBUTING.md) before submitting a pull request.

### Building on OpenCode

If you are working on a project that's related to OpenCode and is using "opencode" as part of its name, for example "opencode-dashboard" or "opencode-mobile", please add a note to your README to clarify that it is not built by the OpenCode team and is not affiliated with us in any way.

---

**Join our community** [Discord](https://discord.gg/opencode) | [X.com](https://x.com/opencode)

---

### Packages Web Src Content Docs Index (`packages/web/src/content/docs/index.mdx`)

---
title: Intro
description: Get started with OpenCode.
---

import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../config.mjs"
export const console = config.console

:::note
OpenCode 1 and OpenCode 2 both use the `opencode` command and cannot be installed side by side under their default command.
See the [OpenCode 2 docs](https://opencode.ai/v2/docs/) to migrate to V2.
:::

[**OpenCode**](/) is an open source AI coding agent. It's available as a terminal-based interface, desktop app, or IDE extension.



Let's get started.

---

#### Prerequisites

To use OpenCode in your terminal, you'll need:

1. A modern terminal emulator like:
   - [WezTerm](https://wezterm.org), cross-platform
   - [Alacritty](https://alacritty.org), cross-platform
   - [Ghostty](https://ghostty.org), Linux and macOS
   - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux and macOS

2. API keys for the LLM providers you want to use.

---

## Install

The easiest way to install OpenCode 1 is through the install script. These installation methods provide the `opencode`
binary and can conflict with or replace an OpenCode 2 installation.

```bash
curl -fsSL https://opencode.ai/install | bash
```

You can also install it with the following commands:

- **Using Node.js**

        <Tabs>

      <TabItem label="npm">
      ```bash
      npm install opencode-ai
      ```

          </TabItem>

        <TabItem label="Bun">
        ```bash
        bun install -g opencode-ai
        ```

          </TabItem>

        <TabItem label="pnpm">
        ```bash
        pnpm install opencode-ai
        ```

          </TabItem>

        <TabItem label="Yarn">
        ```bash
        yarn global add opencode-ai
        ```

      </TabItem>

  </Tabs>

- **Using Homebrew on macOS and Linux**

  ```bash
  brew install anomalyco/tap/opencode
  ```

  > We recommend using the OpenCode tap for the most up to date releases. The official `brew install opencode` formula is maintained by the Homebrew team and is updated less frequently.

- **Installing on Arch Linux**

  ```bash
  sudo pacman -S opencode           # Arch Linux (Stable)
  paru -S opencode-bin              # Arch Linux (Latest from AUR)
  ```

#### Windows

:::tip[Recommended: Use WSL]
For the best experience on Windows, we recommend using [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). It provides better performance and full compatibility with OpenCode's features.
:::

- **Using Chocolatey**

  ```bash
  choco install opencode
  ```

- **Using Scoop**

  ```bash
  scoop install opencode
  ```

- **Using NPM**

  ```bash
  npm install opencode-ai
  ```

- **Using Mise**

  ```bash
  mise use -g github:anomalyco/opencode
  ```

- **Using Docker**

  ```bash
  docker run -it --rm ghcr.io/anomalyco/opencode
  ```

Support for installing OpenCode on Windows using Bun is currently in progress.

You can also grab the binary from the [Releases](https://github.com/anomalyco/opencode/releases).

---

## Configure

With OpenCode you can use any LLM provider by configuring their API keys.

If you are new to using LLM providers, we recommend using [OpenCode Zen](https://opencode.ai/v2/docs/console/).
It's a curated list of models that have been tested and verified by the OpenCode
team.

1. Run the `/connect` command in the TUI, select opencode, and head to [opencode.ai/auth](https://opencode.ai/auth).

   ```txt
   /connect
   ```

2. Sign in, add your billing details, and copy your API key.

3. Paste your API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

Alternatively, you can select one of the other providers. [Learn more](/docs/providers#directory).

---

## Initialize

Now that you've configured a provider, you can navigate to a project that
you want to work on.

```bash
cd /path/to/project
```

And run OpenCode.

```bash
opencode
```

Next, initialize OpenCode for the project by running the following command.

```bash frame="none"
/init
```

This will get OpenCode to analyze your project and create an `AGENTS.md` file in
the project root.

:::tip
You should commit your project's `AGENTS.md` file to Git.
:::

This helps OpenCode understand the project structure and the coding patterns
used.

---

## Usage

You are now ready to use OpenCode to work on your project. Feel free to ask it
anything!

If you are new to using an AI coding agent, here are some examples that might
help.

---

### Ask questions

You can ask OpenCode to explain the codebase to you.

:::tip
Use the `@` key to fuzzy search for files in the project.
:::

```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```

This is helpful if there's a part of the codebase that you didn't work on.

---

### Add features

You can ask OpenCode to add new features to your project. Though we first recommend asking it to create a plan.

1. **Create a plan**

   OpenCode has a _Plan mode_ that disables its ability to make changes and
   instead suggest _how_ it'll implement the feature.

   Switch to it using the **Tab** key. You'll see an indicator for this in the lower right corner.

   ```bash frame="none" title="Switch to Plan mode"
   <TAB>
   ```

   Now let's describe what we want it to do.

   ```txt frame="none"
   When a user deletes a note, we'd like to flag it as deleted in the database.
   Then create a screen that shows all the recently deleted notes.
   From this screen, the user can undelete a note or permanently delete it.
   ```

   You want to give OpenCode enough details to understand what you want. It helps
   to talk to it like you are talking to a junior developer on your team.

   :::tip
   Give OpenCode plenty of context and examples to help it understand what you
   want.
   :::

2. **Iterate on the plan**

   Once it gives you a plan, you can give it feedback or add more details.

   ```txt frame="none"
   We'd like to design this new screen using a design I've used before.
   [Image #1] Take a look at this image and use it as a reference.
   ```

   :::tip
   Drag and drop images into the terminal to add them to the prompt.
   :::

   OpenCode can scan any images you give it and add them to the prompt. You can
   do this by dragging and dropping an image into the terminal.

3. **Build the feature**

   Once you feel comfortable with the plan, switch back to _Build mode_ by
   hitting the **Tab** key again.

   ```bash frame="none"
   <TAB>
   ```

   And asking it to make the changes.

   ```bash frame="none"
   Sounds good! Go ahead and make the changes.
   ```

---

### Make changes

For more straightforward changes, you can ask OpenCode to directly build it
without having to review the plan first.

```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```

You want to make sure you provide a good amount of detail so OpenCode makes the right
changes.

---

### Undo changes

Let's say you ask OpenCode to make some changes.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

But you realize that it is not what you wanted. You **can undo** the changes
using the `/undo` command.

```bash frame="none"
/undo
```

OpenCode will now revert the changes you made and show your original message
again.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

From here you can tweak the prompt and ask OpenCode to try again.

:::tip
You can run `/undo` multiple times to undo multiple changes.
:::

Or you **can redo** the changes using the `/redo` command.

```bash frame="none"
/redo
```

---

## Customize

And that's it! You are now a pro at using OpenCode.

To make it your own, we recommend [picking a theme](/docs/themes), [customizing the keybinds](/docs/keybinds), [configuring code formatters](/docs/formatters), [creating custom commands](/docs/commands), or playing around with the [OpenCode config](/docs/config).

---

### Services Www Src Docs Content Index (`services/www/src/docs/content/index.mdx`)

---
title: "Intro"
---

OpenCode is an open source AI coding agent. It’s available as a terminal-based interface, desktop app, or web app.


## CLI

<CodeTabs
  id="install"
  label="Install method"
  tabs={[
    { label: "curl", code: "curl -fsSL https://opencode.ai/v2/install | bash" },
    { label: "homebrew", code: "brew install anomalyco/tap/opencode-v2" },
    { label: "npm", code: "npm install @opencode/cli" },
    { label: "bun", code: "bun install -g --trust @opencode/cli" },
    { label: "pnpm", code: "pnpm add --allow-build=@opencode/cli @opencode/cli" },
    { label: "yarn", code: "yarn global add @opencode/cli" },
    { label: "vite+", code: "vp install -g @opencode/cli" },
    { label: "aur", code: "paru -S opencode-beta" },
    { label: "mise", code: "mise use -g opencode" },
  ]}
/>

The npm package uses a postinstall script to select the native `opencode` binary for your platform. The Bun and pnpm commands
explicitly allow the required script; Vite+ requires no additional flag. The mise command requires mise 2026.10.9 or later;
older versions install OpenCode 1.

Windows package managers are not supported.


Download a standalone CLI binary for your platform.

- **macOS:** [Apple silicon](https://opencode.ai/update/api/latest/cli/opencode/opencode-darwin-arm64.zip) · [Intel](https://opencode.ai/update/api/latest/cli/opencode/opencode-darwin-x64.zip) · [Intel (baseline)](https://opencode.ai/update/api/latest/cli/opencode/opencode-darwin-x64-baseline.zip)
- **Windows:** [ARM64](https://opencode.ai/update/api/latest/cli/opencode/opencode-windows-arm64.zip) · [x64](https://opencode.ai/update/api/latest/cli/opencode/opencode-windows-x64.zip) · [x64 (baseline)](https://opencode.ai/update/api/latest/cli/opencode/opencode-windows-x64-baseline.zip)
- **Linux (glibc):** [ARM64](https://opencode.ai/update/api/latest/cli/opencode/opencode-linux-arm64.tar.gz) · [x64](https://opencode.ai/update/api/latest/cli/opencode/opencode-linux-x64.tar.gz) · [x64 (baseline)](https://opencode.ai/update/api/latest/cli/opencode/opencode-linux-x64-baseline.tar.gz)
- **Linux (musl):** [ARM64](https://opencode.ai/update/api/latest/cli/opencode/opencode-linux-arm64-musl.tar.gz) · [x64](https://opencode.ai/update/api/latest/cli/opencode/opencode-linux-x64-musl.tar.gz) · [x64 (baseline)](https://opencode.ai/update/api/latest/cli/opencode/opencode-linux-x64-baseline-musl.tar.gz)

## Desktop

Download the latest OpenCode Desktop build for your platform.

- **macOS:** [Apple silicon](https://opencode.ai/update/api/latest/desktop/opencode/opencode-desktop-mac-arm64.dmg) · [Intel](https://opencode.ai/update/api/latest/desktop/opencode/opencode-desktop-mac-x64.dmg)
- **Windows:** [x64](https://opencode.ai/update/api/latest/desktop/opencode/opencode-desktop-win-x64.exe) · [ARM64](https://opencode.ai/update/api/latest/desktop/opencode/opencode-desktop-win-arm64.exe)
- **Linux (.deb):** [x64](https://opencode.ai/update/api/latest/desktop/opencode/opencode-desktop-linux-amd64.deb) · [ARM64](https://opencode.ai/update/api/latest/desktop/opencode/opencode-desktop-linux-arm64.deb)
- **Linux (.rpm):** [x64](https://opencode.ai/update/api/latest/desktop/opencode/opencode-desktop-linux-x86_64.rpm) · [ARM64](https://opencode.ai/update/api/latest/desktop/opencode/opencode-desktop-linux-aarch64.rpm)
- **Linux (AppImage):** [x64](https://opencode.ai/update/api/latest/desktop/opencode/opencode-desktop-linux-x86_64.AppImage) · [ARM64](https://opencode.ai/update/api/latest/desktop/opencode/opencode-desktop-linux-arm64.AppImage)


## Web

Access the OpenCode web interface with the `opencode pair` command.

```bash
$ opencode pair

  Open a link to connect. Links work once and expire in 5 minutes.

  http://127.0.0.1:49374/auth/connect/...
```

## Docker

Docker images use versioned tags, for example `ghcr.io/anomalyco/opencode:2.0.0`.

---

## Connect

OpenCode has built-in support for many LLM providers. You can connect to them
directly [in the TUI](/cli/providers) with `/connect`.

See [Providers](/providers) to configure custom providers.

If you'd like easy access to all the best coding models you can try out
[OpenCode Console](/console).

You can also try [OpenCode Go](/console/go), a $10/month subscription
plan that grants you access to the best coding models.

---

## Customize

Make OpenCode your own by editing the [OpenCode config](/config), [loading plugins](/plugins), [connecting MCP
servers](/mcp-servers), or [creating commands](/commands). For terminal interface themes and keybindings, see [CLI
settings](/cli/config).

---

## Learn

If you are interested in an indepth course on OpenCode Boot.dev has created an excellent [AI Coding with
OpenCode](https://www.boot.dev/courses/learn-ai-coding) course in consultation with our team. All the information in the course is
free to read and watch, though some interactive features may require payment.

---

### Packages Web Src Content Docs Ar Index (`packages/web/src/content/docs/ar/index.mdx`)

---
title: مقدمة
description: ابدأ باستخدام OpenCode.
---

import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console

[**OpenCode**](/) هو وكيل ترميز بالذكاء الاصطناعي مفتوح المصدر. يتوفر كواجهة terminal، وتطبيق لسطح المكتب، أو إضافة لبيئة تطوير متكاملة (IDE).



لنبدأ.

---

#### المتطلبات

لاستخدام OpenCode في terminal، ستحتاج إلى:

1. محاكي terminal حديث مثل:
   - [WezTerm](https://wezterm.org) متعدد المنصات
   - [Alacritty](https://alacritty.org) متعدد المنصات
   - [Ghostty](https://ghostty.org) على Linux وmacOS
   - [Kitty](https://sw.kovidgoyal.net/kitty/) على Linux وmacOS

2. مفاتيح API لمزوّدي نماذج اللغة (LLM) الذين تريد استخدامهم.

---

## التثبيت

أسهل طريقة لتثبيت OpenCode هي عبر سكربت التثبيت.

```bash
curl -fsSL https://opencode.ai/install | bash
```

يمكنك أيضا تثبيته عبر الأوامر التالية:

- **باستخدام Node.js**

        <Tabs>

      <TabItem label="npm">
      ```bash
      npm install opencode-ai
      ```

          </TabItem>

        <TabItem label="Bun">
        ```bash
        bun install -g opencode-ai
        ```

          </TabItem>

        <TabItem label="pnpm">
        ```bash
        pnpm install opencode-ai
        ```

          </TabItem>

        <TabItem label="Yarn">
        ```bash
        yarn global add opencode-ai
        ```

      </TabItem>

  </Tabs>

- **باستخدام Homebrew على macOS وLinux**

  ```bash
  brew install anomalyco/tap/opencode
  ```

  > نوصي باستخدام tap الخاص بـ OpenCode للحصول على أحدث الإصدارات. صيغة `brew install opencode` الرسمية تُدار بواسطة فريق Homebrew ويتم تحديثها بوتيرة أقل.

- **باستخدام Paru على Arch Linux**

  ```bash
  sudo pacman -S opencode           # Arch Linux (Stable)
  paru -S opencode-bin              # Arch Linux (Latest from AUR)
  ```

#### Windows

:::tip[موصى به: استخدم WSL]
لأفضل تجربة على Windows، نوصي باستخدام [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). يوفر أداء أفضل وتوافقا كاملا مع ميزات OpenCode.
:::

- **باستخدام Chocolatey**

  ```bash
  choco install opencode
  ```

- **باستخدام Scoop**

  ```bash
  scoop install opencode
  ```

- **باستخدام NPM**

  ```bash
  npm install opencode-ai
  ```

- **باستخدام Mise**

  ```bash
  mise use -g github:anomalyco/opencode
  ```

- **باستخدام Docker**

  ```bash
  docker run -it --rm ghcr.io/anomalyco/opencode
  ```

دعم تثبيت OpenCode على Windows باستخدام Bun قيد العمل حاليا.

يمكنك أيضا تنزيل الملف التنفيذي من صفحة [Releases](https://github.com/anomalyco/opencode/releases).

---

## الإعداد

مع OpenCode يمكنك استخدام أي مزود LLM عبر إعداد مفاتيح API الخاصة به.

إذا كنت جديدا على استخدام مزوّدي LLM، فنوصي باستخدام [OpenCode Zen](https://opencode.ai/v2/docs/console/).
إنها قائمة منتقاة من النماذج تم اختبارها والتحقق منها بواسطة فريق OpenCode.

1. شغّل الأمر `/connect` في واجهة TUI، واختر opencode، ثم انتقل إلى [opencode.ai/auth](https://opencode.ai/auth).

   ```txt
   /connect
   ```

2. سجّل الدخول، وأضف تفاصيل الدفع، ثم انسخ مفتاح API.

3. الصق مفتاح API.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

بدلا من ذلك يمكنك اختيار أحد المزوّدين الآخرين. [اعرف المزيد](/docs/providers#directory).

---

## التهيئة

بعد أن قمت بإعداد مزوّد، يمكنك الانتقال إلى المشروع الذي تريد العمل عليه.

```bash
cd /path/to/project
```

ثم شغّل OpenCode.

```bash
opencode
```

بعد ذلك، هيّئ OpenCode للمشروع عبر تشغيل الأمر التالي.

```bash frame="none"
/init
```

سيجعل هذا OpenCode يحلل مشروعك ويُنشئ ملف `AGENTS.md` في جذر المشروع.

:::tip
يستحسن أن تقوم بعمل commit لملف `AGENTS.md` الخاص بمشروعك إلى Git.
:::

يساعد هذا OpenCode على فهم بنية المشروع وأنماط الترميز المستخدمة.

---

## الاستخدام

أصبحت الآن جاهزا لاستخدام OpenCode للعمل على مشروعك. لا تتردد في سؤاله أي شيء!

إذا كنت جديدا على استخدام وكيل ترميز بالذكاء الاصطناعي، فإليك بعض الأمثلة التي قد تساعد.

---

### اطرح أسئلة

يمكنك أن تطلب من OpenCode شرح قاعدة الشيفرة لك.

:::tip
استخدم المفتاح `@` للبحث التقريبي عن الملفات داخل المشروع.
:::

```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```

يفيد هذا عندما تكون هناك أجزاء من قاعدة الشيفرة لم تعمل عليها.

---

### أضف ميزات

يمكنك أن تطلب من OpenCode إضافة ميزات جديدة إلى مشروعك، لكننا نوصي أولا بطلب إنشاء خطة.

1. **أنشئ خطة**

   لدى OpenCode _وضع Plan_ يعطل قدرته على إجراء التغييرات، ويقترح بدلا من ذلك _كيف_ سينفّذ الميزة.

   انتقل إليه باستخدام مفتاح **Tab**. سترى مؤشرا لذلك في الزاوية السفلية اليمنى.

   ```bash frame="none" title="التبديل إلى وضع Plan"
   <TAB>
   ```

   الآن لنصف ما نريده أن يفعله.

   ```txt frame="none"
   When a user deletes a note, we'd like to flag it as deleted in the database.
   Then create a screen that shows all the recently deleted notes.
   From this screen, the user can undelete a note or permanently delete it.
   ```

   احرص على تزويد OpenCode بتفاصيل كافية ليفهم ما تريد. يساعد أن تتحدث إليه كما لو كنت تتحدث إلى مطور مبتدئ ضمن فريقك.

   :::tip
   أعطِ OpenCode سياقا وأمثلة كافية لمساعدته على فهم ما تريد.
   :::

2. **حسّن الخطة**

   بعد أن يقدم لك خطة، يمكنك إعطاؤه ملاحظات أو إضافة تفاصيل أكثر.

   ```txt frame="none"
   We'd like to design this new screen using a design I've used before.
   [Image #1] Take a look at this image and use it as a reference.
   ```

   :::tip
   اسحب الصور وأفلِتها داخل terminal لإضافتها إلى الطلب.
   :::

   يستطيع OpenCode فحص أي صور تزوده بها وإضافتها إلى الطلب. يمكنك فعل ذلك عبر سحب الصورة وإفلاتها داخل terminal.

3. **ابنِ الميزة**

   عندما تشعر بالارتياح للخطة، عد إلى _وضع Build_ بالضغط على مفتاح **Tab** مرة أخرى.

   ```bash frame="none"
   <TAB>
   ```

   ثم اطلب منه تنفيذ التغييرات.

   ```bash frame="none"
   Sounds good! Go ahead and make the changes.
   ```

---

### نفّذ تغييرات

للتغييرات الأبسط، يمكنك أن تطلب من OpenCode تنفيذها مباشرة دون الحاجة لمراجعة خطة أولا.

```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```

تأكد من تقديم قدر مناسب من التفاصيل لكي يجري OpenCode التغييرات الصحيحة.

---

### تراجع عن التغييرات

لنفترض أنك طلبت من OpenCode إجراء بعض التغييرات.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

لكن تتضح لك لاحقا أنها ليست ما تريده. يمكنك **التراجع** عن التغييرات باستخدام الأمر `/undo`.

```bash frame="none"
/undo
```

سيقوم OpenCode الآن بعكس التغييرات التي أُجريت ويعرض رسالتك الأصلية مجددا.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

من هنا يمكنك تعديل الطلب وطلب المحاولة مرة أخرى.

:::tip
يمكنك تشغيل `/undo` عدة مرات للتراجع عن عدة تغييرات.
:::

أو يمكنك **إعادة تنفيذ** التغييرات باستخدام الأمر `/redo`.

```bash frame="none"
/redo
```

---

## التخصيص

وهذا كل شيء! أصبحت الآن محترفا في استخدام OpenCode.

لتجعله مناسبا لك، نوصي بـ [اختيار سمة](/docs/themes)، و[تخصيص اختصارات لوحة المفاتيح](/docs/keybinds)، و[إعداد منسقات الشيفرة](/docs/formatters)، و[إنشاء أوامر مخصصة](/docs/commands)، أو التجربة مع [إعدادات OpenCode](/docs/config).

---

### Packages Web Src Content Docs Bs Index (`packages/web/src/content/docs/bs/index.mdx`)

---
title: Uvod
description: Započnite sa OpenCode.
---

import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console

[**OpenCode**](/) je AI agent za kodiranje otvorenog koda. Dostupan je kao interfejs baziran na terminalu, desktop aplikacija ili IDE ekstenzija.

Hajde da počnemo.

---

#### Preduvjeti

Da biste koristili OpenCode u svom terminalu, trebat će vam:

1. Moderan emulator terminala kao što su:
   - [WezTerm](https://wezterm.org), više platformi
   - [Alacritty](https://alacritty.org), više platformi
   - [Ghostty](https://ghostty.org), Linux i macOS
   - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux i macOS
2. API ključevi za LLM provajdere koje želite koristiti.

---

## Instalacija

Najlakši način za instaliranje OpenCode je putem instalacijske skripte.

```bash
curl -fsSL https://opencode.ai/install | bash
```

Također ga možete instalirati pomoću sljedećih naredbi:

- **Korištenje Node.js**

        <Tabs>

      <TabItem label="npm">
      ```bash
      npm install opencode-ai
      ```

          </TabItem>

        <TabItem label="Bun">
        ```bash
        bun install -g opencode-ai
        ```

          </TabItem>

        <TabItem label="pnpm">
        ```bash
        pnpm install opencode-ai
        ```

          </TabItem>

        <TabItem label="Yarn">
        ```bash
        yarn global add opencode-ai
        ```

      </TabItem>

  </Tabs>

- **Korištenje Homebrew-a na macOS-u i Linux-u**

```bash
  brew install anomalyco/tap/opencode
```

> Preporučujemo korištenje OpenCode tap za najnovija izdanja. Službenu formulu `brew install opencode` održava Homebrew tim i ažurira se rjeđe.

- **Korištenje Parua na Arch Linuxu**

  ```bash
  sudo pacman -S opencode           # Arch Linux (Stable)
  paru -S opencode-bin              # Arch Linux (Latest from AUR)
  ```

#### Windows

:::tip[Preporučeno: Koristite WSL]
Za najbolje iskustvo na Windows-u preporučujemo korištenje [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). Pruža bolje performanse i potpunu kompatibilnost sa OpenCode funkcijama.
:::

- **Korištenje Chocolatey-a**

```bash
  choco install opencode
```

- **Korištenje Scoop-a**

```bash
  scoop install opencode
```

- **Korištenje NPM-a**

```bash
  npm install opencode-ai
```

- **Korištenje Mise**

```bash
  mise use -g github:anomalyco/opencode
```

- **Korištenje Dockera**

```bash
  docker run -it --rm ghcr.io/anomalyco/opencode
```

Podrška za instaliranje OpenCode na Windows koristeći Bun je trenutno u toku.
Također možete preuzeti binarnu datoteku iz [Releases](https://github.com/anomalyco/opencode/releases).

---

## Konfiguracija

Uz OpenCode možete koristiti bilo kojeg LLM provajdera tako što ćete konfigurirati njihove API ključeve.
Ako ste tek počeli koristiti LLM provajdere, preporučujemo korištenje [OpenCode Zen](https://opencode.ai/v2/docs/console/).
To je kurirana lista modela koji su testirani i verifikovani od strane OpenCode tima.

1. Pokrenite naredbu `/connect` u TUI-u, odaberite opencode i idite na [opencode.ai/auth](https://opencode.ai/auth).

```txt
   /connect
```

2. Prijavite se, dodajte svoje detalje naplate i kopirajte svoj API ključ.
3. Zalijepite svoj API ključ.

```txt
   ┌ API key
   │
   │
   └ enter
```

Alternativno, možete odabrati jednog od drugih provajdera. [Saznajte više](/docs/providers#directory).

---

## Inicijalizacija

Sada kada ste konfigurisali provajdera, možete se kretati do projekta na kojem želite raditi.

```bash
cd /path/to/project
```

I pokrenite OpenCode.

```bash
opencode
```

Zatim inicijalizirajte OpenCode za projekat pokretanjem sljedeće naredbe.

```bash frame="none"
/init
```

Ovo će omogućiti OpenCode da analizira vaš projekat i kreira `AGENTS.md` fajl u korijenu projekta.
:::tip
Trebali biste komitovati datoteku `AGENTS.md` vašeg projekta u Git.
:::
Ovo pomaže OpenCode da razumije strukturu projekta i obrasce kodiranja koji se koriste.

---

## Korištenje

Sada ste spremni da koristite OpenCode za rad na svom projektu. Slobodno pitajte bilo šta!
Ako ste novi u korištenju agenta za AI kodiranje, evo nekoliko primjera koji bi mogli pomoći.

---

### Postavljanje pitanja

Možete zamoliti OpenCode da vam objasni kodnu bazu.
:::tip
Koristite tipku `@` za nejasnu pretragu datoteka u projektu.
:::

```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```

Ovo je korisno ako postoji dio kodne baze na kojem niste radili.

---

### Dodavanje funkcija

Možete zamoliti OpenCode da vašem projektu doda nove funkcije. Iako preporučujemo da ga prvo zamolite da napravi plan.

1. **Kreirajte plan**
   OpenCode ima _Plan mod_ koji onemogućuje njegovu sposobnost da pravi promjene i umjesto toga predlaže _kako_ će implementirati ovu funkciju.
   Prebacite se na njega pomoću tipke **Tab**. Vidjet ćete indikator za ovo u donjem desnom uglu.

```bash frame="none" title="Switch to Plan mode"
   <TAB>
```

Hajde sada da opišemo šta želimo da uradi.

```txt frame="none"
    When a user deletes a note, we'd like to flag it as deleted in the database.
    Then create a screen that shows all the recently deleted notes.
    From this screen, the user can undelete a note or permanently delete it.
```

Želite da date OpenCode dovoljno detalja da razumije šta želite. Pomaže da razgovarate s njim kao da razgovarate sa mlađim programerom u svom timu.
:::tip
Dajte OpenCode dosta konteksta i primjera koji će mu pomoći da razumije šta vi želite.
:::

2. **Ponovite plan**
   Kada vam da plan, možete mu dati povratne informacije ili dodati više detalja.

```txt frame="none"
    We'd like to design this new screen using a design I've used before.
    [Image #1] Take a look at this image and use it as a reference.
```

:::tip
Prevucite i ispustite slike u terminal da biste ih dodali u prompt.
:::
OpenCode može skenirati sve slike koje mu date i dodati ih u prompt. Možete to učiniti povlačenjem i ispuštanjem slike u terminal.

3. **Izgradite funkciju**
   Kada se osjećate ugodno s planom, vratite se na _Build mode_ ponovnim pritiskom na taster **Tab**.

```bash frame="none"
   <TAB>
```

I tražeći od njega da napravi promjene.

```bash frame="none"
   Sounds good! Go ahead and make the changes.
```

---

### Pravljenje izmjena

Za jednostavnije promjene, možete zamoliti OpenCode da ga direktno izgradi bez potrebe da prvo pregledate plan.

```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```

Želite da budete sigurni da ste pružili dobru količinu detalja kako bi OpenCode napravio ispravne promjene.

---

### Poništavanje izmjena

Recimo da tražite od OpenCode da izvrši neke promjene.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

Ali shvatate da to nije ono što ste željeli. Možete **poništiti** promjene koristeći naredbu `/undo`.

```bash frame="none"
/undo
```

OpenCode će sada poništiti promjene koje ste napravili i ponovo prikazati vašu originalnu poruku.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

Odavde možete podesiti prompt i zamoliti OpenCode da pokuša ponovo.
:::tip
Možete pokrenuti `/undo` više puta da poništite više promjena.
:::
Ili **možete ponoviti** promjene koristeći naredbu `/redo`.

```bash frame="none"
/redo
```

---

## Prilagođavanje

I to je to! Sada ste profesionalac u korištenju OpenCode.
Da biste to učinili svojim, preporučujemo [odabir teme](/docs/themes), [prilagođavanje povezivanja tipki](/docs/keybinds), [konfiguriranje formatera koda](/docs/formatters), [kreiranje prilagođenih komandi](/docs/commands), ili igranje sa [OpenCode config](/docs/config).

---

### Packages Web Src Content Docs Da Index (`packages/web/src/content/docs/da/index.mdx`)

---
title: Introduktion
description: Kom godt i gang med OpenCode.
---

import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console

[**OpenCode**](/) er en open source AI-kodningsagent. Den er tilgængelig som en terminalbaseret grænseflade, desktop-app eller IDE-udvidelse.



Lad os komme i gang.

---

#### Forudsætninger

For at bruge OpenCode i din terminal skal du bruge:

1. En moderne terminalemulator som:
   - [WezTerm](https://wezterm.org), på tværs af platforme
   - [Alacritty](https://alacritty.org), på tværs af platforme
   - [Ghostty](https://ghostty.org), Linux og macOS
   - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux og macOS

2. API-nøgler til de LLM udbydere, du vil bruge.

---

## Installation

Den nemmeste måde at installere OpenCode på er gennem installationsscriptet.

```bash
curl -fsSL https://opencode.ai/install | bash
```

Du kan også installere det med følgende kommandoer:

- **Bruger Node.js**

        <Tabs>

      <TabItem label="npm">
      ```bash
      npm install opencode-ai
      ```

          </TabItem>

        <TabItem label="Bun">
        ```bash
        bun install -g opencode-ai
        ```

          </TabItem>

        <TabItem label="pnpm">
        ```bash
        pnpm install opencode-ai
        ```

          </TabItem>

        <TabItem label="Yarn">
        ```bash
        yarn global add opencode-ai
        ```

      </TabItem>

  </Tabs>

- **Brug af Homebrew på macOS og Linux**

  ```bash
  brew install anomalyco/tap/opencode
  ```

  > Vi anbefaler at bruge OpenCode-tap for at få de mest opdaterede udgivelser. Den officielle `brew install opencode`-formel vedligeholdes af Homebrew-teamet og opdateret sjældnere.

- **Brug af Paru på Arch Linux**

  ```bash
  sudo pacman -S opencode           # Arch Linux (Stable)
  paru -S opencode-bin              # Arch Linux (Latest from AUR)
  ```

#### Windows

:::tip[Anbefalet: Brug WSL]
For at få den bedste oplevelse på Windows anbefaler vi at bruge [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). Det giver bedre ydeevne og fuld kompatibilitet med OpenCodes funktioner.
:::

- **Brug af Chocolatey**

  ```bash
  choco install opencode
  ```

- **Brug af Scoop**

  ```bash
  scoop install opencode
  ```

- **Bruger NPM**

  ```bash
  npm install opencode-ai
  ```

- **Brug af Mise**

  ```bash
  mise use -g github:anomalyco/opencode
  ```

- **Brug af Docker**

  ```bash
  docker run -it --rm ghcr.io/anomalyco/opencode
  ```

Support til installation af OpenCode på Windows ved hjælp af Bun er i gang.

Du kan også få fat i binæren fra [Releases](https://github.com/anomalyco/opencode/releases).

---

## Konfiguration

Med OpenCode kan du bruge enhver LLM udbyder ved at konfigurere deres API-nøgler.

Hvis du er ny til at bruge LLM-udbydere, anbefaler vi at bruge [OpenCode Zen](https://opencode.ai/v2/docs/console/).
Det er en udvalgt liste over modeller, der er blevet testet og verificeret af OpenCode
holde.

1. Kør kommandoen `/connect` i TUI, vælg opencode, og gå til [opencode.ai/auth](https://opencode.ai/auth).

   ```txt
   /connect
   ```

2. Log ind, tilføj dine faktureringsoplysninger, og kopier din API-nøgle.

3. Indsæt din API-nøgle.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

Alternativt kan du vælge en af ​​de andre udbydere. [Læs mere](/docs/providers#directory).

---

## Initialisering

Nu hvor du har konfigureret en udbyder, kan du navigere til et projekt, der
du vil arbejde på.

```bash
cd /path/to/project
```

Og kør OpenCode.

```bash
opencode
```

Derefter initialiseres OpenCode for projektet ved at køre følgende kommando.

```bash frame="none"
/init
```

Dette får OpenCode til at analysere dit projekt og oprette en `AGENTS.md` fil i
projektets rod.

:::tip
Du bør overgive dit projekter `AGENTS.md` fil til Git.
:::

Dette hjælper OpenCode med at forstå projektstrukturen og kodningsmønstrene
brugt.

---

## Brug

Du er nu klar til at bruge OpenCode til at arbejde på dit projekt. Spørg det gerne
noget!

Hvis du er ny til at bruge en AI-kodningsagent, er her nogle eksempler, der evt
hjælp.

---

### Stil spørgsmål

Du kan bede OpenCode om at forklare kodebasen for dig.

:::tip
Brug `@`-tasten til at søge efter filer i projektet.
:::

```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```

Dette er nyttigt, hvis der er en del af kodebasen, som du ikke har arbejdet på.

---

### Tilføj funktioner

Du kan bede OpenCode om at tilføje nye funktioner til dit projekt. Selvom vi først anbefaler, at du beder den om at lave en plan.

1. **Opret en plan**

   OpenCode har en _Plan mode_, der deaktiverer dens evne til at foretage ændringer og
   foreslå i stedet _hvordan_ det vil implementere funktionen.

   Skift til det ved hjælp af **Tab**-tasten. Du vil se en indikator for dette i nederste højre hjørne.

   ```bash frame="none" title="Skift til Plan-tilstand"
   <TAB>
   ```

   Lad os nu beskrive, hvad vi vil have den til at gøre.

   ```txt frame="none"
   When a user deletes a note, we'd like to flag it as deleted in the database.
   Then create a screen that shows all the recently deleted notes.
   From this screen, the user can undelete a note or permanently delete it.
   ```

   Du vil give OpenCode nok detaljer til at forstå, hvad du ønsker. Det hjælper
   at tale med det, som om du taler med en juniorudvikler på dit team.

:::tip
Giv OpenCode masser af kontekst og eksempler for at hjælpe den med at forstå, hvad du
ønsker.
:::

2. **Gentag om planen**

   Når det giver dig en plan, kan du give den feedback eller tilføje flere detaljer.

   ```txt frame="none"
   We'd like to design this new screen using a design I've used before.
   [Image #1] Take a look at this image and use it as a reference.
   ```

:::tip
Træk og slip billeder i terminalen for at tilføje dem til prompten.
:::

OpenCode kan scanne alle billeder, du giver dem og tilføje dem til prompten. Det kan du
gør dette ved at trække og slippe et billede ind i terminalen.

3. **Byg funktionen**

   Når du føler dig godt tilpas med planen, skal du skifte tilbage til _Byggetilstand_ ved
   trykke på **Tab**-tasten igen.

   ```bash frame="none"
   <TAB>
   ```

   Og beder den om at foretage ændringerne.

   ```bash frame="none"
   Sounds good! Go ahead and make the changes.
   ```

---

### Foretag ændringer

For mere ligetil ændringer kan du bede OpenCode om at bygge den direkte
uden at skulle gennemgå planen først.

```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```

Du vil sikre dig, at du giver en god mængde detaljer, så OpenCode gør det rigtige
ændringer.

---

### Fortryd ændringer

Lad os sige, at du beder OpenCode om at foretage nogle ændringer.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

Men du indser, at det ikke er, hvad du ønskede. Du **kan fortryde** ændringerne
ved hjælp af kommandoen `/undo`.

```bash frame="none"
/undo
```

OpenCode vil nu vende tilbage til ændringerne, du har foretaget, og vise din oprindelige besked
igen.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

Herfra kan du justere prompten og bede OpenCode om at prøve igen.

:::tip
Du kan køre `/undo` flere gange for at fortryde flere ændringer.
:::

Eller du **kan gentage** ændringerne ved hjælp af kommandoen `/redo`.

```bash frame="none"
/redo
```

---

## Tilpasning

Og det er det! Du er nu en professionel i at bruge OpenCode.

For at gøre det til dit eget, anbefaler vi [at vælge et tema](/docs/themes), [tilpasse genvejstaster](/docs/keybinds), [konfigurere kodeformater](/docs/formatters), [oprette brugerdefinerede kommandoer](/docs/commands) eller at lege med [OpenCode-konfiguration](/docs/config).

---

### Packages Web Src Content Docs De Index (`packages/web/src/content/docs/de/index.mdx`)

---
title: Einführung
description: Beginnen Sie mit OpenCode.
---

import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console

[**OpenCode**](/) ist ein Open-Source-Coding-Agent für AI. Es ist als terminalbasierte Schnittstelle, Desktop-App oder IDE-Erweiterung verfügbar.



Fangen wir an.

---

#### Voraussetzungen

Um OpenCode in Ihrem Terminal verwenden zu können, benötigen Sie:

1. Ein moderner Terminal-Emulator, zum Beispiel:
   - [WezTerm](https://wezterm.org), cross-platform
   - [Alacritty](https://alacritty.org), plattformübergreifend
   - [Ghostty](https://ghostty.org), Linux und macOS
   - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux und macOS

2. API-Schlüssel für die LLM-Anbieter, die Sie verwenden möchten.

---

## Installation

Der einfachste Weg, OpenCode zu installieren, ist über das Installationsskript.

```bash
curl -fsSL https://opencode.ai/install | bash
```

Sie können es auch mit den folgenden Befehlen installieren:

- **Mit Node.js**

        <Tabs>

      <TabItem label="npm">
      ```bash
      npm install opencode-ai
      ```

          </TabItem>

        <TabItem label="Bun">
        ```bash
        bun install -g opencode-ai
        ```

          </TabItem>

        <TabItem label="pnpm">
        ```bash
        pnpm install opencode-ai
        ```

          </TabItem>

        <TabItem label="Yarn">
        ```bash
        yarn global add opencode-ai
        ```

      </TabItem>

  </Tabs>

- **Homebrew unter macOS und Linux verwenden**

  ```bash
  brew install anomalyco/tap/opencode
  ```

  > Wir empfehlen die Verwendung des OpenCode-Taps für die aktuellsten Versionen. Die offizielle `brew install opencode`-Formel wird vom Homebrew-Team gepflegt und seltener aktualisiert.

- **Verwendung von Paru unter Arch Linux**

  ```bash
  sudo pacman -S opencode           # Arch Linux (Stable)
  paru -S opencode-bin              # Arch Linux (Latest from AUR)
  ```

#### Windows

:::tip[Empfohlen: Verwenden Sie WSL]
Für das beste Erlebnis unter Windows empfehlen wir die Verwendung von [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). Es bietet eine bessere Leistung und vollständige Kompatibilität mit den Funktionen von OpenCode.
:::

- **Verwendung von Chocolatey**

  ```bash
  choco install opencode
  ```

- **Scoop verwenden**

  ```bash
  scoop install opencode
  ```

- **Mit NPM**

  ```bash
  npm install opencode-ai
  ```

- **Mit Mise**

  ```bash
  mise use -g github:anomalyco/opencode
  ```

- **Verwendung von Docker**

  ```bash
  docker run -it --rm ghcr.io/anomalyco/opencode
  ```

Die Unterstützung für die Installation von OpenCode unter Windows mit Bun ist derzeit in Arbeit.

Sie können die Binärdatei auch aus [Releases](https://github.com/anomalyco/opencode/releases) abrufen.

---

## Konfiguration

Mit OpenCode können Sie jeden LLM-Anbieter verwenden, indem Sie dessen API-Schlüssel konfigurieren.

Wenn Sie mit der Verwendung von LLM-Anbietern noch nicht vertraut sind, empfehlen wir die Verwendung von [OpenCode Zen](https://opencode.ai/v2/docs/console/).
Es handelt sich um eine kuratierte Liste von Modellen, die vom OpenCode Team getestet und verifiziert wurden.

1. Führen Sie den Befehl `/connect` in TUI aus, wählen Sie OpenCode aus und gehen Sie zu [opencode.ai/auth](https://opencode.ai/auth).

   ```txt
   /connect
   ```

2. Melden Sie sich an, geben Sie Ihre Rechnungsdaten ein und kopieren Sie Ihren API-Schlüssel.

3. Fügen Sie Ihren API-Schlüssel ein.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

Alternativ können Sie auch einen der anderen Anbieter auswählen. [Mehr erfahren](/docs/providers#directory).

---

## Initialisierung

Nachdem Sie nun einen Anbieter konfiguriert haben, können Sie zu einem Projekt navigieren
an dem Sie arbeiten möchten.

```bash
cd /path/to/project
```

Und führen Sie OpenCode aus.

```bash
opencode
```

Als nächstes initialisieren Sie OpenCode für das Projekt, indem Sie den folgenden Befehl ausführen.

```bash frame="none"
/init
```

Dadurch wird OpenCode dazu veranlasst, Ihr Projekt zu analysieren und eine `AGENTS.md`-Datei im Projektstammverzeichnis zu erstellen.

:::tip
Sie sollten die `AGENTS.md`-Datei Ihres Projekts an Git übergeben.
:::

Dies hilft OpenCode, die Projektstruktur und die Codierungsmuster zu verstehen
die verwendet werden.

---

## Verwendung

Sie können nun OpenCode verwenden, um an Ihrem Projekt zu arbeiten. Fragen Sie ruhig nach
allem!

Wenn Sie mit der Verwendung eines AI-Codierungsagenten noch nicht vertraut sind, finden Sie hier einige Beispiele, die hilfreich sein könnten.

---

### Fragen stellen

Sie können OpenCode bitten, Ihnen die Codebasis zu erklären.

:::tip
Verwenden Sie die Taste `@`, um eine Fuzzy-Suche nach Dateien im Projekt durchzuführen.
:::

```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```

Dies ist hilfreich, wenn es einen Teil der Codebasis gibt, an dem Sie nicht gearbeitet haben.

---

### Funktionen hinzufügen

Sie können OpenCode bitten, Ihrem Projekt neue Funktionen hinzuzufügen. Wir empfehlen jedoch, es zunächst um die Erstellung eines Plans zu bitten.

1. **Erstellen Sie einen Plan**

   OpenCode verfügt über einen _Plan Mode_, der seine Fähigkeit, Änderungen vorzunehmen, deaktiviert
   Schlagen Sie stattdessen vor, wie die Funktion implementiert wird.

   Wechseln Sie mit der **Tabulatortaste** dorthin. In der unteren rechten Ecke sehen Sie einen Indikator dafür.

   ```bash frame="none" title="In den Plan-Modus wechseln"
   <TAB>
   ```

   Beschreiben wir nun, was es tun soll.

   ```txt frame="none"
   When a user deletes a note, we'd like to flag it as deleted in the database.
   Then create a screen that shows all the recently deleted notes.
   From this screen, the user can undelete a note or permanently delete it.
   ```

   Sie möchten OpenCode genügend Details geben, um zu verstehen, was Sie wollen. Es hilft
   mit ihm zu sprechen, als ob Sie mit einem Junior-Entwickler in Ihrem Team sprechen würden.

   :::tip
   Geben Sie OpenCode reichlich Kontext und Beispiele, damit es versteht, was Sie
   wollen.
   :::

2. **Den Plan überarbeiten**

   Sobald Sie einen Plan erhalten, können Sie ihm Feedback geben oder weitere Details hinzufügen.

   ```txt frame="none"
   We'd like to design this new screen using a design I've used before.
   [Image #1] Take a look at this image and use it as a reference.
   ```

   :::tip
   Ziehen Sie Bilder per Drag-and-Drop in das Terminal, um sie zur Eingabeaufforderung hinzuzufügen.
   :::

   OpenCode kann alle von Ihnen bereitgestellten Bilder scannen und zur Eingabeaufforderung hinzufügen. Du kannst
   Ziehen Sie dazu ein Bild per Drag & Drop in das Terminal.

3. **Funktion erstellen**

   Wenn Sie mit dem Plan zufrieden sind, wechseln Sie zurück in den _Build Mode_
   indem Sie erneut die **Tabulatortaste** drücken.

   ```bash frame="none"
   <TAB>
   ```

   Und es bitten, die Änderungen vorzunehmen.

   ```bash frame="none"
   Sounds good! Go ahead and make the changes.
   ```

---

### Änderungen vornehmen

Für einfachere Änderungen können Sie OpenCode bitten, es direkt zu erstellen
ohne den Plan vorher überprüfen zu müssen.

```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```

Sie möchten sicherstellen, dass Sie viele Details bereitstellen, damit OpenCode die richtigen
Änderungen vornimmt.

---

### Änderungen rückgängig machen

Nehmen wir an, Sie bitten OpenCode, einige Änderungen vorzunehmen.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

Aber Sie erkennen, dass es nicht das ist, was Sie wollten. Sie können die Änderungen **rückgängig machen**
mit dem Befehl `/undo`.

```bash frame="none"
/undo
```

OpenCode macht nun die von Ihnen vorgenommenen Änderungen rückgängig und zeigt Ihre ursprüngliche Nachricht
wieder an.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

Von hier aus können Sie die Eingabeaufforderung anpassen und OpenCode bitten, es erneut zu versuchen.

:::tip
Sie können `/undo` mehrmals ausführen, um mehrere Änderungen rückgängig zu machen.
:::

Oder Sie **können** die Änderungen mit dem Befehl `/redo` wiederholen.

```bash frame="none"
/redo
```

---

## Anpassung

Und das ist es! Sie sind jetzt ein Profi im Umgang mit OpenCode.

Um es zu Ihrem eigenen zu machen, empfehlen wir [ein Theme auszuwählen](/docs/themes), [Keybinds anzupassen](/docs/keybinds), [Code-Formatter zu konfigurieren](/docs/formatters), [eigene Commands zu erstellen](/docs/commands) oder mit der [OpenCode-Konfiguration](/docs/config) zu experimentieren.

---

### Packages Web Src Content Docs Es Index (`packages/web/src/content/docs/es/index.mdx`)

---
title: Introducción
description: Comience a usar OpenCode.
---

import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console

[**OpenCode**](/) es un agente de codigo de IA de código abierto. Está disponible como interfaz basada en terminal, aplicación de escritorio o extensión IDE.



Comencemos.

---

#### Requisitos previos

Para usar OpenCode en la terminal, necesitará:

1. Un emulador de terminal moderno como:
   - [WezTerm](https://wezterm.org), multiplataforma
   - [Alacritty](https://alacritty.org), multiplataforma
   - [Ghostty](https://ghostty.org), Linux y macOS
   - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux y macOS

2. Claves de API de los proveedores de LLM que quiera usar.

---

## Instalar

La forma más sencilla de instalar OpenCode es mediante el script de instalación.

```bash
curl -fsSL https://opencode.ai/install | bash
```

También puedes instalarlo con alguno de los siguientes métodos:

- **Usando Node.js**

        <Tabs>

      <TabItem label="npm">
      ```bash
      npm install opencode-ai
      ```

          </TabItem>

        <TabItem label="Bun">
        ```bash
        bun install -g opencode-ai
        ```

          </TabItem>

        <TabItem label="pnpm">
        ```bash
        pnpm install opencode-ai
        ```

          </TabItem>

        <TabItem label="Yarn">
        ```bash
        yarn global add opencode-ai
        ```

      </TabItem>

  </Tabs>

- **Usando Homebrew en macOS y Linux**

  ```bash
  brew install anomalyco/tap/opencode
  ```

  > Recomendamos utilizar el tap OpenCode para las versiones más actualizadas. La fórmula oficial `brew install opencode` la mantiene el equipo Homebrew y se actualiza con menos frecuencia.

- **Usando Paru en Arch Linux**

  ```bash
  sudo pacman -S opencode           # Arch Linux (Stable)
  paru -S opencode-bin              # Arch Linux (Latest from AUR)
  ```

#### Windows

:::tip[Recomendado: Usar WSL]
Para obtener la mejor experiencia en Windows, recomendamos utilizar [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). Ofrece mejor rendimiento y compatibilidad total con las funciones de OpenCode.
:::

- **Usando Chocolatey**

  ```bash
  choco install opencode
  ```

- **Usando Scoop**

  ```bash
  scoop install opencode
  ```

- **Usando NPM**

  ```bash
  npm install opencode-ai
  ```

- **Usando Mise**

  ```bash
  mise use -g github:anomalyco/opencode
  ```

- **Usando Docker**

  ```bash
  docker run -it --rm ghcr.io/anomalyco/opencode
  ```

El soporte para instalar OpenCode en Windows usando Bun todavía está en desarrollo.

También puede obtener el binario desde [Versiones](https://github.com/anomalyco/opencode/releases).

---

## Configuración

Con OpenCode, puede usar cualquier proveedor de LLM configurando sus claves de API.

Si es nuevo en el uso de proveedores de LLM, le recomendamos usar [OpenCode Zen](https://opencode.ai/v2/docs/console/).
Es una selección de modelos probados y verificados por el equipo de OpenCode.

1. Ejecute el comando `/connect` en la TUI, seleccione opencode y diríjase a [opencode.ai/auth](https://opencode.ai/auth).

   ```txt
   /connect
   ```

2. Inicie sesión, agregue sus datos de facturación y copie su clave de API.

3. Pega tu clave de API.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

También puede seleccionar otro proveedor. [Más información](/docs/providers#directory).

---

## Inicializar

Ahora que ya configuró un proveedor, vaya al proyecto en el que quiera trabajar.

```bash
cd /path/to/project
```

Luego, ejecute OpenCode.

```bash
opencode
```

A continuación, inicialice OpenCode para el proyecto con el siguiente comando:

```bash frame="none"
/init
```

OpenCode analizará su proyecto y creará un archivo AGENTS.md en la raíz.

:::tip
Asegúrese de versionar en Git el archivo AGENTS.md de su proyecto.
:::

Esto ayuda a OpenCode a comprender la estructura del proyecto y los patrones de código que se usan en él.

---

## Usar

Ahora ya está listo para usar OpenCode en su proyecto. Puede pedirle desde explicaciones del código hasta cambios concretos.

Si es la primera vez que usa un agente de codigo con IA, estos ejemplos pueden servirle como punto de partida.

---

### Hacer preguntas

Puede pedirle a OpenCode que le explique el código base.

:::tip
Utilice la tecla `@` para realizar una búsqueda aproximada de archivos dentro del proyecto.
:::

```txt frame="none" "@packages/functions/src/api/index.ts"
¿Cómo se maneja la autenticación en @packages/functions/src/api/index.ts
```

Esto resulta útil cuando hay una parte del código base en la que usted no ha trabajado.

---

### Agregar funcionalidades

Puede pedirle a OpenCode que agregue nuevas funcionalidades a su proyecto. Aun así, primero recomendamos pedirle que cree un plan.

1. **Crear un plan**

   OpenCode tiene un modo Plan que desactiva temporalmente su capacidad de hacer cambios y, en su lugar, propone _cómo_ implementará la funcionalidad.

   Cambie a este modo con la tecla **Tab.** Verá un indicador en la esquina inferior derecha.

   ```bash frame="none" title="Switch to Plan mode"
   <TAB>
   ```

   Ahora describa lo que quiere que haga.

   ```txt frame="none"
   Cuando un usuario elimine una nota, queremos marcarla como eliminada en la base de datos.
   Luego, cree una pantalla que muestre todas las notas eliminadas recientemente.
   Desde esa pantalla, el usuario podrá restaurar una nota o eliminarla de forma permanente.
   ```

   Procure darle a OpenCode suficiente contexto para que entienda exactamente lo que necesita. Ayuda hablarle como si estuviera hablando con un desarrollador junior de su equipo.

   :::tip
   Déle a OpenCode todo el contexto y los ejemplos que pueda para ayudarle a comprender lo que desea.
   :::

2. **Iterar sobre el plan**

   Una vez que OpenCode le proponga un plan, puede darle comentarios o agregar más detalles.

   ```txt frame="none"
   Queremos diseñar esta nueva pantalla usando un diseño que ya hemos usado antes.
   [Imagen #1] Revise esta imagen y úsela como referencia.
   ```

   :::tip
   Arrastre y suelte imágenes en la terminal para agregarlas al mensaje.
   :::

   OpenCode puede analizar cualquier imagen que usted le proporcione y añadirla al contexto del mensaje. Puede hacerlo arrastrando y soltando una imagen en la terminal.

3. **Implementar la funcionalidad**

   Cuando esté conforme con el plan, vuelva al modo _Build_ presionando de nuevo la tecla Tab.

   ```bash frame="none"
   <TAB>
   ```

   Luego, pídale que haga los cambios.

   ```bash frame="none"
   Perfecto. Continúe y realice los cambios.
   ```

---

### Realizar cambios

Para cambios más sencillos, puede pedirle a OpenCode que los implemente directamente, sin revisar antes un plan.

```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
Necesitamos agregar autenticación a la ruta /settings. Revise cómo se maneja esto
en la ruta /notes en @packages/functions/src/notes.ts e implemente
la misma lógica en @packages/functions/src/settings.ts.
```

Procure dar suficientes detalles para que OpenCode pueda tomar las decisiones correctas al hacer los cambios

---

### Deshacer cambios

Supongamos que le pide a OpenCode que haga algunos cambios.

```txt frame="none" "@packages/functions/src/api/index.ts"
¿Puede refactorizar la función en @packages/functions/src/api/index.ts?
```

Pero luego se da cuenta de que no era lo que quería. Puede **deshacer** los cambios usando el comando `/undo`.

```bash frame="none"
/undo
```

OpenCode revertirá los cambios que hizo y volverá a mostrar su mensaje original.

```txt frame="none" "@packages/functions/src/api/index.ts"
¿Puede refactorizar la función en @packages/functions/src/api/index.ts?
```

Desde ahí, puede modificar el mensaje y pedirle a OpenCode que lo intente de nuevo.

:::tip
Puede ejecutar `/undo` varias veces para deshacer varios cambios.
:::

También puede rehacer los cambios usando el comando `/redo.`

```bash frame="none"
/redo
```

---

## Personalizar

Y eso es todo. Ya conoce lo básico para empezar a usar OpenCode.

Para personalizarlo, recomendamos [elegir un tema](/docs/themes), [personalizar las combinaciones de teclas](/docs/keybinds), [configurar formateadores de código](/docs/formatters), [crear comandos personalizados](/docs/commands) o explorar la [configuración OpenCode](/docs/config).

---

### Packages Web Src Content Docs Fr Index (`packages/web/src/content/docs/fr/index.mdx`)

---
title: Introduction
description: Commencez avec OpenCode.
---

import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console

[**OpenCode**](/) est un agent de codage d'IA open source. Il est disponible sous forme d'interface basée sur un terminal, d'application de bureau ou d'extension IDE.



Commençons.

---

#### Prérequis

Pour utiliser OpenCode dans votre terminal, vous aurez besoin de :

1. Un émulateur de terminal moderne comme :
   - [WezTerm](https://wezterm.org), multiplateforme
   - [Alacritty](https://alacritty.org), multiplateforme
   - [Ghostty](https://ghostty.org), Linux et macOS
   - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux et macOS

2. Clés API pour les fournisseurs de LLM que vous souhaitez utiliser.

---

## Installation

Le moyen le plus simple d'installer OpenCode est d'utiliser le script d'installation.

```bash
curl -fsSL https://opencode.ai/install | bash
```

Vous pouvez également l'installer avec les commandes suivantes :

- **Node.js**

    <Tabs>

      <TabItem label="npm">
      ```bash
      npm install opencode-ai
      ```

      </TabItem>

      <TabItem label="Bun">
      ```bash
      bun install -g opencode-ai
      ```

      </TabItem>

      <TabItem label="pnpm">
      ```bash
      pnpm install opencode-ai
      ```

      </TabItem>

      <TabItem label="Yarn">
      ```bash
      yarn global add opencode-ai
      ```

      </TabItem>

  </Tabs>

- **Via Homebrew sur macOS et Linux**

  ```bash
  brew install anomalyco/tap/opencode
  ```

  > Nous vous recommandons d'utiliser le tap OpenCode pour les versions les plus récentes. La formule officielle `brew install opencode` est maintenue par l'équipe Homebrew et est mise à jour moins fréquemment.

- **Via Paru sur Arch Linux**

  ```bash
  sudo pacman -S opencode           # Arch Linux (Stable)
  paru -S opencode-bin              # Arch Linux (Latest from AUR)
  ```

#### Windows

:::tip[Recommandé : utilisez WSL]
Pour une expérience optimale sur Windows, nous vous recommandons d'utiliser le [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). Il offre de meilleures performances et une compatibilité totale avec les fonctionnalités de OpenCode.
:::

- **Via Chocolatey**

  ```bash
  choco install opencode
  ```

- **Via Scoop**

  ```bash
  scoop install opencode
  ```

- **Via NPM**

  ```bash
  npm install opencode-ai
  ```

- **Via Mise**

  ```bash
  mise use -g github:anomalyco/opencode
  ```

- **Via Docker**

  ```bash
  docker run -it --rm ghcr.io/anomalyco/opencode
  ```

Le support de l'installation de OpenCode sur Windows à l'aide de Bun est actuellement en cours de développement.

Vous pouvez également récupérer le binaire dans les [Releases](https://github.com/anomalyco/opencode/releases).

---

## Configuration

Avec OpenCode, vous pouvez utiliser n'importe quel fournisseur de LLM en configurant ses clés API.

Si vous débutez avec les fournisseurs de LLM, nous vous recommandons d'utiliser [OpenCode Zen](https://opencode.ai/v2/docs/console/).
C'est une liste curée de modèles qui ont été testés et vérifiés par l'équipe OpenCode.

1. Exécutez la commande `/connect` dans le TUI, sélectionnez opencode et allez sur [opencode.ai/auth](https://opencode.ai/auth).

   ```txt
   /connect
   ```

2. Connectez-vous, ajoutez vos informations de facturation et copiez votre clé API.

3. Collez votre clé API.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

Vous pouvez également sélectionner l'un des autres fournisseurs. [En savoir plus](/docs/providers#directory).

---

## Initialisation

Maintenant que vous avez configuré un fournisseur, vous pouvez accéder à un projet sur lequel vous voulez travailler.

```bash
cd /path/to/project
```

Et exécutez OpenCode.

```bash
opencode
```

Ensuite, initialisez OpenCode pour le projet en exécutant la commande suivante.

```bash frame="none"
/init
```

Cela permettra à OpenCode d'analyser votre projet et de créer un fichier `AGENTS.md` à la racine du projet.

:::tip
Vous devez valider le fichier `AGENTS.md` de votre projet dans Git.
:::

Cela aide OpenCode à comprendre la structure du projet et les modèles de codage utilisés.

---

## Utilisation

Vous êtes maintenant prêt à utiliser OpenCode pour travailler sur votre projet. N'hésitez pas à lui demander n'importe quoi !

Si vous débutez dans l'utilisation d'un agent de codage IA, voici quelques exemples qui pourraient aider.

---

### Poser des questions

Vous pouvez demander à OpenCode de vous expliquer la base de code.

:::tip
Utilisez la touche `@` pour effectuer une recherche floue de fichiers dans le projet.
:::

```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```

Ceci est utile s'il y a une partie de la base de code sur laquelle vous n'avez pas travaillé.

---

### Ajouter des fonctionnalités

Vous pouvez demander à OpenCode d'ajouter de nouvelles fonctionnalités à votre projet. Cependant, nous recommandons d’abord de lui demander de créer un plan.

1. **Créer un plan**

OpenCode dispose d'un _Mode Plan_ qui désactive sa capacité à apporter des modifications et suggère plutôt _comment_ il implémentera la fonctionnalité.

Accédez-y à l'aide de la touche **Tab**. Vous verrez un indicateur à cet effet dans le coin inférieur droit.

```bash frame="none" title="Switch to Plan mode"
   <TAB>
```

Décrivons maintenant ce que nous voulons qu'il fasse.

```txt frame="none"
   When a user deletes a note, we'd like to flag it as deleted in the database.
   Then create a screen that shows all the recently deleted notes.
   From this screen, the user can undelete a note or permanently delete it.
```

Vous souhaitez donner à OpenCode suffisamment de détails pour comprendre ce que vous voulez. Ça aide pour lui parler comme si vous parliez à un développeur junior de votre équipe.

:::tip
Donnez à OpenCode beaucoup de contexte et d'exemples pour l'aider à comprendre ce que vous voulez.
:::

2. **Itérer sur le plan**

Une fois qu'il vous donne un plan, vous pouvez lui faire part de vos commentaires ou ajouter plus de détails.

```txt frame="none"
   We'd like to design this new screen using a design I've used before.
   [Image #1] Take a look at this image and use it as a reference.
```

:::tip
Glissez-déposez des images dans le terminal pour les ajouter à l'invite.
:::

OpenCode peut scanner toutes les images que vous lui donnez et les ajouter à l'invite. Vous pouvez le faire en glissant et en déposant une image dans le terminal.

3. **Créez la fonctionnalité**

Une fois que vous vous sentez à l'aise avec le plan, revenez au _Mode Build_ en appuyant à nouveau sur la touche **Tab**.

```bash frame="none"
   <TAB>
```

Et demandez-lui d'apporter les modifications.

```bash frame="none"
   Sounds good! Go ahead and make the changes.
```

---

### Apporter des modifications

Pour des modifications plus simples, vous pouvez demander à OpenCode de construire directement sans avoir à revoir le plan au préalable.

```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```

Vous devez fournir suffisamment de détails pour qu'OpenCode effectue les bonnes modifications.

---

### Annuler les modifications

Disons que vous demandez à OpenCode d'apporter quelques modifications.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

Mais vous réalisez que ce n’est pas ce que vous vouliez. Vous **pouvez annuler** les modifications à l'aide de la commande `/undo`.

```bash frame="none"
/undo
```

OpenCode annulera désormais les modifications que vous avez apportées et affichera votre message d'origine encore.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

À partir de là, vous pouvez modifier l'invite et demander à OpenCode de réessayer.

:::tip
Vous pouvez exécuter `/undo` plusieurs fois pour annuler plusieurs modifications.
:::

Ou vous **pouvez refaire** les modifications à l'aide de la commande `/redo`.

```bash frame="none"
/redo
```

---

## Personnaliser

Et c'est tout ! Vous êtes désormais un pro de l'utilisation de OpenCode.

Pour vous l'approprier, nous vous recommandons de [choisir un thème](/docs/themes), [de personnaliser les raccourcis clavier](/docs/keybinds), de [configurer les formateurs de code](/docs/formatters), de [créer des commandes personnalisées](/docs/commands) ou de jouer avec la [OpenCode Config](/docs/config).

---

### Packages Web Src Content Docs It Index (`packages/web/src/content/docs/it/index.mdx`)

---
title: Introduzione
description: Inizia con OpenCode.
---

import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console

[**OpenCode**](/) e un agente di programmazione AI open source. E disponibile come interfaccia per terminale, app desktop o estensione per IDE.



Iniziamo.

---

#### Prerequisiti

Per usare OpenCode nel terminale, ti serve:

1. Un emulatore di terminale moderno, come:
   - [WezTerm](https://wezterm.org), cross-platform
   - [Alacritty](https://alacritty.org), cross-platform
   - [Ghostty](https://ghostty.org), Linux and macOS
   - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux and macOS

2. Le chiavi API dei provider LLM che vuoi usare.

---

## Installa

Il modo piu semplice per installare OpenCode e usare lo script di installazione.

```bash
curl -fsSL https://opencode.ai/install | bash
```

Puoi anche installarlo con i seguenti comandi:

- **Con Node.js**

        <Tabs>

      <TabItem label="npm">
      ```bash
      npm install opencode-ai
      ```

          </TabItem>

        <TabItem label="Bun">
        ```bash
        bun install -g opencode-ai
        ```

          </TabItem>

        <TabItem label="pnpm">
        ```bash
        pnpm install opencode-ai
        ```

          </TabItem>

        <TabItem label="Yarn">
        ```bash
        yarn global add opencode-ai
        ```

      </TabItem>

  </Tabs>

- **Con Homebrew su macOS e Linux**

  ```bash
  brew install anomalyco/tap/opencode
  ```

  > Ti consigliamo di usare il tap di OpenCode per avere le release piu aggiornate. La formula ufficiale `brew install opencode` e mantenuta dal team Homebrew e viene aggiornata meno spesso.

- **Con Paru su Arch Linux**

  ```bash
  sudo pacman -S opencode           # Arch Linux (Stable)
  paru -S opencode-bin              # Arch Linux (Latest from AUR)
  ```

#### Windows

:::tip[Consigliato: usa WSL]
Per la migliore esperienza su Windows, ti consigliamo di usare [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). Offre prestazioni migliori e piena compatibilita con le funzionalita di OpenCode.
:::

- **Con Chocolatey**

  ```bash
  choco install opencode
  ```

- **Con Scoop**

  ```bash
  scoop install opencode
  ```

- **Con NPM**

  ```bash
  npm install opencode-ai
  ```

- **Con Mise**

  ```bash
  mise use -g github:anomalyco/opencode
  ```

- **Con Docker**

  ```bash
  docker run -it --rm ghcr.io/anomalyco/opencode
  ```

Il supporto per installare OpenCode su Windows usando Bun e attualmente in lavorazione.

Puoi anche scaricare il binario dalle [Releases](https://github.com/anomalyco/opencode/releases).

---

## Configura

Con OpenCode puoi usare qualsiasi provider LLM configurando le relative chiavi API.

Se e la prima volta che usi provider LLM, ti consigliamo [OpenCode Zen](https://opencode.ai/v2/docs/console/).
E una lista curata di modelli testati e verificati dal team di OpenCode.

1. Esegui il comando `/connect` nella TUI, seleziona opencode e vai su [opencode.ai/auth](https://opencode.ai/auth).

   ```txt
   /connect
   ```

2. Accedi, aggiungi i dettagli di fatturazione e copia la tua chiave API.

3. Incolla la tua chiave API.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

In alternativa, puoi selezionare uno degli altri provider. [Scopri di piu](/docs/providers#directory).

---

## Inizializza

Ora che hai configurato un provider, puoi spostarti in un progetto su cui vuoi lavorare.

```bash
cd /path/to/project
```

E avviare OpenCode.

```bash
opencode
```

Poi inizializza OpenCode per il progetto eseguendo il comando seguente.

```bash frame="none"
/init
```

Questo fara analizzare il progetto a OpenCode e creera un file `AGENTS.md` nella root del progetto.

:::tip
Dovresti committare il file `AGENTS.md` del progetto su Git.
:::

Questo aiuta OpenCode a capire la struttura del progetto e gli stili di codice usati.

---

## Utilizzo

Ora sei pronto a usare OpenCode sul tuo progetto. Sentiti libero di chiedergli qualsiasi cosa!

Se e la prima volta che usi un agente di programmazione AI, ecco alcuni esempi che possono aiutare.

---

### Fai domande

Puoi chiedere a OpenCode di spiegarti la codebase.

:::tip
Usa il tasto `@` per fare una ricerca fuzzy dei file nel progetto.
:::

```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```

Questo e utile se c'e una parte della codebase su cui non hai lavorato.

---

### Aggiungi funzionalità

Puoi chiedere a OpenCode di aggiungere nuove funzionalita al progetto. Pero ti consigliamo prima di chiedergli di creare un piano.

1. **Crea un piano**

   OpenCode ha una _Plan mode_ che disabilita la possibilita di fare modifiche e si limita a suggerire _come_ implementera la funzionalita.

   Passaci con il tasto **Tab**. Vedrai un indicatore nell'angolo in basso a destra.

   ```bash frame="none" title="Switch to Plan mode"
   <TAB>
   ```

   Ora descriviamo cosa vogliamo che faccia.

   ```txt frame="none"
   When a user deletes a note, we'd like to flag it as deleted in the database.
   Then create a screen that shows all the recently deleted notes.
   From this screen, the user can undelete a note or permanently delete it.
   ```

   Devi dare a OpenCode abbastanza dettagli per capire cosa vuoi. Aiuta parlargli come se stessi parlando a uno sviluppatore junior del tuo team.

   :::tip
   Dai a OpenCode molto contesto ed esempi per aiutarlo a capire cosa vuoi.
   :::

2. **Itera sul piano**

   Una volta che ti da un piano, puoi dargli feedback o aggiungere piu dettagli.

   ```txt frame="none"
   We'd like to design this new screen using a design I've used before.
   [Image #1] Take a look at this image and use it as a reference.
   ```

   :::tip
   Trascina e rilascia le immagini nel terminale per aggiungerle al prompt.
   :::

   OpenCode puo analizzare le immagini che gli dai e aggiungerle al prompt. Puoi farlo trascinando e rilasciando un'immagine nel terminale.

3. **Implementa la funzionalita**

   Quando ti senti a tuo agio con il piano, torna in _Build mode_ premendo di nuovo il tasto **Tab**.

   ```bash frame="none"
   <TAB>
   ```

   E chiedigli di fare le modifiche.

   ```bash frame="none"
   Sounds good! Go ahead and make the changes.
   ```

---

### Apporta modifiche

Per modifiche piu semplici, puoi chiedere a OpenCode di implementarle direttamente senza dover prima rivedere un piano.

```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```

Assicurati di fornire abbastanza dettagli, cosi OpenCode fa le modifiche giuste.

---

### Annulla modifiche

Mettiamo che tu chieda a OpenCode di fare alcune modifiche.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

Ma ti accorgi che non e quello che volevi. Puoi **annullare** le modifiche usando il comando `/undo`.

```bash frame="none"
/undo
```

OpenCode ora ripristina le modifiche e mostra di nuovo il tuo messaggio originale.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

Da qui puoi modificare il prompt e chiedere a OpenCode di riprovare.

:::tip
Puoi eseguire `/undo` piu volte per annullare piu modifiche.
:::

Oppure puoi **rifare** le modifiche usando il comando `/redo`.

```bash frame="none"
/redo
```

---

## Personalizza

E tutto qui! Ora sei un pro nell'usare OpenCode.

Per renderlo davvero tuo, ti consigliamo di [scegliere un tema](/docs/themes), [personalizzare i tasti rapidi](/docs/keybinds), [configurare i formatter](/docs/formatters), [creare comandi personalizzati](/docs/commands) o sperimentare con la [configurazione di OpenCode](/docs/config).

---

### Packages Web Src Content Docs Ja Index (`packages/web/src/content/docs/ja/index.mdx`)

---
title: はじめに
description: OpenCode を始めましょう。
---

import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console

[**OpenCode**](/) は、オープンソースの AI コーディングエージェントです。これは、ターミナルベースのインターフェイス、デスクトップアプリ、または IDE 拡張機能として利用できます。

を使用したOpenCode TUI

始めましょう。

---

#### 前提条件

ターミナルで OpenCode を使用するには、次のものが必要です。

1. 次のような最新のターミナルエミュレータ:
   - [WezTerm](https://wezterm.org)、クロスプラットフォーム
   - [Alacritty](https://alacritty.org)、クロスプラットフォーム
   - [Ghostty](https://ghostty.org)、Linux および macOS
   - [Kitty](https://sw.kovidgoyal.net/kitty/)、Linux および macOS

2. 使用する LLM プロバイダーの API キー。

---

## インストール

OpenCode をインストールする最も簡単な方法は、インストールスクリプトを使用することです。

```bash
curl -fsSL https://opencode.ai/install | bash
```

次のコマンドを使用してインストールすることもできます。

- **Node.js の使用**

        <Tabs>

      <TabItem label="npm">
      ```bash
      npm install opencode-ai
      ```

          </TabItem>

        <TabItem label="Bun">
        ```bash
        bun install -g opencode-ai
        ```

          </TabItem>

        <TabItem label="pnpm">
        ```bash
        pnpm install opencode-ai
        ```

          </TabItem>

        <TabItem label="Yarn">
        ```bash
        yarn global add opencode-ai
        ```

      </TabItem>

  </Tabs>

- **macOS および Linux での Homebrew の使用**

  ```bash
  brew install anomalyco/tap/opencode
  ```

  > 最新のリリースには OpenCode タップを使用することをお勧めします。公式の `brew install opencode` 式は Homebrew チームによって維持されており、更新頻度は低くなります。

- **Arch Linux での Paru の使用**

  ```bash
  sudo pacman -S opencode           # Arch Linux (Stable)
  paru -S opencode-bin              # Arch Linux (Latest from AUR)
  ```

#### Windows

:::tip[推奨: WSL を使用する]
Windows で最高のエクスペリエンスを得るには、[Windows Subsystem for Linux (WSL)](/docs/windows-wsl) を使用することをお勧めします。これにより、パフォーマンスが向上し、OpenCode の機能との完全な互換性が提供されます。
:::

- **Chocolatey の使用**

  ```bash
  choco install opencode
  ```

- **Scoop の使用**

  ```bash
  scoop install opencode
  ```

- **npm の使用**

  ```bash
  npm install opencode-ai
  ```

- **Mise の使用**

  ```bash
  mise use -g github:anomalyco/opencode
  ```

- **Docker の使用**

  ```bash
  docker run -it --rm ghcr.io/anomalyco/opencode
  ```

Bun を使用して Windows に OpenCode をインストールするためのサポートは現在進行中です。

[Releases](https://github.com/anomalyco/opencode/releases).

---

## 設定

OpenCode を使用すると、API キーを構成することで任意の LLM プロバイダーを使用できます。

LLM プロバイダーを初めて使用する場合は、[OpenCode Zen](https://opencode.ai/v2/docs/console/) をお勧めします。
これは、OpenCode チームによってテストおよび検証されたモデルの厳選されたリストです。

1. TUI で `/connect` コマンドを実行し、opencode を選択して、[opencode.ai/auth](https://opencode.ai/auth) で認証します。

   ```txt
   /connect
   ```

2. サインインし、お支払いの詳細を追加し、API キーをコピーします。

3. API キーを貼り付けます。

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

あるいは、他のプロバイダーのいずれかを選択することもできます。 [詳細はこちら](/docs/providers#directory)。

---

## 初期化

プロバイダーを構成したので、取り組みたいプロジェクトに移動できます。

```bash
cd /path/to/project
```

そしてOpenCodeを実行します。

```bash
opencode
```

次に、次のコマンドを実行して、プロジェクトの OpenCode を初期化します。

```bash frame="none"
/init
```

これにより、OpenCode がプロジェクトを分析し、プロジェクトのルートに `AGENTS.md` ファイルを作成します。

:::tip
プロジェクトの `AGENTS.md` ファイルを Git にコミットする必要があります。
:::

これは、OpenCode がプロジェクトの構造と使用されているコーディングパターンを理解するのに役立ちます。

---

## 使用法

これで、OpenCode を使用してプロジェクトに取り組む準備が整いました。何でもお気軽にお尋ねください！

AI コーディングエージェントを初めて使用する場合は、次の例を参考にしてください。

---

### 質問する

OpenCode にコードベースの説明を依頼できます。

:::tip
プロジェクト内のファイルをあいまい検索するには、`@` キーを使用します。
:::

```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```

これは、コードベースに作業していない部分がある場合に役立ちます。

---

### 機能を追加する

OpenCode に新しい機能をプロジェクトに追加するよう依頼できます。ただし、最初は計画の作成を依頼することをお勧めします。

1. **計画を作成する**

OpenCode には、変更を加える機能を無効にする _Plan mode_ があり、
代わりに、その機能を*どのように*実装するかを提案します。

**Tab** キーを使用してそれに切り替えます。右下隅にこれを示すインジケーターが表示されます。

```bash frame="none" title="Switch to Plan mode"
   <TAB>
```

では、何をしたいのかを説明しましょう。

```txt frame="none"
   When a user deletes a note, we'd like to flag it as deleted in the database.
   Then create a screen that shows all the recently deleted notes.
   From this screen, the user can undelete a note or permanently delete it.
```

自分が何を望んでいるのかを理解するために、OpenCode に十分な詳細を提供したいと考えています。
チームの若手開発者と話しているように話すと良いでしょう。

:::tip
OpenCode に多くのコンテキストと例を提供して、意図する内容を理解できるようにします。
:::

2. **計画を反復する**

計画が示されたら、フィードバックを送信したり、詳細を追加したりできます。

```txt frame="none"
   We'd like to design this new screen using a design I've used before.
   [Image #1] Take a look at this image and use it as a reference.
```

:::tip
画像をターミナルにドラッグアンドドロップして、プロンプトに追加します。
:::

OpenCode は、指定された画像をスキャンしてプロンプトに追加できます。
画像をターミナルにドラッグアンドドロップしてこれを行うことができます。

3. **機能を構築する**

計画に慣れたら、*Build mode*に戻ります。
**Tab** キーをもう一度押します。

```bash frame="none"
   <TAB>
```

そして変更を加えるように依頼します。

```bash frame="none"
   Sounds good! Go ahead and make the changes.
```

---

### 変更を加える

より単純な変更については、OpenCode に直接ビルドするよう依頼できます。
最初に計画を見直す必要はありません。

```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```

OpenCode が適切な変更を行えるように、十分な量の詳細を確実に提供する必要があります。

---

### 変更を元に戻す

OpenCode にいくつかの変更を依頼するとします。

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

しかし、それは自分が望んでいたものではないことに気づきます。変更は **元に戻すことができます**
`/undo` コマンドを使用します。

```bash frame="none"
/undo
```

OpenCode は加えた変更を元に戻し、元のメッセージを再度表示します。

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

ここからプロンプトを調整し、OpenCode に再試行を依頼できます。

:::tip
`/undo` を複数回実行すると、複数の変更を元に戻すことができます。
:::

または、`/redo` コマンドを使用して変更を**やり直す**こともできます。

```bash frame="none"
/redo
```

---

## カスタマイズ

それで終わりです！これであなたは OpenCode の使い方のプロになりました。

独自のものにするには、[テーマ](/docs/themes) を選択する、[キーバインドをカスタマイズする](/docs/keybinds)、[コードフォーマッタ](/docs/formatters) を設定する、[カスタムコマンド](/docs/commands) を作成する、または [OpenCode設定](/docs/config) を試してみることをお勧めします。

---

### Packages Web Src Content Docs Ko Index (`packages/web/src/content/docs/ko/index.mdx`)

---
title: 소개
description: OpenCode를 시작해 보세요.
---

import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console

[**OpenCode**](/)는 오픈 소스 AI coding agent입니다. 터미널 기반 인터페이스, 데스크톱 앱, IDE 확장으로 사용할 수 있습니다.



바로 시작해 보겠습니다.

---

#### 사전 준비

터미널에서 OpenCode를 사용하려면 다음이 필요합니다.

1. 다음과 같은 최신 터미널 에뮬레이터
   - [WezTerm](https://wezterm.org), 크로스 플랫폼
   - [Alacritty](https://alacritty.org), 크로스 플랫폼
   - [Ghostty](https://ghostty.org), Linux 및 macOS
   - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux 및 macOS

2. 사용할 LLM 제공자의 API 키

---

## 설치

OpenCode를 설치하는 가장 쉬운 방법은 설치 스크립트를 사용하는 것입니다.

```bash
curl -fsSL https://opencode.ai/install | bash
```

다음 명령으로도 설치할 수 있습니다.

- **Node.js 사용**

        <Tabs>

      <TabItem label="npm">
      ```bash
      npm install opencode-ai
      ```

          </TabItem>

        <TabItem label="Bun">
        ```bash
        bun install -g opencode-ai
        ```

          </TabItem>

        <TabItem label="pnpm">
        ```bash
        pnpm install opencode-ai
        ```

          </TabItem>

        <TabItem label="Yarn">
        ```bash
        yarn global add opencode-ai
        ```

      </TabItem>

  </Tabs>

- **macOS/Linux에서 Homebrew 사용**

  ```bash
  brew install anomalyco/tap/opencode
  ```

  > 최신 릴리스를 사용하려면 OpenCode tap 사용을 권장합니다. 공식 `brew install opencode` formula는 Homebrew 팀이 관리하며 업데이트 주기가 더 깁니다.

- **Arch Linux에 설치**

  ```bash
  sudo pacman -S opencode           # Arch Linux (Stable)
  paru -S opencode-bin              # Arch Linux (Latest from AUR)
  ```

#### Windows

:::tip[권장: WSL 사용]
Windows에서는 [Windows Subsystem for Linux (WSL)](/docs/windows-wsl) 사용을 권장합니다. 성능이 더 좋고 OpenCode 기능과의 완전한 호환성을 제공합니다.
:::

- **Chocolatey 사용**

  ```bash
  choco install opencode
  ```

- **Scoop 사용**

  ```bash
  scoop install opencode
  ```

- **NPM 사용**

  ```bash
  npm install opencode-ai
  ```

- **Mise 사용**

  ```bash
  mise use -g github:anomalyco/opencode
  ```

- **Docker 사용**

  ```bash
  docker run -it --rm ghcr.io/anomalyco/opencode
  ```

현재 Windows에서 Bun을 사용한 OpenCode 설치 지원은 준비 중입니다.

[Releases](https://github.com/anomalyco/opencode/releases)에서 바이너리를 직접 받아 설치할 수도 있습니다.

---

## 구성

OpenCode는 API 키를 설정하면 원하는 LLM 제공자를 사용할 수 있습니다.

LLM 제공자를 처음 사용한다면 [OpenCode Zen](https://opencode.ai/v2/docs/console/) 사용을 권장합니다.
OpenCode 팀이 테스트하고 검증한 모델 목록입니다.

1. TUI에서 `/connect` 명령을 실행하고 `opencode`를 선택한 다음 [opencode.ai/auth](https://opencode.ai/auth)로 이동합니다.

   ```txt
   /connect
   ```

2. 로그인하고 결제 정보를 추가한 뒤 API 키를 복사합니다.

3. API 키를 붙여 넣습니다.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

또는 다른 제공자 중 하나를 선택할 수도 있습니다. [더 알아보기](/docs/providers#directory).

---

## 초기화

이제 제공자 구성을 마쳤으니 작업하려는 프로젝트로 이동합니다.

```bash
cd /path/to/project
```

그리고 OpenCode를 실행합니다.

```bash
opencode
```

다음 명령을 실행해 프로젝트에서 OpenCode를 초기화합니다.

```bash frame="none"
/init
```

이 명령을 실행하면 OpenCode가 프로젝트를 분석하고 프로젝트 루트에 `AGENTS.md` 파일을 생성합니다.

:::tip
프로젝트의 `AGENTS.md` 파일은 Git에 커밋하는 것을 권장합니다.
:::

이렇게 하면 OpenCode가 프로젝트 구조와 사용 중인 코딩 패턴을 더 잘 이해할 수 있습니다.

---

## 사용법

이제 OpenCode로 프로젝트 작업을 시작할 준비가 되었습니다. 무엇이든 물어보세요.

AI coding agent를 처음 사용한다면 도움이 될 수 있는 예시를 소개합니다.

---

### 질문하기

OpenCode에 코드베이스 설명을 요청할 수 있습니다.

:::tip
프로젝트 파일은 `@` 키로 퍼지 검색할 수 있습니다.
:::

```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```

이 방법은 직접 작업하지 않은 코드 영역을 이해할 때 유용합니다.

---

### 기능 추가

OpenCode에 프로젝트의 새 기능 추가를 요청할 수 있습니다. 다만 먼저 계획을 만들도록 요청하는 것을 권장합니다.

1. **계획 만들기**

   OpenCode에는 변경 작업 기능을 비활성화하고 기능을 구현할 방법만 제안하는 *Plan mode*가 있습니다.

   **Tab** 키를 눌러 전환하세요. 화면 오른쪽 아래에서 모드 표시를 확인할 수 있습니다.

   ```bash frame="none" title="Switch to Plan mode"
   <TAB>
   ```

   이제 수행하길 원하는 작업을 설명해 보겠습니다.

   ```txt frame="none"
   When a user deletes a note, we'd like to flag it as deleted in the database.
   Then create a screen that shows all the recently deleted notes.
   From this screen, the user can undelete a note or permanently delete it.
   ```

   OpenCode가 원하는 작업을 이해할 수 있도록 충분한 세부 정보를 제공해야 합니다. 팀의 주니어 개발자에게 말하듯이 설명하면 도움이 됩니다.

   :::tip
   OpenCode가 원하는 작업을 이해하도록 충분한 맥락과 예시를 제공하세요.
   :::

2. **계획 다듬기**

   계획이 나오면 피드백을 주거나 세부 사항을 더 추가할 수 있습니다.

   ```txt frame="none"
   We'd like to design this new screen using a design I've used before.
   [Image #1] Take a look at this image and use it as a reference.
   ```

   :::tip
   이미지를 터미널에 드래그 앤 드롭해 prompt에 추가하세요.
   :::

   OpenCode는 제공한 이미지를 스캔해 prompt에 추가할 수 있습니다. 이미지를 터미널에 드래그 앤 드롭하면 됩니다.

3. **기능 구현**

   계획이 충분히 마음에 들면 **Tab** 키를 다시 눌러 *Build mode*로 전환하세요.

   ```bash frame="none"
   <TAB>
   ```

   그리고 변경을 적용해 달라고 요청하세요.

   ```bash frame="none"
   Sounds good! Go ahead and make the changes.
   ```

---

### 바로 변경하기

비교적 간단한 변경은 계획을 먼저 검토하지 않고 바로 구현하도록 요청할 수 있습니다.

```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```

OpenCode가 올바른 변경을 하도록 충분한 세부 정보를 제공해야 합니다.

---

### 변경 되돌리기

예를 들어 OpenCode에 변경을 요청했다고 해보겠습니다.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

그런데 원하는 결과가 아니었다면 `/undo` 명령으로 변경을 **되돌릴 수** 있습니다.

```bash frame="none"
/undo
```

OpenCode가 방금 적용한 변경을 되돌리고 원래 메시지를 다시 보여줍니다.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

여기에서 prompt를 수정해 다시 요청할 수 있습니다.

:::tip
`/undo`는 여러 번 연속으로 실행할 수 있습니다.
:::

또는 `/redo` 명령으로 변경을 **다시 적용**할 수 있습니다.

```bash frame="none"
/redo
```

---

## 사용자 지정

이제 OpenCode 사용법을 익혔습니다.

원하는 방식에 맞추려면 [테마 선택](/docs/themes), [키바인드 사용자 지정](/docs/keybinds), [코드 formatter 설정](/docs/formatters), [custom command 만들기](/docs/commands), [OpenCode config 설정](/docs/config)을 권장합니다.

---

### Packages Web Src Content Docs Nb Index (`packages/web/src/content/docs/nb/index.mdx`)

---
title: Introduksjon
description: Kom i gang med OpenCode.
---

import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console

[**OpenCode**](/) er en åpen kildekode AI kodeagent. Den er tilgjengelig som et terminalbasert grensesnitt, skrivebordsapp eller IDE-utvidelse.



La oss komme i gang.

---

#### Forutsetninger

For å bruke OpenCode i terminalen din trenger du:

1. En moderne terminalemulator som:
   - [WezTerm](https://wezterm.org), på tvers av plattformer
   - [Alacritty](https://alacritty.org), på tvers av plattformer
   - [Ghostty](https://ghostty.org), Linux og macOS
   - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux og macOS

2. API-nøkler for LLM-leverandørene du vil bruke.

---

## Installasjon

Den enkleste måten å installere OpenCode på er gjennom installasjonsskriptet.

```bash
curl -fsSL https://opencode.ai/install | bash
```

Du kan også installere den med følgende kommandoer:

- **Bruke Node.js**

        <Tabs>

      <TabItem label="npm">
      ```bash
      npm install opencode-ai
      ```

          </TabItem>

        <TabItem label="Bun">
        ```bash
        bun install -g opencode-ai
        ```

          </TabItem>

        <TabItem label="pnpm">
        ```bash
        pnpm install opencode-ai
        ```

          </TabItem>

        <TabItem label="Yarn">
        ```bash
        yarn global add opencode-ai
        ```

      </TabItem>

  </Tabs>

- **Bruke Homebrew på macOS og Linux**

  ```bash
  brew install anomalyco/tap/opencode
  ```

  > Vi anbefaler å bruke OpenCode-tappen for de mest oppdaterte utgivelsene. Den offisielle `brew install opencode`-formelen vedlikeholdes av Homebrew-teamet og oppdateres sjeldnere.

- **Bruke Paru på Arch Linux**

  ```bash
  sudo pacman -S opencode           # Arch Linux (Stable)
  paru -S opencode-bin              # Arch Linux (Latest from AUR)
  ```

#### Windows

:::tip[Anbefalt: Bruk WSL]
For den beste opplevelsen på Windows anbefaler vi å bruke [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). Det gir bedre ytelse og full kompatibilitet med funksjonene i OpenCode.
:::

- **Bruke Chocolatey**

  ```bash
  choco install opencode
  ```

- **Bruke Scoop**

  ```bash
  scoop install opencode
  ```

- **Bruke npm**

  ```bash
  npm install opencode-ai
  ```

- **Bruke Mise**

  ```bash
  mise use -g github:anomalyco/opencode
  ```

- **Bruke Docker**

  ```bash
  docker run -it --rm ghcr.io/anomalyco/opencode
  ```

Støtte for installasjon av OpenCode på Windows med Bun er under arbeid.

Du kan også hente binæren fra [Releases](https://github.com/anomalyco/opencode/releases).

---

## Konfigurasjon

Med OpenCode kan du bruke hvilken som helst LLM-leverandør ved å konfigurere deres API-nøkler.

Hvis du er ukjent med LLM-leverandører, anbefaler vi å bruke [OpenCode Zen](https://opencode.ai/v2/docs/console/).
Det er en kuratert liste over modeller som har blitt testet og verifisert av OpenCode-teamet.

1. Kjør kommandoen `/connect` i TUI, velg OpenCode og gå til [opencode.ai/auth](https://opencode.ai/auth).

   ```txt
   /connect
   ```

2. Logg på, legg til faktureringsdetaljene dine og kopier API-nøkkelen.

3. Lim inn API-nøkkelen.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

Alternativt kan du velge en av de andre leverandørene. [Finn ut mer](/docs/providers#directory).

---

## Initialisering

Nå som du har konfigurert en leverandør, kan du navigere til et prosjekt som
du vil jobbe med.

```bash
cd /path/to/project
```

Og kjør OpenCode.

```bash
opencode
```

Deretter initialiserer du OpenCode for prosjektet ved å kjøre følgende kommando.

```bash frame="none"
/init
```

Dette vil få OpenCode til å analysere prosjektet ditt og opprette en `AGENTS.md`-fil i
prosjektroten.

:::tip
Du bør overgi prosjektets `AGENTS.md`-fil til Git.
:::

Dette hjelper OpenCode med å forstå prosjektstrukturen og kodingsmønstrene
brukt.

---

## Bruk

Du er nå klar til å bruke OpenCode for å jobbe med prosjektet ditt. Spør det gjerne
noe!

Hvis du er ukjent med AI-kodeagenter, her er noen eksempler som kan
hjelpe.

---

### Still spørsmål

Du kan be OpenCode forklare kodebasen for deg.

:::tip
Bruk `@`-tasten for uklart søk etter filer i prosjektet.
:::

```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```

Dette er nyttig hvis det er en del av kodebasen du ikke har jobbet med.

---

### Legg til funksjonalitet

Du kan be OpenCode legge til nye funksjoner i prosjektet ditt. Selv om vi først anbefaler å be den om å lage en plan.

1. **Lag en plan**

   OpenCode har en _Plan-modus_ som deaktiverer muligheten til å gjøre endringer og
   foreslår i stedet _hvordan_ den vil implementere funksjonen.

   Bytt til den ved å bruke **Tab**-tasten. Du vil se en indikator for dette i nedre høyre hjørne.

   ```bash frame="none" title="Switch to Plan mode"
   <TAB>
   ```

   La oss nå beskrive hva vi vil at den skal gjøre.

   ```txt frame="none"
   When a user deletes a note, we'd like to flag it as deleted in the database.
   Then create a screen that shows all the recently deleted notes.
   From this screen, the user can undelete a note or permanently delete it.
   ```

   Du bør gi OpenCode nok detaljer til å forstå hva du ønsker. Det hjelper
   å snakke med det som om du snakker med en juniorutvikler på laget ditt.

   :::tip
   Gi OpenCode mye kontekst og eksempler for å hjelpe den å forstå hva du
   ønsker.
   :::

2. **Iterer på planen**

   Når du får en plan, kan du gi den tilbakemelding eller legge til flere detaljer.

   ```txt frame="none"
   We'd like to design this new screen using a design I've used before.
   [Image #1] Take a look at this image and use it as a reference.
   ```

   :::tip
   Dra og slipp bilder i terminalen for å legge dem til ledeteksten.
   :::

   OpenCode kan skanne alle bilder du gir den og legge dem til i ledeteksten. Du kan
   gjør dette ved å dra og slippe et bilde inn i terminalen.

3. **Bygg funksjonen**

   Når du føler deg komfortabel med planen, bytt tilbake til _Byggemodus_ ved å
   trykke på **Tab**-tasten igjen.

   ```bash frame="none"
   <TAB>
   ```

   Og be den om å gjøre endringene.

   ```bash frame="none"
   Sounds good! Go ahead and make the changes.
   ```

---

### Gjør endringer

For mer enkle endringer kan du be OpenCode om å bygge det direkte
uten å måtte gjennomgå planen først.

```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```

Sørg for å gi nok detaljer, slik at OpenCode gjør de rette
endringene.

---

### Angre endringer

La oss si at du ber OpenCode om å gjøre noen endringer.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

Men du skjønner at det ikke er det du ønsket. Du **kan angre** endringene
ved å bruke kommandoen `/undo`.

```bash frame="none"
/undo
```

OpenCode vil nå tilbakestille endringene du har gjort og vise den opprinnelige meldingen
igjen.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

Herfra kan du justere ledeteksten og be OpenCode om å prøve igjen.

:::tip
Du kan kjøre `/undo` flere ganger for å angre flere endringer.
:::

Eller du **kan gjøre om** endringene ved å bruke `/redo`-kommandoen.

```bash frame="none"
/redo
```

---

## Tilpasning

Og det er det! Du er nå en proff på å bruke OpenCode.

For å tilpasse det anbefaler vi å [velge et tema](/docs/themes), [tilpasse tastebindingene](/docs/keybinds), [konfigurere kodeformattere](/docs/formatters), [opprette egendefinerte kommandoer](/docs/commands) eller leke med [OpenCode-konfigurasjonen](/docs/config).

---

### Packages Web Src Content Docs Pl Index (`packages/web/src/content/docs/pl/index.mdx`)

---
title: Wstęp
description: Zacznij pracę z opencode.
---

import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console

[**opencode**](/) to agent kodujący AI typu open source. Jest dostępny jako interfejs terminalowy, aplikacja desktopowa i rozszerzenie IDE.



Zacznijmy.

---

#### Warunki wstępne

Aby uzyskać dostęp do opencode w swoim terminalu, będziesz potrzebować:

1. Nowoczesny emulator terminala, taki jak:
   - [WezTerm](https://wezterm.org), wieloplatformowy
   - [Alacritty](https://alacritty.org), wieloplatformowy
   - [Ghostty](https://ghostty.org), Linux i macOS
   - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux i macOS

2. Klucze API dla dostawców LLM, z których korzystasz.

---

## Instalacja

Najłatwiej zainstalować opencode za pomocą skryptu instalacyjnego.

```bash
curl -fsSL https://opencode.ai/install | bash
```

Możesz też użyć poniższych metod instalacji:

- **Przy użyciu Node.js**

        <Tabs>

      <TabItem label="npm">
      ```bash
      npm install opencode-ai
      ```

          </TabItem>

        <TabItem label="Bun">
        ```bash
        bun install -g opencode-ai
        ```

          </TabItem>

        <TabItem label="pnpm">
        ```bash
        pnpm install opencode-ai
        ```

          </TabItem>

        <TabItem label="Yarn">
        ```bash
        yarn global add opencode-ai
        ```

      </TabItem>

  </Tabs>

- **Korzystanie z Homebrew na macOS i Linux**

  ```bash
  brew install anomalyco/tap/opencode
  ```

  > W celu uzyskania najbardziej aktualnej wersji zalecamy korzystanie z opencode. Oficjalna formuła `brew install opencode` jest utrzymywana przez zespół Homebrew i jest aktualizowana.

- **Korzystanie z Paru na Arch Linux**

  ```bash
  sudo pacman -S opencode           # Arch Linux (Stable)
  paru -S opencode-bin              # Arch Linux (Latest from AUR)
  ```

#### Windows

:::tip[Zalecane: Uruchamianie w WSL]
Aby najlepiej wykorzystać działanie w systemie Windows, zalecamy włączenie [Podsystemu Windows dla systemu Linux (WSL)](/docs/windows-wsl). Zapewnia to pełną kompatybilność z funkcjami opencode.
:::

- **Używając Chocolatey**

  ```bash
  choco install opencode
  ```

- **Korzystanie z Scoop**

  ```bash
  scoop install opencode
  ```

- **Przy użyciu NPM**

  ```bash
  npm install opencode-ai
  ```

- **Używając Mise’a**

  ```bash
  mise use -g github:anomalyco/opencode
  ```

- **Korzystanie z Dockera**

  ```bash
  docker run -it --rm ghcr.io/anomalyco/opencode
  ```

Obecnie pracujemy nad instalacją opencode w systemie Windows za pomocą Bun.

Możesz także pobrać plik binarny z [Releases](https://github.com/anomalyco/opencode/releases).

---

## Konfiguracja

Dzięki opencode możesz korzystać z dowolnego dostawcy LLM, konfigurując jego klucze API.

Jeśli będziesz korzystać z wielu dostawców LLM, zalecamy skorzystanie z [OpenCode Zen](https://opencode.ai/v2/docs/console/).
Aby uzyskać dostęp do wyselekcjonowanej listy modeli, które zostały zatwierdzone i zweryfikowane przez zespół opencode.

1. Uruchom polecenie `/connect` w TUI, wybierz opencode i przejdź do [opencode.ai/auth](https://opencode.ai/auth).

   ```txt
   /connect
   ```

2. Zaloguj się, dodaj szczegóły rozliczeniowe i skopiuj klucz API.

3. Wklej swój klucz API.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

Alternatywnie możesz wybrać jednego z dodatkowych dostawców. [Dowiedz się więcej](/docs/providers#directory).

---

## Inicjalizacja

Po skonfigurowaniu dostawcy możesz przejść do projektu, nad którym chcesz pracować.

```bash
cd /path/to/project
```

Uruchom opencode.

```bash
opencode
```

Następnie zainicjuj opencode dla projektu, uruchamiając odpowiednie polecenie.

```bash frame="none"
/init
```

Spowoduje to, że opencode przeanalizuje Twój projekt i utworzy plik `AGENTS.md` w katalogu głównym projektu.

:::tip
Powinieneś zacommitować plik `AGENTS.md` swojego projektu w Git.
:::

Pomaga to opencode zrozumieć strukturę projektu i stosowane wzorce kodowania.

---

## Użycie

Teraz możesz pracować nad swoim projektem. Możesz zapytać o wszystko!

Jeśli dopiero zaczynasz korzystać z agenta kodującego AI, oto kilka wskazówek, które mogą być pomocne.

---

### Zadawaj pytania

Możesz poprosić opencode o wyjaśnienie bazy kodu.

:::tip
Użyj `@` do wyszukiwania rozmytego plików w projekcie.
:::

```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```

Jest to pomocne, jeśli istnieje część bazy kodu, nad którą nie pracowałeś.

---

### Dodaj funkcje

Możesz poprosić opencode o dodanie nowej funkcji do Twojego projektu. Najpierw zalecamy poproszenie o przygotowanie planu.

1. **Stwórz Plan**

   opencode ma _Plan Mode_, który umożliwia wyłączenie zmian i
   zamiast tego zasugeruje, jak zaimplementować tę funkcję.

   Przejdź do niego za pomocą klawisza **Tab**. Zobaczysz odpowiedni wskaźnik w prawym dolnym rogu.

   ```bash frame="none" title="Switch to Plan mode"
   <TAB>
   ```

   Opiszmy teraz, co chcemy, żeby zrobił.

   ```txt frame="none"
   When a user deletes a note, we'd like to flag it as deleted in the database.
   Then create a screen that shows all the recently deleted notes.
   From this screen, the user can undelete a note or permanently delete it.
   ```

   Wersja opencode jest bardzo inteligentna, aby zrozumieć, czego chcesz. To pomaga
   rozmawiaj z nim tak, jakbyś rozmawiał z młodszym programistą w swoim zespole.

   :::tip
   Podaj opencode kontekst, aby zrozumiał, czego chcesz.
   :::

2. **Udoskonalanie planu**

   Gdy będziesz mieć plan, możesz zostawić go lub dodać więcej.

   ```txt frame="none"
   We'd like to design this new screen using a design I've used before.
   [Image #1] Take a look at this image and use it as a reference.
   ```

   :::tip
   Przeciągnij i upuść obrazy do terminala, aby dodać je do monitu.
   :::

   opencode może zeskanować obrazy, które mu przekażesz i zrozumieć je. Możesz to zrobić, przeciągając i upuszczając obraz do terminala.

3. **Wprowadź zmiany**

   Kiedy już będziesz zadowolony z planu, przełącz się z powrotem do _Act Mode_ naciskając klawisz **Tab**.

   ```bash frame="none"
   <TAB>
   ```

   Poproś o wprowadzenie zmian.

   ```bash frame="none"
   Sounds good! Go ahead and make the changes.
   ```

---

### Wprowadź zmiany

Aby wprowadzić kolejną zmianę, możesz poprosić opencode lub zrobić to bezpośrednio bez konieczności wcześniejszego przeglądania planu.

```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```

Musisz upewnić się, że dostarczyłeś odpowiednie pliki, aby opencode mógł wprowadzić zmiany.

---

### Cofnij zmiany

Załóżmy, że prosisz opencode o wprowadzenie zmian.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

Ale zdajesz sobie sprawę, że to nie jest to, czego chciałeś. **Możesz cofnąć** zmiany
za pomocą polecenia `/undo`.

```bash frame="none"
/undo
```

opencode cofnie teraz zmiany i wyświetli wiadomość ponownie.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

Możesz edytować monit i poprosić opencode o ponowną próbę.

:::tip
Możesz użyć `/undo` wiele razy, aby cofnąć wiele zmian.
:::

Możesz też **przywrócić** zmianę za pomocą polecenia `/redo`.

```bash frame="none"
/redo
```

---

## Dostosuj

To tyle! Jesteś teraz profesjonalistą w korzystaniu z opencode.

Aby dostosować go do potrzeb, zalecamy [wybranie motywu](/docs/themes), [dostosowanie skrótów klawiaturowych](/docs/keybinds), [konfigurowanie programów formatujących kod](/docs/formatters), [tworzenie niestandardowych poleceń](/docs/commands) lub zabawę z [konfiguracją opencode](/docs/config).

---

### Packages Web Src Content Docs Pt Br Index (`packages/web/src/content/docs/pt-br/index.mdx`)

---
title: Introdução
description: Comece a usar o opencode.
---

import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console

[**opencode**](/) é um agente de codificação de IA de código aberto. Está disponível como uma interface baseada em terminal, aplicativo desktop ou extensão de IDE.



Vamos começar.

---

#### Pré-requisitos

Para usar o opencode no seu terminal, você precisará de:

1. Um emulador de terminal moderno como:
   - [WezTerm](https://wezterm.org), multiplataforma
   - [Alacritty](https://alacritty.org), multiplataforma
   - [Ghostty](https://ghostty.org), Linux e macOS
   - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux e macOS

2. Chaves de API para os provedores de LLM que você deseja usar.

---

## Instalação

A maneira mais fácil de instalar o opencode é através do script de instalação.

```bash
curl -fsSL https://opencode.ai/install | bash
```

Você também pode instalá-lo com os seguintes comandos:

- **Usando Node.js**

        <Tabs>

      <TabItem label="npm">
      ```bash
      npm install opencode-ai
      ```

          </TabItem>

        <TabItem label="Bun">
        ```bash
        bun install -g opencode-ai
        ```

          </TabItem>

        <TabItem label="pnpm">
        ```bash
        pnpm install opencode-ai
        ```

          </TabItem>

        <TabItem label="Yarn">
        ```bash
        yarn global add opencode-ai
        ```

      </TabItem>

  </Tabs>

- **Usando Homebrew no macOS e Linux**

  ```bash
  brew install anomalyco/tap/opencode
  ```

  > Recomendamos usar o tap do opencode para as versões mais atualizadas. A fórmula oficial `brew install opencode` é mantida pela equipe do Homebrew e é atualizada com menos frequência.

- **Usando Paru no Arch Linux**

  ```bash
  sudo pacman -S opencode           # Arch Linux (Stable)
  paru -S opencode-bin              # Arch Linux (Latest from AUR)
  ```

#### Windows

:::tip[Recomendado: Use WSL]
Para a melhor experiência no Windows, recomendamos usar o [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). Ele oferece melhor desempenho e total compatibilidade com os recursos do opencode.
:::

- **Usando Chocolatey**

  ```bash
  choco install opencode
  ```

- **Usando Scoop**

  ```bash
  scoop install opencode
  ```

- **Usando NPM**

  ```bash
  npm install opencode-ai
  ```

- **Usando Mise**

  ```bash
  mise use -g github:anomalyco/opencode
  ```

- **Usando Docker**

  ```bash
  docker run -it --rm ghcr.io/anomalyco/opencode
  ```

O suporte para instalar o opencode no Windows usando Bun está atualmente em andamento.

Você também pode baixar o binário na seção [Releases](https://github.com/anomalyco/opencode/releases).

---

## Configuração

Com o opencode, você pode usar qualquer provedor de LLM configurando suas chaves de API.

Se você é novo no uso de provedores de LLM, recomendamos usar o [OpenCode Zen](https://opencode.ai/v2/docs/console/).
É uma lista selecionada de modelos que foram testados e verificados pela equipe do opencode.

1. Execute o comando `/connect` no TUI, selecione opencode e acesse [opencode.ai/auth](https://opencode.ai/auth).

   ```txt
   /connect
   ```

2. Faça login, adicione seus dados de cobrança e copie sua chave de API.

3. Cole sua chave de API.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

Alternativamente, você pode selecionar um dos outros provedores. [Saiba mais](/docs/providers#directory).

---

## Inicialização

Agora que você configurou um provedor, pode navegar até um projeto no qual deseja trabalhar.

```bash
cd /path/to/project
```

E execute o opencode.

```bash
opencode
```

Em seguida, inicialize o opencode para o projeto executando o seguinte comando.

```bash frame="none"
/init
```

Isso fará com que o opencode analise seu projeto e crie um arquivo `AGENTS.md` na raiz do projeto.

:::tip
Você deve commitar o arquivo `AGENTS.md` do seu projeto no Git.
:::

Isso ajuda o opencode a entender a estrutura do projeto e os padrões de codificação utilizados.

---

## Uso

Agora você está pronto para usar o opencode para trabalhar em seu projeto. Sinta-se à vontade para perguntar qualquer coisa!

Se você é novo no uso de um agente de codificação de IA, aqui estão alguns exemplos que podem ajudar.

---

### Fazendo perguntas

Você pode pedir ao opencode para explicar a base de código para você.

:::tip
Use a tecla `@` para buscar arquivos no projeto.
:::

```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```

Isso é útil se houver uma parte da base de código na qual você não trabalhou.

---

### Adicionando recursos

Você pode pedir ao opencode para adicionar novos recursos ao seu projeto. Embora primeiro recomendemos pedir para ele criar um plano.

1. **Criar um plano**

   O opencode tem um _Modo de Plano_ que desabilita sua capacidade de fazer alterações e, em vez disso, sugere _como_ implementará o recurso.

   Mude para ele usando a tecla **Tab**. Você verá um indicador para isso no canto inferior direito.

   ```bash frame="none" title="Switch to Plan mode"
   <TAB>
   ```

   Agora vamos descrever o que queremos que ele faça.

   ```txt frame="none"
   When a user deletes a note, we'd like to flag it as deleted in the database.
   Then create a screen that shows all the recently deleted notes.
   From this screen, the user can undelete a note or permanently delete it.
   ```

   Você quer dar ao opencode detalhes suficientes para entender o que você deseja. Ajuda conversar com ele como se você estivesse falando com um desenvolvedor júnior da sua equipe.

   :::tip
   Dê ao opencode bastante contexto e exemplos para ajudá-lo a entender o que você deseja.
   :::

2. **Iterar sobre o plano**

   Uma vez que ele lhe der um plano, você pode dar feedback ou adicionar mais detalhes.

   ```txt frame="none"
   We'd like to design this new screen using a design I've used before.
   [Image #1] Take a look at this image and use it as a reference.
   ```

   :::tip
   Arraste e solte imagens no terminal para adicioná-las ao prompt.
   :::

   O opencode pode escanear qualquer imagem que você fornecer e adicioná-la ao prompt. Você pode fazer isso arrastando e soltando uma imagem no terminal.

3. **Construir o recurso**

   Uma vez que você se sinta confortável com o plano, volte para o _Modo de Construção_ pressionando a tecla **Tab** novamente.

   ```bash frame="none"
   <TAB>
   ```

   E peça para ele fazer as alterações.

   ```bash frame="none"
   Sounds good! Go ahead and make the changes.
   ```

---

### Fazendo alterações

Para alterações mais simples, você pode pedir ao opencode para construí-las diretamente sem precisar revisar o plano primeiro.

```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```

Você quer ter certeza de fornecer uma boa quantidade de detalhes para que o opencode faça as alterações corretas.

---

### Desfazendo alterações

Vamos supor que você peça ao opencode para fazer algumas alterações.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

Mas você percebe que não era isso que você queria. Você **pode desfazer** as alterações usando o comando `/undo`.

```bash frame="none"
/undo
```

O opencode agora reverterá as alterações que você fez e mostrará sua mensagem original novamente.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

A partir daqui, você pode ajustar o prompt e pedir ao opencode para tentar novamente.

:::tip
Você pode executar `/undo` várias vezes para desfazer várias alterações.
:::

Ou você **pode refazer** as alterações usando o comando `/redo`.

```bash frame="none"
/redo
```

---

## Personalização

E é isso! Agora você é um profissional em usar o opencode.

Para torná-lo seu, recomendamos [escolher um tema](/docs/themes), [personalizar os atalhos de teclado](/docs/keybinds), [configurar formatadores de código](/docs/formatters), [criar comandos personalizados](/docs/commands) ou brincar com a [configuração do opencode](/docs/config).

---

### Packages Web Src Content Docs Ru Index (`packages/web/src/content/docs/ru/index.mdx`)

---
title: Введение
description: Начните работу с opencode.
---

import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console

[**opencode**](/) — это агент кодирования искусственного интеллекта с открытым исходным кодом. Он доступен в виде интерфейса на базе терминала, настольного приложения или расширения IDE.



Давайте начнем.

---

#### Системные требования

Чтобы использовать opencode в вашем терминале, вам понадобится:

1. Современный эмулятор терминала, например:
   - [WezTerm](https://wezterm.org), кроссплатформенный
   - [Alacritty](https://alacritty.org), кроссплатформенный
   - [Ghostty](https://ghostty.org), Linux и macOS
   - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux и macOS

2. Ключи API для поставщиков LLM, которых вы хотите использовать.

---

## Установка

Самый простой способ установить opencode — через сценарий установки.

```bash
curl -fsSL https://opencode.ai/install | bash
```

Вы также можете установить его с помощью следующих команд:

- **Использование Node.js**

        <Tabs>

      <TabItem label="npm">
      ```bash
      npm install opencode-ai
      ```

          </TabItem>

        <TabItem label="Bun">
        ```bash
        bun install -g opencode-ai
        ```

          </TabItem>

        <TabItem label="pnpm">
        ```bash
        pnpm install opencode-ai
        ```

          </TabItem>

        <TabItem label="Yarn">
        ```bash
        yarn global add opencode-ai
        ```

      </TabItem>

  </Tabs>

- **Использование Homebrew в macOS и Linux**

  ```bash
  brew install anomalyco/tap/opencode
  ```

  > Мы рекомендуем использовать tap opencode для получения самых последних версий. Официальная формула `brew install opencode` поддерживается командой Homebrew и обновляется реже.

- **Использование Paru в Arch Linux**

  ```bash
  sudo pacman -S opencode           # Arch Linux (Stable)
  paru -S opencode-bin              # Arch Linux (Latest from AUR)
  ```

#### Windows

:::tip[Рекомендуется: используйте WSL]
Для наилучшей работы в Windows мы рекомендуем использовать [Подсистема Windows для Linux (WSL)](/docs/windows-wsl). Он обеспечивает лучшую производительность и полную совместимость с функциями opencode.
:::

- **Используя Chocolatey**

  ```bash
  choco install opencode
  ```

- **Использование Scoop**

  ```bash
  scoop install opencode
  ```

- **Использование NPM**

  ```bash
  npm install opencode-ai
  ```

- **Использование Mise**

  ```bash
  mise use -g github:anomalyco/opencode
  ```

- **Использование Docker**

  ```bash
  docker run -it --rm ghcr.io/anomalyco/opencode
  ```

В настоящее время добавляется поддержка установки opencode в Windows с помощью Bun.

Вы также можете получить бинарный файл в разделе [Releases](https://github.com/anomalyco/opencode/releases).

---

## Настроить

С opencode вы можете использовать любого поставщика LLM, настроив его ключи API.

Если вы новичок в использовании поставщиков LLM, мы рекомендуем использовать [OpenCode Zen](https://opencode.ai/v2/docs/console/).
Это тщательно подобранный список моделей, протестированных и проверенных opencode.

1. Запустите команду `/connect` в TUI, выберите opencode и перейдите по адресу [opencode.ai/auth](https://opencode.ai/auth).

   ```txt
   /connect
   ```

2. Войдите в систему, добавьте свои платежные данные и скопируйте ключ API.

3. Вставьте свой ключ API.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

Альтернативно вы можете выбрать одного из других поставщиков. [Подробнее](/docs/providers#directory).

---

## Инициализация

Теперь, когда вы настроили поставщика, вы можете перейти к проекту, который
над которым вы хотите работать.

```bash
cd /path/to/project
```

И запустите opencode.

```bash
opencode
```

Затем инициализируйте opencode для проекта, выполнив следующую команду.

```bash frame="none"
/init
```

Это позволит opencode проанализировать ваш проект и создать файл `AGENTS.md` в
корень проекта.

:::tip
Вам следует зафиксировать файл `AGENTS.md` вашего проекта в Git.
:::

Это помогает opencode понять структуру проекта и шаблоны кодирования.
использовал.

---

## Использование

Теперь вы готовы использовать opencode для работы над своим проектом. Не стесняйтесь спрашивать о чем угодно!

Если вы новичок в использовании агента кодирования ИИ, вот несколько примеров, которые могут вам помочь.

---

### Задавайте вопросы

Вы можете попросить opencode объяснить вам кодовую базу.

:::tip
Используйте ключ `@` для нечеткого поиска файлов в проекте.
:::

```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```

Это полезно, если есть часть кодовой базы, над которой вы не работали.

---

### Добавление функций

Вы можете попросить opencode добавить новые функции в ваш проект. Хотя мы сначала рекомендуем попросить его создать план.

1. **Составьте план**

   opencode имеет _режим планирования_, который отключает возможность вносить изменения и
   вместо этого предложите _как_ реализовать эту функцию.

   Переключитесь на него с помощью клавиши **Tab**. Вы увидите индикатор этого в правом нижнем углу.

   ```bash frame="none" title="Switch to Plan mode"
   <TAB>
   ```

   Теперь давайте опишем, что мы хотим от него.

   ```txt frame="none"
   When a user deletes a note, we'd like to flag it as deleted in the database.
   Then create a screen that shows all the recently deleted notes.
   From this screen, the user can undelete a note or permanently delete it.
   ```

   Нужно предоставить opencode достаточно подробностей, чтобы ему понять, чего вы хотите. Это помогает
   поговорить с ним так, как будто вы разговариваете с младшим разработчиком в своей команде.

   :::tip
   Дайте opencode много контекста и примеров, чтобы помочь ему понять, что вы
   хотеть.
   :::

2. **Итерация плана**

   Как только он предоставит вам план, вы можете оставить ему отзыв или добавить более подробную информацию.

   ```txt frame="none"
   We'd like to design this new screen using a design I've used before.
   [Image #1] Take a look at this image and use it as a reference.
   ```

   :::tip
   Перетащите изображения в терминал, чтобы добавить их в подсказку.
   :::

   opencode может сканировать любые изображения, которые вы ему предоставляете, и добавлять их в командную строку. Вы можете
   сделать это, перетащив изображение в терминал.

3. **Создайте функцию**

   Как только вы почувствуете себя комфортно с планом, вернитесь в _режим сборки_,
   снова нажав клавишу **Tab**.

   ```bash frame="none"
   <TAB>
   ```

   И попросите его внести изменения.

   ```bash frame="none"
   Sounds good! Go ahead and make the changes.
   ```

---

### Внесение изменений

Для более простых изменений вы можете попросить opencode создать их напрямую.
без необходимости предварительного рассмотрения плана.

```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```

Убедитесь, что предоставили достаточно деталей, чтобы opencode внес корректные изменения.

---

### Отмена изменений

Допустим, вы просите opencode внести некоторые изменения.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

Но вы понимаете, что это не то, чего вы хотели. Вы **можете отменить** изменения
с помощью команды `/undo`.

```bash frame="none"
/undo
```

opencode отменит внесенные вами изменения и покажет исходное сообщение.
снова.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

Отсюда вы можете настроить подсказку и попросить opencode повторить попытку.

:::tip
Вы можете запустить `/undo` несколько раз, чтобы отменить несколько изменений.
:::

Или вы **можете повторить** изменения с помощью команды `/redo`.

```bash frame="none"
/redo
```

---

## Настроить

И все! Теперь вы профессионал в использовании opencode.

Чтобы создать свою собственную, мы рекомендуем [выбрать тему](/docs/themes), [настроить привязки клавиш](/docs/keybinds), [настроить средства форматирования кода](/docs/formatters), [создать собственные команды](/docs/commands) или поиграться с файлом [opencode config](/docs/config).

---

### Packages Web Src Content Docs Th Index (`packages/web/src/content/docs/th/index.mdx`)

---
title: บทนำ
description: เริ่มต้นใช้งาน OpenCode
---

import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console

[**OpenCode**](/) คือเอเจนต์การเข้ารหัส AI แบบโอเพ่นซอร์ส มีให้บริการในรูปแบบอินเทอร์เฟซบน terminal แอปเดสก์ท็อป หรือส่วนขยาย IDE



มาเริ่มกันเลย

---

#### ข้อกำหนดเบื้องต้น

หากต้องการใช้ OpenCode ใน terminal คุณจะต้องมี:

1. terminal อีมูเลเตอร์ที่ทันสมัยเช่น:
   - [WezTerm](https://wezterm.org) ข้ามแพลตฟอร์ม
   - [Alacritty](https://alacritty.org) ข้ามแพลตฟอร์ม
   - [Ghostty](https://ghostty.org), Linux และ macOS
   - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux และ macOS

2. API Key สำหรับผู้ให้บริการ LLM ที่คุณต้องการใช้

---

## ติดตั้ง

วิธีที่ง่ายที่สุดในการติดตั้ง OpenCode คือการใช้สคริปต์การติดตั้ง

```bash
curl -fsSL https://opencode.ai/install | bash
```

คุณยังสามารถติดตั้งได้ด้วยคำสั่งต่อไปนี้:

- **ใช้ Node.js**

        <Tabs>

      <TabItem label="npm">
      ```bash
      npm install opencode-ai
      ```

          </TabItem>

        <TabItem label="Bun">
        ```bash
        bun install -g opencode-ai
        ```

          </TabItem>

        <TabItem label="pnpm">
        ```bash
        pnpm install opencode-ai
        ```

          </TabItem>

        <TabItem label="Yarn">
        ```bash
        yarn global add opencode-ai
        ```

      </TabItem>

  </Tabs>

- **ใช้ Homebrew บน macOS และ Linux**

  ```bash
  brew install anomalyco/tap/opencode
  ```

  > เราขอแนะนำให้ใช้ OpenCode tap เพื่อเผยแพร่ข้อมูลล่าสุด สูตร `brew install opencode` อย่างเป็นทางการได้รับการดูแลโดยทีมงาน Homebrew และมีการอัปเดตไม่บ่อยนัก

- **ใช้ Paru บน Arch Linux**

  ```bash
  sudo pacman -S opencode           # Arch Linux (Stable)
  paru -S opencode-bin              # Arch Linux (Latest from AUR)
  ```

#### Windows

:::tip[แนะนำ: ใช้ WSL]
เพื่อประสบการณ์ที่ดีที่สุดบน Windows เราขอแนะนำให้ใช้ [ระบบย่อย Windows สำหรับ Linux (WSL)](/docs/windows-wsl) ให้ประสิทธิภาพที่ดีขึ้นและความเข้ากันได้เต็มรูปแบบกับคุณสมบัติของ OpenCode
:::

- **ใช้ Chocolatey**

  ```bash
  choco install opencode
  ```

- **ใช้ Scoop**

  ```bash
  scoop install opencode
  ```

- **การใช้ NPM**

  ```bash
  npm install opencode-ai
  ```

- **ใช้ Mise**

  ```bash
  mise use -g github:anomalyco/opencode
  ```

- **ใช้ Docker**

  ```bash
  docker run -it --rm ghcr.io/anomalyco/opencode
  ```

ขณะนี้การสนับสนุนสำหรับการติดตั้ง OpenCode บน Windows โดยใช้ Bun อยู่ระหว่างดำเนินการ

คุณยังสามารถคว้าไบนารี่ได้จาก [เผยแพร่](https://github.com/anomalyco/opencode/releases)

---

## กำหนดค่า

ด้วย OpenCode คุณสามารถใช้ผู้ให้บริการ LLM ใดก็ได้โดยกำหนดค่าคีย์ API

หากคุณยังใหม่ต่อการใช้ผู้ให้บริการ LLM เราขอแนะนำให้ใช้ [OpenCode Zen](https://opencode.ai/v2/docs/console/)
เป็นรายการโมเดลที่ได้รับการดูแลจัดการซึ่งได้รับการทดสอบและตรวจสอบโดย OpenCode
ทีม.

1. เรียกใช้คำสั่ง `/connect` ใน TUI เลือก opencode และไปที่ [opencode.ai/auth](https://opencode.ai/auth)

   ```txt
   /connect
   ```

2. ลงชื่อเข้าใช้ เพิ่มรายละเอียดการเรียกเก็บเงินของคุณ และคัดลอกรหัส API ของคุณ

3. วางคีย์ API ของคุณ

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

หรือคุณสามารถเลือกหนึ่งในผู้ให้บริการรายอื่นได้ [เรียนรู้เพิ่มเติม](/docs/providers#ไดเรกทอรี)

---

## เริ่มต้น

เมื่อคุณได้กำหนดค่าผู้ให้บริการแล้ว คุณสามารถนำทางไปยังโปรเจ็กต์นั้นได้
คุณอยากทำงานต่อ

```bash
cd /path/to/project
```

และเรียกใช้ OpenCode

```bash
opencode
```

จากนั้น เริ่มต้น OpenCode สำหรับโปรเจ็กต์โดยการรันคำสั่งต่อไปนี้

```bash frame="none"
/init
```

นี่จะได้รับ OpenCode เพื่อวิเคราะห์โครงการของคุณและสร้างไฟล์ `AGENTS.md`
รากของโครงการ

:::tip
คุณควรคอมมิตไฟล์ `AGENTS.md` ของโปรเจ็กต์ของคุณไปที่ Git
:::

ซึ่งจะช่วยให้ OpenCode เข้าใจโครงสร้างโปรเจ็กต์และรูปแบบการเขียนโค้ด
ใช้แล้ว.

---

## การใช้งาน

ตอนนี้คุณพร้อมที่จะใช้ OpenCode เพื่อทำงานในโครงการของคุณแล้ว อย่าลังเลที่จะถามมัน
อะไรก็ตาม!

หากคุณยังใหม่ต่อการใช้เอเจนต์การเข้ารหัส AI ต่อไปนี้คือตัวอย่างบางส่วนที่อาจเป็นไปได้
ช่วย.

---

### ถามคำถาม

คุณสามารถขอให้ OpenCode อธิบาย codebase ให้คุณได้

:::tip
ใช้ปุ่ม `@` เพื่อค้นหาไฟล์ในโครงการอย่างคลุมเครือ
:::

```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```

สิ่งนี้มีประโยชน์หากมีส่วนหนึ่งของโค้ดเบสที่คุณไม่ได้ดำเนินการ

---

### เพิ่มคุณสมบัติ

คุณสามารถขอให้ OpenCode เพิ่มคุณสมบัติใหม่ให้กับโครงการของคุณได้ แม้ว่าเราจะแนะนำให้ขอให้สร้างแผนก่อนก็ตาม

1. **สร้างแผน**

   OpenCode มีโหมด _Plan_ ที่ปิดการใช้งานความสามารถในการเปลี่ยนแปลงและ
   แนะนำ _how_ ว่าจะใช้งานฟีเจอร์นี้แทน

   เปลี่ยนไปใช้ปุ่ม **Tab** คุณจะเห็นตัวบ่งชี้นี้ที่มุมขวาล่าง

   ```bash frame="none" title="Switch to Plan mode"
   <TAB>
   ```

   ตอนนี้เรามาอธิบายสิ่งที่เราต้องการให้ทำ

   ```txt frame="none"
   When a user deletes a note, we'd like to flag it as deleted in the database.
   Then create a screen that shows all the recently deleted notes.
   From this screen, the user can undelete a note or permanently delete it.
   ```

   คุณต้องการให้รายละเอียด OpenCode เพียงพอเพื่อทำความเข้าใจสิ่งที่คุณต้องการ มันช่วยได้
   เพื่อพูดคุยเหมือนคุณกำลังพูดคุยกับนักพัฒนารุ่นน้องในทีมของคุณ

   :::tip
   ให้บริบทและตัวอย่างมากมายแก่ OpenCode เพื่อช่วยให้เข้าใจสิ่งที่คุณ
   ต้องการ.
   :::

2. **ทบทวนแผน**

   เมื่อมีแผนแล้ว คุณสามารถให้ข้อเสนอแนะหรือเพิ่มรายละเอียดเพิ่มเติมได้

   ```txt frame="none"
   We'd like to design this new screen using a design I've used before.
   [Image #1] Take a look at this image and use it as a reference.
   ```

   :::tip
   ลากและวางรูปภาพลงใน terminal เพื่อเพิ่มลงในพรอมต์
   :::

   OpenCode สามารถสแกนรูปภาพที่คุณให้มาและเพิ่มลงในข้อความแจ้งได้ คุณสามารถ
   ทำได้โดยลากและวางรูปภาพลงใน terminal

3. **สร้างฟีเจอร์**

   เมื่อคุณรู้สึกพอใจกับแผนแล้ว ให้เปลี่ยนกลับเป็น _Build mode_ ภายใน
   กดปุ่ม **Tab** อีกครั้ง

   ```bash frame="none"
   <TAB>
   ```

   และขอให้ทำการเปลี่ยนแปลง

   ```bash frame="none"
   Sounds good! Go ahead and make the changes.
   ```

---

### ทำการเปลี่ยนแปลง

หากต้องการการเปลี่ยนแปลงที่ตรงไปตรงมามากขึ้น คุณสามารถขอให้ OpenCode สร้างมันโดยตรงได้
โดยไม่ต้องทบทวนแผนก่อน

```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```

คุณต้องการให้แน่ใจว่าคุณให้รายละเอียดในปริมาณที่เหมาะสมเพื่อให้ OpenCode ดำเนินการได้ถูกต้อง
การเปลี่ยนแปลง

---

### เลิกทำการเปลี่ยนแปลง

สมมติว่าคุณขอให้ OpenCode ทำการเปลี่ยนแปลงบางอย่าง

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

แต่คุณก็รู้ว่ามันไม่ใช่สิ่งที่คุณต้องการ คุณ **สามารถยกเลิก** การเปลี่ยนแปลงได้
โดยใช้คำสั่ง `/undo`

```bash frame="none"
/undo
```

OpenCode จะคืนค่าการเปลี่ยนแปลงที่คุณทำและแสดงข้อความต้นฉบับของคุณ
อีกครั้ง.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

จากที่นี่ คุณสามารถปรับแต่งข้อความแจ้งและขอให้ OpenCode ลองอีกครั้ง

:::tip
คุณสามารถเรียกใช้ `/undo` ได้หลายครั้งเพื่อเลิกทำการเปลี่ยนแปลงหลายรายการ
:::

หรือคุณสามารถ **สามารถทำซ้ำ** การเปลี่ยนแปลงโดยใช้คำสั่ง `/redo`

```bash frame="none"
/redo
```

---

## ปรับแต่ง

แค่นั้นแหละ! ตอนนี้คุณเป็นมืออาชีพในการใช้ OpenCode แล้ว

หากต้องการทำให้เป็นของคุณเอง เราขอแนะนำให้ [เลือกธีม](/docs/themes), [ปรับแต่งปุ่มลัด](/docs/keybinds), [กำหนดค่าตัวจัดรูปแบบโค้ด](/docs/formatters), [สร้างคำสั่งที่กำหนดเอง](/docs/commands) หรือลองใช้ [การกำหนดค่า OpenCode](/docs/config)

---

### Packages Web Src Content Docs Tr Index (`packages/web/src/content/docs/tr/index.mdx`)

---
title: Giriş
description: OpenCode kullanmaya başlayın.
---

import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console

[**OpenCode**](/) açık kaynaklı bir AI kodlama ajanıdır. Terminal tabanlı bir arayüz, masaüstü uygulaması veya IDE uzantısı olarak mevcuttur.



Başlayalım.

---

#### Ön koşullar

OpenCode'u terminalinizde kullanmak için ihtiyacınız olacak:

1. Şu gibi modern bir terminal emülatörü:
   - [WezTerm](https://wezterm.org), cross-platform (tüm platformlarda)
   - [Alacritty](https://alacritty.org), cross-platform (tüm platformlarda)
   - [Ghostty](https://ghostty.org), Linux ve macOS
   - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux ve macOS

2. Kullanmak istediğiniz LLM sağlayıcılarının API anahtarları.

---

## Kurulum

OpenCode'u kurmanın en kolay yolu kurulum betiğidir.

```bash
curl -fsSL https://opencode.ai/install | bash
```

Ayrıca aşağıdaki komutlarla da yükleyebilirsiniz:

- **Node.js'yi kullanma**

        <Tabs>

      <TabItem label="npm">
      ```bash
      npm install opencode-ai
      ```

          </TabItem>

        <TabItem label="Bun">
        ```bash
        bun install -g opencode-ai
        ```

          </TabItem>

        <TabItem label="pnpm">
        ```bash
        pnpm install opencode-ai
        ```

          </TabItem>

        <TabItem label="Yarn">
        ```bash
        yarn global add opencode-ai
        ```

      </TabItem>

  </Tabs>

- **Homebrew'u macOS ve Linux'ta kullanma**

  ```bash
  brew install anomalyco/tap/opencode
  ```

  > En güncel sürümler için OpenCode tap'ini kullanmanızı öneririz. Resmi `brew install opencode` formülü Homebrew ekibi tarafından korunur ve daha sık güncellenir.

- **Paru'yu Arch Linux'ta kullanma**

  ```bash
  sudo pacman -S opencode           # Arch Linux (Stable)
  paru -S opencode-bin              # Arch Linux (Latest from AUR)
  ```

#### Windows

:::tip[Önerilen: WSL kullanın]
Windows'ta en iyi deneyim için [Windows Subsystem for Linux (WSL)](/docs/windows-wsl) kullanılmasını öneririz. Daha iyi performans ve OpenCode'un özellikleriyle tam uyumluluğu sağlar.
:::

- **Chocolatey Kullanımı**

  ```bash
  choco install opencode
  ```

- **Scoop Kullanımı**

  ```bash
  scoop install opencode
  ```

- **NPM kullanarak**

  ```bash
  npm install opencode-ai
  ```

- **Mise Kullanımı**

  ```bash
  mise use -g github:anomalyco/opencode
  ```

- **Docker'ı kullanma**

  ```bash
  docker run -it --rm ghcr.io/anomalyco/opencode
  ```

OpenCode'un Bun kullanılarak Windows'a yüklenmesine yönelik destek şu anda devam etmektedir.

İkili dosyayı [Releases](https://github.com/anomalyco/opencode/releases)'dan da alabilirsiniz.

---

## Yapılandırma

OpenCode ile herhangi bir LLM sağlayıcısının API anahtarlarını yapılandırarak kullanabilirsiniz.

LLM sağlayıcılarını kullanmaya yeni başlıyorsanız, [OpenCode Zen](https://opencode.ai/v2/docs/console/) kullanmanızı öneririz.
OpenCode ekibi tarafından test edilmiş ve doğrulanmış modellerin seçilmiş bir listesidir.

1. TUI'de `/connect` komutunu çalıştırın, OpenCode'u seçin ve [opencode.ai/auth](https://opencode.ai/auth)'ye gidin.

   ```txt
   /connect
   ```

2. Oturum açın, fatura ayrıntılarınızı ekleyin ve API anahtarınızı kopyalayın.

3. API anahtarınızı yapıştırın.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

Alternatif olarak diğer sağlayıcılardan birini seçebilirsiniz. [Daha fazla bilgi](/docs/providers#directory).

---

## Başlatma

Artık bir sağlayıcı yapılandırdığınıza göre, üzerinde çalışmak istediğiniz bir projeye gidebilirsiniz.

```bash
cd /path/to/project
```

Ve OpenCode'u çalıştırın.

```bash
opencode
```

Daha sonra aşağıdaki komutu çalıştırarak proje için OpenCode'u başlatın.

```bash frame="none"
/init
```

Bu, OpenCode'un projenizi analiz etmesini ve bir `AGENTS.md` proje kökünde dosyası oluşturmasını sağlayacaktır.

:::tip
Projenizin `AGENTS.md` dosyasını Git'e göndermelisiniz.
:::

Bu, OpenCode'un proje yapısını ve kullanılan kodlama kalıplarını anlamasına yardımcı olur.

---

## Kullanım

Artık projeniz üzerinde çalışmak için OpenCode'u kullanmaya hazırsınız. Dilediğiniz soruyu sorabilirsiniz.

AI kodlama ajanını kullanmaya yeniyseniz aşağıdaki örnekler yardımcı olabilir.

---

### Soru Sorma

OpenCode'dan kod tabanını size açıklamasını isteyebilirsiniz.

:::tip
Projedeki dosyaları bulanık aramak için `@` tuşunu kullanın.
:::

```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```

Kod tabanının üzerinde çalışmadığınız bir kısmı varsa bu yararlı olur.

---

### Özellik Ekleme

OpenCode'dan projenize yeni özellikler eklemesini isteyebilirsiniz. Yine de öncelikle ondan bir plan oluşturmasını istemenizi öneririz.

1. **Bir plan oluşturun**

   OpenCode, değişiklik yapma özelliğini kapatan bir \_Plan modu\_\na sahiptir.
   Bu modda, özelliğin nasıl uygulanacağını önerir.

   **Tab** tuşunu kullanarak buna geçin. Bunun için sağ alt köşede bir gösterge göreceksiniz.

   ```bash frame="none" title="Plan moduna geç"
   <TAB>
   ```

   Şimdi ne yapmasını istediğimizi anlatalım.

   ```txt frame="none"
   When a user deletes a note, we'd like to flag it as deleted in the database.
   Then create a screen that shows all the recently deleted notes.
   From this screen, the user can undelete a note or permanently delete it.
   ```

   OpenCode'un isteğinizi anlaması için yeterli ayrıntı verin.
   Ekibinizdeki junior bir geliştiriciyle konuşur gibi yazmak genelde iyi sonuç verir.

   :::tip
   OpenCode'a ne istediğinizi anlamasına yardımcı olacak bol miktarda bağlam ve örnek verin.
   :::

2. **Planı yineleyin**

   Size bir plan sunduğunda ona geri bildirimde bulunabilir veya daha fazla ayrıntı ekleyebilirsiniz.

   ```txt frame="none"
   We'd like to design this new screen using a design I've used before.
   [Image #1] Take a look at this image and use it as a reference.
   ```

   :::tip
   İsteme eklemek için görüntüleri terminale sürükleyip bırakın.
   :::

   OpenCode verdiğiniz görselleri tarayıp prompt'a ekleyebilir.
   Bunu bir görseli terminale sürükleyip bırakarak yapabilirsiniz.

3. **Özelliği oluşturun**

   Planı yeterli bulduğunuzda **Tab** tuşuna tekrar basarak \_Build modu\_\na dönün.

   ```bash frame="none"
   <TAB>
   ```

   Ardından değişiklikleri yapmasını isteyin.

   ```bash frame="none"
   Sounds good! Go ahead and make the changes.
   ```

---

### Değişiklik Yapma

Daha basit değişikliklerde, önce planı incelemeden OpenCode'dan doğrudan değişiklik yapmasını isteyebilirsiniz.

```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```

OpenCode'un doğru değişiklikleri yapması için yeterli ayrıntı verdiğinizden emin olun.

---

### Değişiklikleri Geri Alma

Diyelim ki OpenCode'dan bazı değişiklikler yapmasını istediniz.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

Ama istediğinin bu olmadığını anlıyorsun. `/undo` komutunu kullanarak değişiklikleri **geri alabilirsiniz**.

```bash frame="none"
/undo
```

OpenCode değişiklikleri geri alır ve orijinal mesajınızı tekrar gösterir.

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

Buradan komut isteminde ince ayar yapabilir ve OpenCode'dan tekrar denemesini isteyebilirsiniz.

:::tip
Birden çok değişikliği geri almak için `/undo` komutunu birden çok kez çalıştırabilirsiniz.
:::

Veya `/redo` komutunu kullanarak değişiklikleri **yeniden yapabilirsiniz**.

```bash frame="none"
/redo
```

---

## Özelleştirme

İşte bu kadar! Artık OpenCode'u kullanma konusunda profesyonelsiniz.

Kendinize göre uyarlamak için [tema seçebilir](/docs/themes), [tuş atamalarını özelleştirebilir](/docs/keybinds), [kod biçimlendirici ayarlayabilir](/docs/formatters), [özel komutlar oluşturabilir](/docs/commands) veya [OpenCode config](/docs/config) ile oynayabilirsiniz.

---

### Packages Web Src Content Docs Zh Cn Index (`packages/web/src/content/docs/zh-cn/index.mdx`)

---
title: 简介
description: 开始使用 OpenCode。
---

import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console

[**OpenCode**](/) 是一个开源的 AI 编码代理。它提供终端界面、桌面应用和 IDE 扩展等多种使用方式。



让我们开始吧。

---

#### 前提条件

要在终端中使用 OpenCode，你需要：

1. 一款现代终端模拟器，例如：
   - [WezTerm](https://wezterm.org)，跨平台
   - [Alacritty](https://alacritty.org)，跨平台
   - [Ghostty](https://ghostty.org)，Linux 和 macOS
   - [Kitty](https://sw.kovidgoyal.net/kitty/)，Linux 和 macOS

2. 你想使用的 LLM 提供商的 API 密钥。

---

## 安装

安装 OpenCode 最简单的方法是通过安装脚本。

```bash
curl -fsSL https://opencode.ai/install | bash
```

你也可以使用以下方式安装：

- **使用 Node.js**

        <Tabs>

      <TabItem label="npm">
      ```bash
      npm install opencode-ai
      ```

          </TabItem>

        <TabItem label="Bun">
        ```bash
        bun install -g opencode-ai
        ```

          </TabItem>

        <TabItem label="pnpm">
        ```bash
        pnpm install opencode-ai
        ```

          </TabItem>

        <TabItem label="Yarn">
        ```bash
        yarn global add opencode-ai
        ```

      </TabItem>

  </Tabs>

- **在 macOS 和 Linux 上使用 Homebrew**

  ```bash
  brew install anomalyco/tap/opencode
  ```

  > 我们推荐使用 OpenCode tap 以获取最新版本。官方的 `brew install opencode` formula 由 Homebrew 团队维护，更新频率较低。

- **在 Arch Linux 上安装**

  ```bash
  sudo pacman -S opencode           # Arch Linux (Stable)
  paru -S opencode-bin              # Arch Linux (Latest from AUR)
  ```

#### Windows

:::tip[推荐：使用 WSL]
为了在 Windows 上获得最佳体验，我们推荐使用 [Windows Subsystem for Linux (WSL)](/docs/windows-wsl)。它提供更好的性能，并完全兼容 OpenCode 的所有功能。
:::

- **使用 Chocolatey**

  ```bash
  choco install opencode
  ```

- **使用 Scoop**

  ```bash
  scoop install opencode
  ```

- **使用 NPM**

  ```bash
  npm install opencode-ai
  ```

- **使用 Mise**

  ```bash
  mise use -g github:anomalyco/opencode
  ```

- **使用 Docker**

  ```bash
  docker run -it --rm ghcr.io/anomalyco/opencode
  ```

在 Windows 上通过 Bun 安装 OpenCode 的支持目前正在开发中。

你也可以从 [Releases](https://github.com/anomalyco/opencode/releases) 页面直接下载二进制文件。

---

## 配置

通过 OpenCode，你可以配置 API 密钥来使用任意 LLM 提供商。

如果你刚开始接触 LLM 提供商，我们推荐使用 [OpenCode Zen](https://opencode.ai/v2/docs/console/)。这是一组经过 OpenCode 团队测试和验证的精选模型。

1. 在 TUI 中运行 `/connect` 命令，选择 opencode，然后前往 [opencode.ai/auth](https://opencode.ai/auth)。

   ```txt
   /connect
   ```

2. 登录并添加账单信息，然后复制你的 API 密钥。

3. 粘贴你的 API 密钥。

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

你也可以选择其他提供商。[了解更多](/docs/providers#directory)。

---

## 初始化

配置好提供商后，导航到你想要处理的项目目录。

```bash
cd /path/to/project
```

然后运行 OpenCode。

```bash
opencode
```

接下来，运行以下命令为项目初始化 OpenCode。

```bash frame="none"
/init
```

OpenCode 会分析你的项目并在项目根目录创建一个 `AGENTS.md` 文件。

:::tip
你应该将项目的 `AGENTS.md` 文件提交到 Git。
:::

这有助于 OpenCode 理解项目结构和编码规范。

---

## 使用

现在你已经准备好使用 OpenCode 来处理项目了，尽管提问吧！

如果你是第一次使用 AI 编码代理，以下示例可能会对你有所帮助。

---

### 提问

你可以让 OpenCode 为你讲解代码库。

:::tip
使用 `@` 键可以模糊搜索项目中的文件。
:::

```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```

当你遇到不熟悉的代码时，这个功能非常有用。

---

### 添加功能

你可以让 OpenCode 为项目添加新功能。不过我们建议先让它制定一个计划。

1. **制定计划**

   OpenCode 有一个*计划模式*，该模式下它不会进行任何修改，而是建议*如何*实现该功能。

   使用 **Tab** 键切换到计划模式。你会在右下角看到模式指示器。

   ```bash frame="none" title="Switch to Plan mode"
   <TAB>
   ```

   接下来描述你希望它做什么。

   ```txt frame="none"
   When a user deletes a note, we'd like to flag it as deleted in the database.
   Then create a screen that shows all the recently deleted notes.
   From this screen, the user can undelete a note or permanently delete it.
   ```

   你需要提供足够的细节，让 OpenCode 理解你的需求。可以把它当作团队中的一名初级开发者来沟通。

   :::tip
   为 OpenCode 提供充足的上下文和示例，帮助它理解你的需求。
   :::

2. **迭代计划**

   当它给出计划后，你可以提供反馈或补充更多细节。

   ```txt frame="none"
   We'd like to design this new screen using a design I've used before.
   [Image #1] Take a look at this image and use it as a reference.
   ```

   :::tip
   将图片拖放到终端中即可将其添加到提示词中。
   :::

   OpenCode 可以扫描你提供的图片并将其添加到提示词中。只需将图片拖放到终端窗口即可。

3. **构建功能**

   当你对计划满意后，再次按 **Tab** 键切换回*构建模式*。

   ```bash frame="none"
   <TAB>
   ```

   然后让它开始实施。

   ```bash frame="none"
   Sounds good! Go ahead and make the changes.
   ```

---

### 直接修改

对于比较简单的修改，你可以直接让 OpenCode 实施，无需先审查计划。

```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```

请确保提供足够的细节，以便 OpenCode 做出正确的修改。

---

### 撤销修改

假设你让 OpenCode 做了一些修改。

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

但你发现结果不是你想要的。你**可以使用** `/undo` 命令来撤销修改。

```bash frame="none"
/undo
```

OpenCode 会还原所做的修改，并重新显示你之前的消息。

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

你可以调整提示词，让 OpenCode 重新尝试。

:::tip
你可以多次运行 `/undo` 来撤销多次修改。
:::

你也**可以使用** `/redo` 命令来重做修改。

```bash frame="none"
/redo
```

---

## 个性化

以上就是全部内容！你现在已经是 OpenCode 的使用高手了。

要让它更符合你的习惯，我们推荐[选择一个主题](/docs/themes)、[自定义快捷键](/docs/keybinds)、[配置代码格式化工具](/docs/formatters)、[创建自定义命令](/docs/commands)，或者探索 [OpenCode 配置](/docs/config)。

---

### Packages Web Src Content Docs Zh Tw Index (`packages/web/src/content/docs/zh-tw/index.mdx`)

---
title: 簡介
description: 開始使用 OpenCode。
---

import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console

[**OpenCode**](/) 是一個開源的 AI 編碼代理。它提供終端機介面、桌面應用程式和 IDE 擴充功能等多種使用方式。



讓我們開始吧。

---

#### 前提條件

要在終端機中使用 OpenCode，您需要：

1. 一款現代終端機模擬器，例如：
   - [WezTerm](https://wezterm.org)，跨平台
   - [Alacritty](https://alacritty.org)，跨平台
   - [Ghostty](https://ghostty.org)，Linux 和 macOS
   - [Kitty](https://sw.kovidgoyal.net/kitty/)，Linux 和 macOS

2. 您想使用的 LLM 供應商的 API 金鑰。

---

## 安裝

安裝 OpenCode 最簡單的方法是透過安裝指令碼。

```bash
curl -fsSL https://opencode.ai/install | bash
```

您也可以使用以下方式安裝：

- **使用 Node.js**

        <Tabs>

      <TabItem label="npm">
      ```bash
      npm install opencode-ai
      ```

          </TabItem>

        <TabItem label="Bun">
        ```bash
        bun install -g opencode-ai
        ```

          </TabItem>

        <TabItem label="pnpm">
        ```bash
        pnpm install opencode-ai
        ```

          </TabItem>

        <TabItem label="Yarn">
        ```bash
        yarn global add opencode-ai
        ```

      </TabItem>

  </Tabs>

- **在 macOS 和 Linux 上使用 Homebrew**

  ```bash
  brew install anomalyco/tap/opencode
  ```

  > 我們推薦使用 OpenCode tap 以取得最新版本。官方的 `brew install opencode` formula 由 Homebrew 團隊維護，更新頻率較低。

- **在 Arch Linux 上安裝**

  ```bash
  sudo pacman -S opencode           # Arch Linux (Stable)
  paru -S opencode-bin              # Arch Linux (Latest from AUR)
  ```

#### Windows

:::tip[推薦：使用 WSL]
為了在 Windows 上獲得最佳體驗，我們推薦使用 [Windows Subsystem for Linux (WSL)](/docs/windows-wsl)。它提供更好的效能，並完全相容 OpenCode 的所有功能。
:::

- **使用 Chocolatey**

  ```bash
  choco install opencode
  ```

- **使用 Scoop**

  ```bash
  scoop install opencode
  ```

- **使用 NPM**

  ```bash
  npm install opencode-ai
  ```

- **使用 Mise**

  ```bash
  mise use -g github:anomalyco/opencode
  ```

- **使用 Docker**

  ```bash
  docker run -it --rm ghcr.io/anomalyco/opencode
  ```

在 Windows 上透過 Bun 安裝 OpenCode 的支援目前正在開發中。

您也可以從 [Releases](https://github.com/anomalyco/opencode/releases) 頁面直接下載二進位檔案。

---

## 設定

透過 OpenCode，您可以設定 API 金鑰來使用任意 LLM 供應商。

如果您剛開始接觸 LLM 供應商，我們推薦使用 [OpenCode Zen](https://opencode.ai/v2/docs/console/)。這是一組經過 OpenCode 團隊測試和驗證的精選模型。

1. 在 TUI 中執行 `/connect` 指令，選擇 opencode，然後前往 [opencode.ai/auth](https://opencode.ai/auth)。

   ```txt
   /connect
   ```

2. 登入並新增帳單資訊，然後複製您的 API 金鑰。

3. 貼上您的 API 金鑰。

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

您也可以選擇其他供應商。[了解更多](/docs/providers#directory)。

---

## 初始化

設定好供應商後，導覽到您想要處理的專案目錄。

```bash
cd /path/to/project
```

然後執行 OpenCode。

```bash
opencode
```

接下來，執行以下指令為專案初始化 OpenCode。

```bash frame="none"
/init
```

OpenCode 會分析您的專案並在專案根目錄建立一個 `AGENTS.md` 檔案。

:::tip
您應該將專案的 `AGENTS.md` 檔案提交到 Git。
:::

這有助於 OpenCode 理解專案結構和編碼規範。

---

## 使用

現在您已經準備好使用 OpenCode 來處理專案了，儘管提問吧！

如果您是第一次使用 AI 編碼代理，以下範例可能會對您有所幫助。

---

### 提問

您可以讓 OpenCode 為您講解程式碼庫。

:::tip
使用 `@` 鍵可以模糊搜尋專案中的檔案。
:::

```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```

當您遇到不熟悉的程式碼時，這個功能非常有用。

---

### 新增功能

您可以讓 OpenCode 為專案新增新功能。不過我們建議先讓它制定一個計畫。

1. **制定計畫**

   OpenCode 有一個*計畫模式*，該模式下它不會進行任何修改，而是建議*如何*實作該功能。

   使用 **Tab** 鍵切換到計畫模式。您會在右下角看到模式指示器。

   ```bash frame="none" title="Switch to Plan mode"
   <TAB>
   ```

   接下來描述您希望它做什麼。

   ```txt frame="none"
   When a user deletes a note, we'd like to flag it as deleted in the database.
   Then create a screen that shows all the recently deleted notes.
   From this screen, the user can undelete a note or permanently delete it.
   ```

   您需要提供足夠的細節，讓 OpenCode 理解您的需求。可以把它當作團隊中的一名初級開發者來溝通。

   :::tip
   為 OpenCode 提供充足的上下文和範例，幫助它理解您的需求。
   :::

2. **迭代計畫**

   當它給出計畫後，您可以提供回饋或補充更多細節。

   ```txt frame="none"
   We'd like to design this new screen using a design I've used before.
   [Image #1] Take a look at this image and use it as a reference.
   ```

   :::tip
   將圖片拖放到終端機中即可將其新增到提示詞中。
   :::

   OpenCode 可以掃描您提供的圖片並將其新增到提示詞中。只需將圖片拖放到終端機視窗即可。

3. **建置功能**

   當您對計畫滿意後，再次按 **Tab** 鍵切換回*建置模式*。

   ```bash frame="none"
   <TAB>
   ```

   然後讓它開始實施。

   ```bash frame="none"
   Sounds good! Go ahead and make the changes.
   ```

---

### 直接修改

對於比較簡單的修改，您可以直接讓 OpenCode 實施，無需先審查計畫。

```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```

請確保提供足夠的細節，以便 OpenCode 做出正確的修改。

---

### 復原修改

假設您讓 OpenCode 做了一些修改。

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

但您發現結果不是您想要的。您**可以使用** `/undo` 指令來復原修改。

```bash frame="none"
/undo
```

OpenCode 會還原所做的修改，並重新顯示您之前的訊息。

```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```

您可以調整提示詞，讓 OpenCode 重新嘗試。

:::tip
您可以多次執行 `/undo` 來復原多次修改。
:::

您也**可以使用** `/redo` 指令來重做修改。

```bash frame="none"
/redo
```

---

## 個人化

以上就是全部內容！您現在已經是 OpenCode 的使用高手了。

要讓它更符合您的習慣，我們推薦[選擇一個主題](/docs/themes)、[自訂快捷鍵](/docs/keybinds)、[設定程式碼格式化器](/docs/formatters)、[建立自訂指令](/docs/commands)，或者探索 [OpenCode 設定](/docs/config)。

---

### Services Www Src Docs Content Build Index (`services/www/src/docs/content/build/index.mdx`)

---
title: "Intro"
---

OpenCode is used by millions every day. Build on top of it to create your own
applications, integrations, and agent experiences without starting from
scratch.

We also offer Effect APIs for [plugins](/build/plugins/effect),
[clients](/build/client/effect), and [embedded apps](/build/sdk/effect).

<CardGroup cols={1}>
  <Card title="Extend OpenCode" href="/build/plugins">
    Build plugins that add tools, integrations, commands, agents, and custom behavior while keeping the rest of OpenCode
    intact.
  </Card>
  <Card title="Run it as a server" href="/build/client">
    Connect to OpenCode with the same client used by the TUI and desktop app, then build any interface, workflow, or
    agent experience around it.
  </Card>
  <Card title="Embed it" href="/build/sdk">
    Embed OpenCode directly into your application and build a completely custom agent, interface, or developer product
    around it.
  </Card>
</CardGroup>

---

### Services Www Src Docs Content Cli Index (`services/www/src/docs/content/cli/index.mdx`)

---
title: "Intro"
---

Run the CLI in a project to open the full-screen terminal interface:

```bash
opencode
```

Pass a directory to work in a different project:

```bash
opencode ~/code/my-project
```

Suggested terminals:

- [Ghostty](https://ghostty.org)
- [WezTerm](https://wezterm.org)
- [Alacritty](https://alacritty.org)
- [Kitty](https://sw.kovidgoyal.net/kitty/)

Truecolor support gives themes their most accurate colors; terminals without it use an approximation of the available
palette.

## Automation

Use `opencode run` to submit a prompt without opening the interactive interface. It is designed for scripts, CI jobs, and
other workflows that need model output directly in the terminal.

```bash
opencode run "Explain this repository"
```

## Mini

Use `opencode mini` to start OpenCode's minimal interactive interface instead of the full-screen TUI.

```bash
opencode mini
```

Run `opencode mini --help` to see its session, model, agent, prompt, and replay options.

## Background service

By default, OpenCode discovers or starts one shared background server for your user account. Every local OpenCode client
connects to that server, which owns sessions, configuration, integrations, permissions, and tool execution.

Use `--standalone` to run with a private server, or `--server` to connect to a specific server URL:

```bash
opencode --standalone
opencode --server http://localhost:4096
```

To make private servers the default for CLI commands instead of starting the shared service, disable it:

```bash
opencode service set disabled true
opencode
```

This stops the running background service. `--server` still connects to an explicitly selected server; `opencode service start`
can still start the shared service explicitly. To return to automatic service use, run `opencode service unset disabled`.
Pairing requires the shared service and is unavailable while it is disabled.

See [Troubleshooting](/troubleshooting) for shared service diagnostics and the [API reference](/api) for server endpoints.

## Paths

Print a specific local path for use with other tools:

```bash
opencode debug paths db
sqlite3 "$(opencode debug paths db)"
```

The optional selector accepts `db`, `home`, `data`, `config`, `cache`, `state`, `tmp`, `bin`, `log`, or `repos` and prints
only the path and a newline. The database path respects the release channel and `OPENCODE_DB`; relative database overrides
resolve under the data directory, and `:memory:` is printed as-is. This command does not start a server or open the database.

Omit the selector to show all paths with labels:

```bash
opencode debug paths
```

## Uninstall

Preview the files and installation that will be removed:

```bash
opencode uninstall --dry-run
```

Run `opencode uninstall` to confirm removal. OpenCode stops registered background services and persistent terminals before
removing the global cache directory, which is shared by OpenCode versions and channels. Session data, configuration, and
state are never removed.

- `--force` (`-f`) skips confirmation; use it for noninteractive removal.
- Package-manager installations use the detected package manager. Curl installations print the final command to remove
  the executable manually.

---

### Services Www Src Docs Content Console Index (`services/www/src/docs/content/console/index.mdx`)

---
title: "Intro"
---

The [OpenCode Console](https://opencode.ai/console) is an optional service that provides additional benefits to
using OpenCode, on your own or as a team.

- [Workspaces](/console/workspaces) for sharing access with your [team](/console/members)
- [Inference](/console/models) for both proprietary and open source models
- [Providers](/console/providers) for connecting your own provider accounts through the Console gateway
- Usage tracking and [budget](/console/budgets) controls
- Deploy team wide policies to control OpenCode behavior
- [Web search](/console/websearch)
- [Harnesses](/console/harnesses) for using Console models from Claude Code, Codex, and other agents
- [OpenCode Go and Go Plus](/console/go), $10 and $40 monthly subscriptions for open source model access

## Get started

You don't need a team to use the Console. Every account starts with a **Personal** workspace where you are the only
member.

1. Sign in to the [Console](https://opencode.ai/console).
2. Subscribe to [Go](/console/go), add [credits](/console/billing#add-credits), or connect a [provider](/console/providers).
3. Run `/connect` in OpenCode and choose the workspace.
4. Optionally, [invite](/console/members#invite-members) your team.

```text
/connect
```

## Policies

Providers and Tools rules from the Policies page apply to every OpenCode V2 client
connected to the workspace. They are delivered as [policy](/policies#console)
statements with final authority over the member's own configuration and take effect
within about a minute.

---

### Services Www Src Docs Content Build Client Index (`services/www/src/docs/content/build/client/index.mdx`)

---
title: "JavaScript"
---

`@opencode/client` is the TypeScript client for the OpenCode HTTP
API. Use it when your application connects to an OpenCode server over the
network. Its native types and methods are generated from the same contract as the
[API reference](/api). Plugin RPC types come from imported RPC definitions.

## Install

```sh
bun add @opencode/client
```

## Create a client

Create a client with the server URL, then call methods grouped by API resource:

```ts
import { OpenCode } from "@opencode/client"

const client = OpenCode.make({
  baseUrl: "http://localhost:4096",
})

const session = await client.session.create({
  location: { directory: "/workspace" },
})

await client.session.prompt({
  sessionID: session.id,
  text: "Review the current changes",
})
```

## Headers and requests

Pass default authentication or application headers to `OpenCode.make` with
`headers`. You can also supply a custom `fetch` implementation. Each operation
accepts request options as its final argument for an `AbortSignal` or
per-request headers. Event subscriptions are the exception: they accept only
subscriber-local cancellation and use the base client's headers.

```ts
const client = OpenCode.make({
  baseUrl: "https://opencode.example.com",
  headers: {
    authorization: `Bearer ${process.env.OPENCODE_TOKEN}`,
  },
})

await client.session.list(undefined, {
  signal: AbortSignal.timeout(10_000),
})
```

## Stream events

Streaming endpoints return async iterables:

```ts
for await (const event of client.event.subscribe()) {
  console.log(event.type)
}
```

Native and RPC event subscribers share one lazy connection per client. Client,
handle, and iterable creation open no event connection; consumption starts it.
Breaking iteration or aborting a subscriber ends only that iterator. The last
subscriber leaving closes the connection. The shared source waits for active
subscribers to accept each event; consumers should buffer before performing slow work.

Subscriptions are live-only, with no replay or automatic reconnection. A source
failure ends current subscriptions; subscribe again after recovery. A late native
subscriber receives the current `server.connected` marker, not past business events.

## Plugin RPC

Import a plugin's shared contract and pass it to `client.rpc`:

```ts
import { OpenCode } from "@opencode/client"
import { Acme } from "opencode-acme-plugin/rpc"

const acme = client.rpc(Acme)
const result = await acme.search(
  { query: "hello" },
  { location: { directory: "/workspace" }, signal: AbortSignal.timeout(10_000) },
)

const unsubscribe = acme.events.on("updated", (event) => {
  console.log(event.type, event.location.directory, event.data.text)
})
```

The second optional method argument holds `location`, `signal`, and `headers`,
separate from the plugin-defined input. Omitted location follows native request
defaults: base location headers, then the server's working directory. No location
is selected when constructing the subclient.

Methods infer arguments and results from the definition. Schema parsing belongs
to the contract boundary; callers send the accepted input representation, while
handlers receive parsed values. The Promise client accepts Standard Schema or
plain JSON Schema definitions and does
not run schema parsers locally: the server returns already parsed and transformed
output. Effect Schema definitions require the Effect client.

Declared method errors reject like errors from other Promise client endpoints,
and caught errors remain untyped. Generic HTTP RPC error wrappers are removed by
the typed subclient. Reserved `rpc.*` framework failures remain plain RPC failures,
while unrelated authentication, transport, and protocol errors keep their normal
client representations.

RPC subscriptions use local names and receive that RPC's events across all
locations. Inspect the required `event.location` to filter them. `events.subscribe`
matches the native async iterable API:

```ts
for await (const event of acme.events.subscribe("updated")) {
  console.log(event.data.text)
}
```

`events.on` is a convenience wrapper over the same source. It returns unsubscribe;
async callbacks are awaited sequentially. Callback or source failures are logged
and end that listener. Native and typed subscriptions receive the same normal
`rpc.<rpcID>.<event>` envelope with direct object event data. Live subscriptions
do not replay missed events.

The server plugin must be configured and implement the RPC; importing a
definition does not register it. See [plugin RPC](/build/plugins/rpc) for the
definition and registration API. Any HTTP client can also invoke the generic
`POST /api/rpc/{rpcID}/{method}` route with `{ "input": ... }` and receive
`{ "output": ... }`. Omitted input/output fields represent no value.

## Local background service

The main client entrypoints are browser-compatible and do not include local
process management. In a Node application, import the native Promise service
API from `@opencode/client/service`.

- `Service.discover()` returns a healthy registered endpoint without starting
  a process.
- `Service.ensure()` returns a compatible service, starting one when needed.
- `Service.stop()` stops the exact registered service instance.
- `Service.headers(endpoint)` creates the authentication headers for a client.

```ts
import { OpenCode } from "@opencode/client"
import { Service } from "@opencode/client/service"

const endpoint = await Service.ensure()
const client = OpenCode.make({
  baseUrl: endpoint.url,
  headers: Service.headers(endpoint),
})

const info = await client.server.info()
```

`Service.ensure()` accepts an optional registration file, version, service
command, and `onStart` callback. `version` accepts either an exact value or a
compatibility predicate:

```ts
const endpoint = await Service.ensure({
  file: "/var/run/opencode/service.json",
  version: (version) => version.startsWith("2."),
  command: ["opencode", "serve", "--service"],
  onStart(reason, previousVersion) {
    console.log(reason, previousVersion)
  },
})
```

Omit these options to use the standard registration path and
`opencode serve --service` command.

---

### Services Www Src Docs Content Build Plugins Index (`services/www/src/docs/content/build/plugins/index.mdx`)

---
title: "Overview"
---

Plugins can modify OpenCode's behavior and add new features. To change the terminal UI, build a [CLI
plugin](/build/plugins/cli).

Migrating an existing OpenCode 1 plugin? Follow the [V1 plugin migration guide](/build/plugins/migrate-v1).

```ts title=".opencode/plugins/example/index.ts"
import { Plugin } from "@opencode/plugin"

export default Plugin.define({
  id: "example",
  async setup(ctx) {
    await ctx.storage.set("loaded", true)
  },
})
```

Plugins under `.opencode/plugins/` are loaded automatically, like the local example above. To load published packages
or plugin directories from other locations, add them to `plugins` in `opencode.json(c)`:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "plugins": [
    "opencode-acme-plugin",
    "opencode-acme-plugin@1.2.0",
    "@acme/opencode-plugin",
    "./plugins/local",
    "../shared/plugin",
    "/absolute/path/plugin",
    "file:///home/me/plugins/local",
    {
      "package": "@acme/opencode-plugin",
      "options": {
        "agent": "reviewer",
        "strict": true,
      },
    },
  ],
}
```

See [Configure plugins](/plugins) for more loading and configuration options.

## Lifecycle

`setup` runs when the plugin loads. It may return a cleanup function that runs when the plugin unloads.

```ts
import { Plugin } from "@opencode/plugin"

export default Plugin.define({
  id: "example",
  setup(ctx) {
    console.log(`loaded in OpenCode ${ctx.app.version}`)
    return () => console.log("unloaded")
  },
})
```

### Context

The plugin context is essentially an [OpenCode server client](/build/client).
Its read and action methods use the same inputs and responses as the client. It
adds plugin-only methods for transforms, runtime hooks, reloads, registrations,
and plugin options.

```ts
setup(ctx) {
  console.log(ctx.app.version)
}
```

`ctx.location` describes the location where this plugin instance is loaded. It
includes `directory`, optional `workspaceID`, and `project` metadata (`id`,
`directory`, and `canonical`). It is available in both Promise and Effect plugins.
This is the plugin instance's location, not the location of every session it can
access or event it receives.

```ts
setup(ctx) {
  console.log(ctx.location.directory)
  console.log(ctx.location.project.canonical)
}
```

### Options

Pass plugin options with the object form in `opencode.json(c)`.

```jsonc title="opencode.jsonc"
{
  "plugins": [
    {
      "package": "./plugins/company",
      "options": {
        "strict": true,
      },
    },
  ],
}
```

Read those values from `ctx.options` during `setup`.

```ts title="plugins/company/index.ts"
import { Plugin } from "@opencode/plugin"

export default Plugin.define({
  id: "company",
  setup(ctx) {
    const strict = ctx.options.strict === true
  },
})
```

## Transforms

Transforms are synchronous edits to OpenCode's domain state, and each builds on earlier registrations in its domain.
Registry reads such as `ctx.model.list()` reflect every registration so far, including during plugin setup;
startup batching only coalesces update notifications and never delays what a read returns. Resource status APIs still
report the state of running resources: a registered definition does not mean its connection or other resource work has
completed.

Sources contribute providers and immutable model definitions through `ctx.provider.transform`.

```ts title="plugins/models/index.ts"
import { Model, Plugin, Provider } from "@opencode/plugin"

export default Plugin.define({
  id: "company.models",
  async setup(ctx) {
    const providerID = Provider.ID.make("acme")
    const models = [{ ...Model.Info.default(providerID, Model.ID.make("reasoner")), name: "Acme Reasoner" }]
    await ctx.provider.transform((editor) => {
      editor.add({
        info: {
          ...Provider.Info.empty(providerID),
          name: "Acme",
          activation: "enabled",
          package: "@opencode/ai/providers/openai-compatible",
          settings: { baseURL: "http://127.0.0.1:8000/v1" },
        },
        models,
      })
    })

    const available = await ctx.model.list()
  },
})
```

Any registration, removal, or `reload()` marks the registry changed; the next read rebuilds it by replaying every
active transform in registration order onto a fresh value. Keep transforms cheap and repeatable. A value you have
already read is never modified by later rebuilds.

After provider transforms and availability are resolved, OpenCode materializes the active providers' models and replays
every model transform in order. A model policy can inspect the whole candidate collection, including newly refreshed
sources.

```ts title="plugins/model-budget/index.ts"
import { Plugin } from "@opencode/plugin"

export default Plugin.define({
  id: "company.model-budget",
  async setup(ctx) {
    await ctx.model.transform((editor) => {
      editor
        .list()
        .filter((model) => model.cost.some((tier) => tier.output > 20))
        .forEach((model) => {
          editor.remove(model.providerID, model.id)
        })
    })
  },
})
```

Captured inputs are not watched automatically. Load external data before the synchronous callback, then call
`reload()` after those inputs change. Here, `loadFromSource()` returns
`{ info: Provider.Info, models: readonly Model.Info[] }` entries.

```ts title="plugins/models/index.ts"
import { Plugin } from "@opencode/plugin"

export default Plugin.define({
  id: "company.models",
  async setup(ctx) {
    const source = { providers: await loadFromSource() }

    await ctx.provider.transform((editor) => {
      source.providers.forEach((provider) => editor.add(provider))
    })

    const refresh = async () => {
      source.providers = await loadFromSource()
      await ctx.provider.reload()
    }

    const timer = setInterval(() => void refresh().catch(console.error), 60_000)
    return () => clearInterval(timer)
  },
})
```

Provider changes invalidate the whole active model result, so the output-price policy still filters the refreshed models.
Use `ctx.model.reload()` when only an input captured by a model transform changes.

## API

### Agent

Read all agents or fetch one by ID.

```ts
const agents = await ctx.agent.list()
const build = await ctx.agent.get({ agentID: "build" })
```

Register a transform to inspect, update, remove, or select the default agent.

```ts
await ctx.agent.transform((editor) => {
  const agents = editor.list()
  const build = editor.get("build")

  editor.default("build")
  editor.update("build", (agent) => {
    agent.description = "Builds features and fixes bugs"
  })
  editor.remove("legacy")
})
```

Reload agents after external state used by a transform changes.

```ts
await ctx.agent.reload()
```

#### Reference

Schema: [`Agent.Info`](/api#schema-Agent.Info)

```ts
interface AgentContext {
  list(input?: AgentListInput, requestOptions?: RequestOptions): Promise<AgentListOutput>
  get(input: AgentGetInput, requestOptions?: RequestOptions): Promise<AgentGetOutput>
  transform(callback: (editor: AgentEditor) => void): Promise<Registration>
  reload(): Promise<void>
}

interface AgentEditor {
  list(): readonly AgentInfo[]
  get(id: string): AgentInfo | undefined
  default(id: string | undefined): void
  update(id: string, update: (agent: AgentInfo) => void): void
  remove(id: string): void
}

interface Registration {
  dispose(): Promise<void>
}
```

### Providers

Read available providers or inspect one provider's metadata by ID.

```ts
const providers = await ctx.provider.list()
const provider = await ctx.provider.get({ providerID: "anthropic" })
```

Provider transforms edit provider settings and source definitions. Editor reads include inactive providers and expose
immutable definitions; `models.update` edits an owned copy of a source model.

```ts
await ctx.provider.transform((editor) => {
  editor.update("anthropic", (provider) => {
    provider.headers = { ...provider.headers, "x-company": "engineering" }
  })
  editor.models.update("anthropic", "claude-sonnet-4-5", (model) => {
    model.name = "Team Sonnet"
  })
  editor.models.remove("anthropic", "legacy-model")
  editor.remove("legacy-provider")
})
```

Replace a provider's source inventory with `models.set`, then reload after the captured definitions change.

```ts
const source = { models: await loadModels() }
await ctx.provider.transform((editor) => {
  editor.models.set("acme", source.models)
})

source.models = await loadModels()
await ctx.provider.reload()
```

For account-specific discovery, pass the connection used to load the inventory as `sourceConnection`. OpenCode excludes
that provider while another connection is selected, until your plugin publishes its refreshed inventory.

```ts
const connection = await ctx.integration.connection.active("acme")
if (!connection) return
const inventory = await loadInventory(connection)
await ctx.provider.transform((editor) => {
  editor.add({ info: inventory.provider, models: inventory.models, sourceConnection: connection })
})
```

#### Reference

Schemas: [`Provider.Info`](/api#schema-Provider.Info), [`Model.Info`](/api#schema-Model.Info)

```ts
interface ProviderDomain extends ProviderApi {
  transform(callback: (editor: ProviderEditor) => void): Promise<Registration>
  reload(): Promise<void>
}

interface ProviderRecord {
  readonly provider: Provider.Info
  readonly models: ReadonlyMap<string, Model.Info>
  readonly sourceConnection?: ConnectionInfo
}

interface ProviderEditor {
  list(): readonly ProviderRecord[]
  get(providerID: string): ProviderRecord | undefined
  add(input: { info: Provider.Info; models: readonly Model.Info[]; sourceConnection?: ConnectionInfo }): void
  update(providerID: string, update: (provider: DeepMutable<Provider.Info>) => void): void
  remove(providerID: string): void
  readonly models: {
    set(providerID: string, models: readonly Model.Info[]): void
    update(providerID: string, modelID: string, update: (model: DeepMutable<Model.Info>) => void): void
    remove(providerID: string, modelID: string): void
  }
}
```

### Models

Read available models and the default selection.

```ts
const models = await ctx.model.list()
const selected = await ctx.model.default()
```

Model transforms edit the entire active-provider candidate collection. Disabled candidates remain editable until all
transforms finish; `update` can add a model only under an available provider.

```ts
await ctx.model.transform((editor) => {
  editor.list("anthropic").forEach((model) => {
    editor.update(model.providerID, model.id, (draft) => {
      draft.enabled = draft.capabilities.tools
    })
  })
  editor.default.set("anthropic", "claude-sonnet-4-5")
  editor.remove("anthropic", "legacy-model")
})
```

Callbacks edit raw model overrides. Provider defaults are merged once when OpenCode commits the result; unchanged reads
reuse that result. `editor.provider` exposes immutable source definitions, including inactive templates, rather than
model-transform output.

```ts
await ctx.model.transform((editor) => {
  const source = editor.provider.get("anthropic")?.models.get("claude-sonnet-4-5")
  if (!source) return
  editor.update("anthropic", source.id, (model) => {
    model.limit.context = Math.min(model.limit.context, source.limit.context)
  })
})

await ctx.model.reload()
```

#### Reference

Schema: [`Model.Info`](/api#schema-Model.Info)

```ts
interface ModelDomain extends ModelApi {
  transform(callback: (editor: ModelEditor) => void): Promise<Registration>
  reload(): Promise<void>
}

interface ModelEditor {
  list(providerID?: string): readonly DeepMutable<Model.Info>[]
  get(providerID: string, modelID: string): DeepMutable<Model.Info> | undefined
  update(providerID: string, modelID: string, update: (model: DeepMutable<Model.Info>) => void): void
  remove(providerID: string, modelID: string): void
  readonly default: {
    get(): { providerID: string; modelID: string } | undefined
    set(providerID: string, modelID: string): void
  }
  readonly provider: {
    list(): readonly ProviderRecord[]
    get(providerID: string): ProviderRecord | undefined
  }
}
```

### Commands

Read the commands available at a location.

```ts
const commands = await ctx.command.list()
```

Register commands with a transform. The executor receives the session, prompt attachments, and requested delivery mode.

```ts
await ctx.command.transform((editor) => {
  editor.add({
    name: "security-review",
    description: "Review changes for security issues",
    execute: async ({ sessionID, prompt, delivery }) => {
      await ctx.session.prompt({
        ...prompt,
        sessionID,
        text: `Review these changes for security issues.\n\n${prompt.text}`,
        delivery,
      })
    },
  })
})
```

Reload commands after external state used by a transform changes.

```ts
await ctx.command.reload()
```

#### Reference

Schemas: [`Command.Info`](/api#schema-Command.Info),
[`Session.Inbox.Delivery`](/api#schema-Session.Inbox.Delivery)

```ts
interface CommandContext {
  list(input?: CommandListInput, requestOptions?: RequestOptions): Promise<CommandListOutput>
  transform(callback: (editor: CommandEditor) => void): Promise<Registration>
  reload(): Promise<void>
}

interface CommandEditor {
  add(definition: CommandDefinition): void
}

interface CommandDefinition {
  name: string
  description?: string
  execute(input: CommandInvocation): Promise<void>
}

interface CommandInvocation {
  sessionID: string
  prompt: PromptInput
  delivery: "steer" | "queue"
}
```

### Integrations

Read integrations and inspect active credentials.

```ts
const integrations = await ctx.integration.list()
const github = await ctx.integration.get({ integrationID: "github" })
const connection = await ctx.integration.connection.active("github")
const credential = connection ? await ctx.integration.connection.resolve(connection) : undefined
```

Connect integrations with an API key.

```ts
await ctx.integration.connect.key({
  integrationID: "github",
  key: process.env.GITHUB_TOKEN!,
})
```

Start, inspect, complete, or cancel an OAuth connection attempt.

```ts
const attempt = await ctx.integration.oauth.connect({ integrationID: "github", methodID: "oauth" })
const status = await ctx.integration.oauth.status({ integrationID: "github", attemptID: attempt.data.attemptID })
await ctx.integration.oauth.complete({ integrationID: "github", attemptID: attempt.data.attemptID, code })
await ctx.integration.oauth.cancel({ integrationID: "github", attemptID: attempt.data.attemptID })
```

Command-based connections expose the same start, status, and cancel flow.

```ts
const attempt = await ctx.integration.command.connect({ integrationID: "acme", methodID: "cli" })
const status = await ctx.integration.command.status({ integrationID: "acme", attemptID: attempt.data.attemptID })
await ctx.integration.command.cancel({ integrationID: "acme", attemptID: attempt.data.attemptID })
```

Register a transform to inspect integrations and manage their authentication methods.

```ts
await ctx.integration.transform((editor) => {
  const integrations = editor.list()
  const acme = editor.get("acme")

  editor.update("acme", (integration) => {
    integration.name = "Acme"
  })
  editor.method.update({
    integrationID: "acme",
    method: { id: "cli", type: "command", label: "Sign in with Acme CLI", command: ["acme", "login"] },
  })

  const methods = editor.method.list("acme")
  const legacy = methods.find((method) => method.type === "command" && method.id === "legacy")
  if (legacy) editor.method.remove("acme", legacy)
  editor.remove("legacy")
})
```

Reload integrations after external state used by a transform changes.

```ts
await ctx.integration.reload()
```

#### Reference

Schemas: [`Integration.Info`](/api#schema-Integration.Info), [`Integration.Method`](/api#schema-Integration.Method),
[`Connection.Info`](/api#schema-Connection.Info), [`Form.Answer`](/api#schema-Form.Answer)

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Credentials

Make a saved credential the active one for its integration.

```ts
await ctx.credential.activate({ credentialID })
```

#### Reference

```ts
interface CredentialContext {
  activate(input: CredentialActivateInput, requestOptions?: RequestOptions): Promise<void>
}
```

### MCP

List MCP servers and their current connection state.

```ts
const servers = await ctx.mcp.list()
```

Plugins manage MCP servers only through transforms. Use `editor.set` to add or replace a server, `editor.update` to
change its configuration, and `editor.remove` to remove it. Inspect configuration with `editor.list` and `editor.get`.

```ts
await ctx.mcp.transform((editor) => {
  const servers = editor.list()
  const docs = editor.get("docs")
  editor.set("docs", { type: "remote", url: "https://mcp.example.com" })
  editor.update("docs", (server) => {
    server.disabled = false
  })
  editor.remove("legacy")
})
```

Set `disabled: true` in a transform to disable a server and disconnect it, or `disabled: false` to enable it and allow
OpenCode to connect. OpenCode reconciles server lifecycle from the transformed configuration.

Call `reload()` after external state used by a transform changes to reapply transforms and reconcile the servers.

```ts
await ctx.mcp.reload()
```

#### Reference

Schemas: [`Mcp.Server`](/api#schema-Mcp.Server), [`Mcp.LocalConfigEncoded`](/api#schema-Mcp.LocalConfigEncoded),
[`Mcp.RemoteConfigEncoded`](/api#schema-Mcp.RemoteConfigEncoded)

```ts
interface MCPContext {
  list(input?: McpListInput, requestOptions?: RequestOptions): Promise<McpListOutput>
  transform(callback: (editor: MCPEditor) => void): Promise<Registration>
  reload(): Promise<void>
}

interface MCPEditor {
  list(): readonly (readonly [string, McpServerConfig])[]
  get(name: string): McpServerConfig | undefined
  set(name: string, config: McpServerConfig): void
  update(name: string, update: (config: McpServerConfig) => void): void
  remove(name: string): void
}
```

### Plugins

List the plugins currently active for a location.

```ts
const plugins = await ctx.plugin.list()
```

#### Reference

Schemas: [`Plugin.Info`](/api#schema-Plugin.Info), [`Plugin.Source`](/api#schema-Plugin.Source)

```ts
interface PluginContext {
  list(input?: PluginListInput, requestOptions?: RequestOptions): Promise<PluginListOutput>
}
```

### References

Read the references available at a location.

```ts
const references = await ctx.reference.list()
```

Register a transform to inspect, add, or remove local and Git references. `get(name)` returns the current configured source,
or `undefined` when the name is absent.

```ts
await ctx.reference.transform((editor) => {
  const references = editor.list()
  editor.add("handbook", { type: "local", path: "/workspace/docs/handbook" })
  editor.add("standards", { type: "git", repository: "https://github.com/acme/standards", branch: "main" })
  const handbook = editor.get("handbook")
  editor.remove("legacy")
})
```

Reload references after external state used by a transform changes.

```ts
await ctx.reference.reload()
```

#### Reference

Schemas: [`Reference.Info`](/api#schema-Reference.Info), [`Reference.LocalSource`](/api#schema-Reference.LocalSource),
[`Reference.GitSource`](/api#schema-Reference.GitSource)

```ts
interface ReferenceContext {
  list(input?: ReferenceListInput, requestOptions?: RequestOptions): Promise<ReferenceListOutput>
  transform(callback: (editor: ReferenceEditor) => void): Promise<Registration>
  reload(): Promise<void>
}

interface ReferenceEditor {
  list(): readonly (readonly [string, ReferenceLocalSource | ReferenceGitSource])[]
  get(name: string): ReferenceLocalSource | ReferenceGitSource | undefined
  add(name: string, source: ReferenceLocalSource | ReferenceGitSource): void
  remove(name: string): void
}
```

### Generate

Generate text with a selected model without creating a session, invoking tools, or adding to session history.

```ts
const review = await ctx.generate.text({
  model: { providerID: "anthropic", id: "claude-sonnet-4-6" },
  prompt: "Review this proposed action.",
})
```

### Permissions

Ask for permission before performing an action. `assert` evaluates the session's [permission rules](/permissions),
including saved approvals, and prompts the user when a rule resolves to `ask`. It resolves once the action is allowed.

```ts
execute: async (input, context) => {
  await ctx.permission.assert({
    sessionID: context.sessionID,
    agent: context.agent,
    source: { type: "tool", messageID: context.messageID, id: context.id },
    action: "deploy",
    resources: [input.environment],
    save: [input.environment],
  })
  return { content: await deploy(input.environment) }
}
```

- `action` and `resources` are matched against the rules. Any `deny` blocks the action; otherwise any `ask` prompts.
- `save` lists the patterns stored when the user chooses to always allow.
- `agent` selects whose rules apply and defaults to the session's agent. `source` attaches the prompt to a tool call.
- `metadata` passes extra detail to permission prompts and `evaluate` hooks.

A deny rule or a rejection with feedback rejects with a `Tool.Error` that carries the reason, so the model sees it and
continues. A plain rejection ends the current step. Let these errors propagate rather than returning them as tool
output.

Inspect or resolve pending permission requests.

```ts
const pending = await ctx.permission.list({ sessionID })
const request = await ctx.permission.get({ sessionID, requestID })
await ctx.permission.reply({ sessionID, requestID, reply: "once" })
```

Replace the session-scoped permission rules. They are evaluated after the agent's rules, and the
last matching rule wins. Child sessions inherit the rules in effect when they are created.

```ts
await ctx.session.update({
  sessionID,
  permissions: [{ action: "edit", resource: "/path/to/original/checkout/**", effect: "deny" }],
})
```

### Sessions

Create or read a session.

```ts
const created = await ctx.session.create({ title: "Review" })
const session = await ctx.session.get({ sessionID })
const messages = await ctx.session.context({ sessionID })
```

List sessions a page at a time. To get the next page, pass `cursor.next` back as `cursor`. The cursor remembers your
filters, so you don't need to repeat them.

```ts
const page = await ctx.session.list({ directory: ctx.location.directory, limit: 20 })
const next = page.cursor.next ? await ctx.session.list({ cursor: page.cursor.next, limit: 20 }) : undefined
```

Change the agent or model used by subsequent requests.

```ts
await ctx.session.switchAgent({ sessionID, agent: "build" })
await ctx.session.switchModel({ sessionID, model: { providerID: "anthropic", id: "claude-sonnet-4-5" } })
```

Send user prompts, transient generation requests, commands, or synthetic messages.

```ts
const prompt = await ctx.session.prompt({ sessionID, text: "Review the current changes" })
const generated = await ctx.session.generate({ sessionID, prompt: "Summarize this project" })
const command = await ctx.session.command({ sessionID, command: "review", arguments: "--staged" })
const synthetic = await ctx.session.synthetic({ sessionID, text: "Deployment completed" })
```

Rename, interrupt, or wait for a session.

```ts
await ctx.session.update({ sessionID, title: "Review" })
await ctx.session.interrupt({ sessionID, continue: false })
await ctx.session.wait({ sessionID })
```

Remove a temporary session with `remove`. Removal stops active execution and recursively deletes child sessions.

```ts
await ctx.session.remove({ sessionID })
```

Request compaction with `compact`. It returns the admitted inbox item, not a completed summary; compaction runs at
the next step boundary by default. Pass `delivery: "queue"` to preserve queue order instead.

```ts
const compaction = await ctx.session.compact({ sessionID })
```

#### Reference

Schemas: [`Session.Info`](/api#schema-Session.Info), [`Model.Ref`](/api#schema-Model.Ref),
[`Session.Inbox.User`](/api#schema-Session.Inbox.User), [`Session.Inbox.Synthetic`](/api#schema-Session.Inbox.Synthetic)

```ts
interface SessionContext {
  create(input?: SessionCreateInput, requestOptions?: RequestOptions): Promise<SessionInfo>
  get(input: SessionGetInput, requestOptions?: RequestOptions): Promise<SessionInfo>
  remove(input: SessionRemoveInput, requestOptions?: RequestOptions): Promise<void>
  context(input: SessionContextInput, requestOptions?: RequestOptions): Promise<readonly SessionMessageInfo[]>
  switchAgent(input: SessionSwitchAgentInput, requestOptions?: RequestOptions): Promise<void>
  switchModel(input: SessionSwitchModelInput, requestOptions?: RequestOptions): Promise<void>
  update(input: SessionUpdateInput, requestOptions?: RequestOptions): Promise<void>
  move(input: SessionMoveInput, requestOptions?: RequestOptions): Promise<void>
  prompt(input: SessionPromptInput, requestOptions?: RequestOptions): Promise<SessionInboxUser>
  generate(input: SessionGenerateInput, requestOptions?: RequestOptions): Promise<{ text: string }>
  command(input: SessionCommandInput, requestOptions?: RequestOptions): Promise<SessionInboxUser>
  compact(input: SessionCompactInput, requestOptions?: RequestOptions): Promise<SessionInboxCompaction>
  synthetic(input: SessionSyntheticInput, requestOptions?: RequestOptions): Promise<SessionInboxSynthetic>
  interrupt(input: SessionInterruptInput, requestOptions?: RequestOptions): Promise<void>
  wait(input: SessionWaitInput, requestOptions?: RequestOptions): Promise<void>
}
```

### Skills

Read the skills available at a location.

```ts
const skills = await ctx.skill.list()
```

Register a transform to inspect, add, update, or remove skills. `get(id)` returns the current editor entry, or `undefined`
when the skill is absent.

```ts
await ctx.skill.transform((editor) => {
  const skills = editor.list()
  editor.add({
    id: "review",
    name: "Review",
    description: "Review the current changes",
    path: "/workspace/.opencode/skills/review/SKILL.md",
    content: "Review the current changes for correctness and missing tests.",
  })
  const review = editor.get("review")
  editor.update("review", (skill) => {
    skill.autoinvoke = true
  })
  editor.remove("legacy")
})
```

Reload skills after external state used by a transform changes.

```ts
await ctx.skill.reload()
```

#### Reference

Schema: [`Skill.Info`](/api#schema-Skill.Info)

```ts
interface SkillContext {
  list(input?: SkillListInput, requestOptions?: RequestOptions): Promise<SkillListOutput>
  transform(callback: (editor: SkillEditor) => void): Promise<Registration>
  reload(): Promise<void>
}

interface SkillEditor {
  list(): readonly SkillInfo[]
  get(id: string): SkillInfo | undefined
  add(skill: SkillInfo): void
  update(id: string, update: (skill: SkillInfo) => void): void
  remove(id: string): void
}
```

### Storage

Store, read, or remove durable JSON values scoped to the plugin.

```ts
await ctx.storage.set("settings", { strict: true })
const settings = await ctx.storage.get("settings")
await ctx.storage.remove("settings")
```

Scan keys by prefix with optional cursor pagination.

```ts
const page = await ctx.storage.scan({ prefix: "cache/", limit: 100 })
const next = page.next
```

#### Reference

```ts
interface StorageContext {
  get(key: string): Promise<Json | undefined>
  set(key: string, value: Json): Promise<void>
  remove(key: string): Promise<void>
  scan(options: StorageScanOptions): Promise<StorageScanResult>
}

interface StorageScanOptions {
  prefix: string
  after?: string
  limit?: number
}

interface StorageScanResult {
  entries: readonly { key: string; value: Json }[]
  next?: string
}
```

### Tools

Read the tools currently registered, after every transform, outside of a transform callback. Each tool has an `id`
containing its effective name.

```ts
const tools = await ctx.tool.list()
const read = tools.find((tool) => tool.id === "read")
```

Register, update, and remove tools with a synchronous transform, including in Promise plugins. Load external data
before registering or reloading. A later valid registration overrides the same effective tool name.

```ts
const registration = await ctx.tool.transform((editor) => {
  editor.namespace({
    name: "acme",
    description: "Customer account tools",
  })
  editor.add({
    name: "greeting",
    description: "Create a greeting",
    input: {
      type: "object",
      properties: { name: { type: "string" } },
      required: ["name"],
      additionalProperties: false,
    },
    options: { namespace: "acme", codemode: true },
    execute: async (input, context) => {
      await context.progress({ status: "greeting" })
      return { content: `Hello ${(input as { name: string }).name}!` }
    },
  })
})
```

Promise tool executors receive `context.signal`. Pass it to cancellable work such as `fetch` so stopping the Session
also stops the underlying operation.

```ts
execute: async ({ url }, context) => {
  const response = await fetch(url, { signal: context.signal })
  return { content: await response.text() }
}
```

Call `reload()` after changing source data captured by the callback. Reload replays the active transforms without
changing their order; it does not rerun plugin setup.

```ts
await ctx.tool.reload()
```

Use `list()` and `get()` to inspect tools currently in the editor. Tools have an `id` containing their effective name,
and `get()` returns `undefined` when that ID is not present. Use `update` and `remove` with the effective tool name,
including its namespace (`acme_greeting` above). Dots in
namespaces and unsupported characters in tool names become `_`. Missing names are ignored; creating a tool requires
`add` with a complete definition. Updates preserve the name and namespace. Assign new schemas or options to replace
them rather than mutating nested values. Invalid updates are logged and leave the previous definition intact.

```ts
await ctx.tool.transform((editor) => {
  editor.update("acme_greeting", (tool) => {
    tool.description = "Greet the user by name"
  })
  editor.remove("acme_obsolete")
})
```

Updates and removals replay in order with additions, including after MCP catalog refreshes. Disposing their
registration removes those changes and rebuilds from the remaining transforms.

Dispose a registration to remove its transform and rebuild from the remaining transforms, revealing any earlier
definition it overrode. Disposal is idempotent, and unloading the plugin also disposes its registrations.

```ts
await registration.dispose()
```

Each model request captures a stable, executable tool snapshot. Later transforms, reloads, and disposal affect future
snapshots, not the definitions, Code Mode namespace descriptions, or executors already captured. Executors that close
over mutable plugin data still observe that data; capture a value inside the transform when it must remain tied to
that definition.

#### Reference

Schemas: [`Tool.Content`](/api#schema-Tool.Content), [`Tool.TextContent`](/api#schema-Tool.TextContent),
[`Tool.FileContent`](/api#schema-Tool.FileContent)

```ts
interface ToolContext {
  list(): Promise<readonly (ToolInfo & { readonly id: string })[]>
  transform(callback: (editor: ToolEditor) => void): Promise<Registration>
  reload(): Promise<void>
}

interface ToolEditor {
  list(): readonly (ToolInfo & { readonly id: string })[]
  get(id: string): (ToolInfo & { readonly id: string }) | undefined
  namespace(namespace: { name: string; description: string }): void
  add(tool: ToolInfo): void
  update(id: string, update: (tool: Types.Mutable<ToolInfo>) => void): void
  remove(id: string): void
}
```

### VCS

Read repository information, working-copy status, or file diffs.

```ts
const info = await ctx.vcs.get()
const branches = await ctx.vcs.branches({ search: "feature", limit: 10 })
const changes = await ctx.vcs.status()
const diff = await ctx.vcs.diff({ mode: "working", context: 3 })
```

Register a location-scoped VCS provider with a transform. A provider matching the detected repository type is selected
automatically; use `editor.default.set` to select a different provider.

```ts
await ctx.vcs.transform((editor) => {
  editor.add({
    id: "custom",
    name: "Custom VCS",
    info: async () => ({ branch: { current: "feature", default: "main" } }),
    branches: async (input, { signal }) => readBranches(input, signal),
    status: async (scope, { signal }) => readStatus(scope.worktree, signal),
    diff: async (input, { signal }) => readDiff(input, signal),
  })
  editor.default.set("custom")
})
```

Provider callbacks receive the current location, working-copy root, canonical project root, and optional repository
store. Diff callbacks also receive the selected mode, requested context, and output byte budget. Repository discovery
continues to use OpenCode's built-in Git and Mercurial detectors.

Providers can optionally implement `init(scope, { signal })` to create a repository in `scope.worktree`. Initialization
selects the provider by ID (Git by default), not by the detected repository type. Register a provider with `init` even
when the location has no repository yet; OpenCode checks that the directory exists and has no repository before calling
it, then rediscovers the project. New repository formats still need discovery support beyond this callback.

#### Reference

Schemas: [`Vcs.Info`](/api#schema-Vcs.Info), [`Vcs.FileStatus`](/api#schema-Vcs.FileStatus),
[`FileDiff.Info`](/api#schema-FileDiff.Info)

```ts
interface VcsContext {
  get(input?: VcsGetInput, requestOptions?: RequestOptions): Promise<VcsGetOutput>
  branches(input?: VcsBranchesInput, requestOptions?: RequestOptions): Promise<VcsBranchesOutput>
  status(input?: VcsStatusInput, requestOptions?: RequestOptions): Promise<VcsStatusOutput>
  diff(input: VcsDiffInput, requestOptions?: RequestOptions): Promise<VcsDiffOutput>
  transform(callback: (editor: VcsEditor) => void): Promise<Registration>
  reload(): Promise<void>
}

interface VcsEditor {
  add(definition: VcsDefinition): void
  default: {
    get(): string | undefined
    set(providerID: string): void
  }
}

interface VcsDefinition {
  init?(scope: VcsScope, context: { signal: AbortSignal }): Promise<void>
  // Existing info, branches, status, and diff callbacks are required.
}
```

### Worktrees

Register a local worktree strategy using the normal plugin lifecycle. The implementation module in this example owns
option validation and the backend's `create`, `remove`, and `list` operations.

```ts title="plugins/worktrees/index.ts"
import { Plugin } from "@opencode/plugin"
import { makeStrategy } from "./strategy"

export default Plugin.define({
  id: "company.worktrees",
  async setup(ctx) {
    const strategy = makeStrategy(ctx.options)
    await ctx.worktree.transform((editor) => {
      editor.add(strategy)
    })
  },
})
```

Load the plugin through `plugins` and configure the common destination separately:

```jsonc title="opencode.jsonc"
{
  "worktree": { "directory": "../worktrees" },
  "plugins": [{ "package": "./plugins/worktrees", "options": {} }],
}
```

- Adding a strategy selects it automatically. The last active registration wins; no strategy-selection config is needed.
- Disposing its registration or unloading the plugin restores the previous implementation, ultimately the bundled Git strategy.
- `reload()` replays transforms after captured inputs change; it does not rerun plugin setup.
- Creation failures do not retry through Git. Existing worktrees retain their recorded owner even when the default changes.
- Strategies manage local directories. Remote workspace provisioning is not part of this interface.

#### Operations

The plugin context exposes the same project-based worktree operations as the client. Every operation requires a
`projectID`. `list` reads only saved inventory, including known checkouts of the same project; it does not load
configuration, start plugins, or discover filesystem changes.

```ts
const projectID = ctx.location.project.id
const created = await ctx.worktree.create({ projectID, name: "task" })
const inventory = await ctx.worktree.list({ projectID })
await ctx.worktree.refresh({ projectID })
await ctx.worktree.remove({ projectID, directory: created.directory, force: false })
```

Create loads configuration and plugins from the project's saved `canonical` directory and uses their selected strategy.
It accepts an optional parent `directory`, source `from`, starting `branch`, and `name`.
The source defaults to the canonical checkout, and a `from` override must belong to that project. Choosing a source
does not change the configuration root.
A supplied starting ref must be supported by the selected strategy;
Rift's native snapshot operation, for example, has no ref-selection option.

Create and refresh wait for the canonical checkout's plugins to activate. Calls made during that checkout's plugin
setup see registrations made so far and do not wait for their own activation.

Remove loads the canonical configuration and activates its plugins, then uses the worktree's recorded strategy rather
than the currently selected default. An unavailable recorded owner produces an error. The worktree's destination can
be elsewhere:

```ts
await ctx.worktree.remove({
  directory: "/worktrees/task",
  projectID,
  force: false,
})
```

Missing owners fail removal rather than falling back to Git. A strategy can throw `new Worktree.OperationError({
message: "Uncommitted changes", forceRequired: true })`, importing `Worktree` from `@opencode/plugin`, to request
force confirmation without depending on Core or Git errors.

Refresh loads canonical configuration and asks all available strategies to find worktrees across known checkout roots.
It combines results, preserves recorded ownership, and prunes missing directories. A failed discovery source is logged
while other sources continue. Existing directories remain saved even if no available strategy reports them. Observe
`worktree.updated` and call `list` again to read changed inventory.

```ts
await ctx.worktree.refresh({ projectID })
```

#### Reference

Implementations receive a suggested destination after naming and collision handling. Return the actual directory from
`create`; it may differ when a backend requires its own layout. OpenCode resolves the returned path and uses it for
inventory, startup commands, and the API result. The returned directory must exist.

Strategies choosing another destination handle naming collisions there. OpenCode still creates the suggested parent
directory before calling the strategy. `list` must report only directories the strategy owns, plus any repository roots.

```ts
interface WorktreeDefinition {
  readonly id: string
  create(
    input: { sourceDirectory: string; directory: string; branch?: string },
    context: { signal: AbortSignal },
  ): Promise<{ directory: string }>
  remove(input: { directory: string; force: boolean }, context: { signal: AbortSignal }): Promise<void>
  list(
    sourceDirectory: string,
    context: { signal: AbortSignal },
  ): Promise<readonly { directory: string; type: "root" | "worktree" }[]>
}

interface WorktreeEditor {
  add(definition: WorktreeDefinition): void
}

interface WorktreeDomain extends WorktreeApi {
  transform(callback: (editor: WorktreeEditor) => void): Promise<Registration>
  reload(): Promise<void>
}
```

Promise callbacks must cooperate with `signal` cancellation. Effect callbacks return Effects and use Effect interruption
instead. Registrations remain scoped to the plugin runtime; project operations use the canonical checkout's registry.
Core configuration adapters feed directory settings into that registry.

### Websearch

List websearch providers or run a query through the selected provider.

```ts
const providers = await ctx.websearch.providers()
const results = await ctx.websearch.query({ query: "OpenCode plugins", providerID: "internal" })
```

Register a provider and select the default provider with a transform.

```ts
await ctx.websearch.transform((editor) => {
  editor.add({
    id: "internal",
    name: "Internal search",
    execute: async ({ query }, { signal }) => {
      const response = await fetch(`https://search.example.com?q=${encodeURIComponent(query)}`, { signal })
      const result = await response.json()
      return [{ url: result.url, title: result.title, content: result.content, time: {} }]
    },
  })
  editor.default.set("internal")
})
```

Disable websearch by selecting `false`, or reload providers after external state changes.

```ts
await ctx.websearch.transform((editor) => editor.default.set(false))
await ctx.websearch.reload()
```

#### Reference

Schemas: [`WebSearch.Provider`](/api#schema-WebSearch.Provider), [`WebSearch.Result`](/api#schema-WebSearch.Result)

```ts
interface WebSearchContext {
  providers(input?: WebsearchProvidersInput, requestOptions?: RequestOptions): Promise<WebsearchProvidersOutput>
  query(input: WebsearchQueryInput, requestOptions?: RequestOptions): Promise<WebsearchQueryOutput>
  transform(callback: (editor: WebSearchEditor) => void): Promise<Registration>
  reload(): Promise<void>
}

interface WebSearchEditor {
  add(provider: WebSearchDefinition): void
  default: {
    get(): string | false | undefined
    set(providerID: string | false): void
  }
}
```

### Events

Subscribe to the connected server's public event stream. Abort the stream during plugin cleanup.

```ts
const controller = new AbortController()
void (async () => {
  for await (const event of ctx.event.subscribe({ signal: controller.signal })) {
    console.log(event.type)
  }
})()
return () => controller.abort()
```

#### Reference

Schema: [`V2EventEncoded`](/api#schema-V2EventEncoded)

```ts
interface EventContext {
  subscribe(options?: { signal?: AbortSignal }): AsyncIterable<OpenCodeEvent>
}
```

## Hooks

Hooks intercept live operations. Register a hook on its domain and dispose the
returned registration when it is no longer needed.

```ts
const registration = await ctx.session.hook("context", () => {})
await registration.dispose()
```

Multiple plugins can register the same hook. OpenCode runs them in plugin order,
so later hooks see changes made by earlier hooks.

### Sessions

Session hooks intercept prompt admission, model calls, native HTTP, and retries.

#### Prompt admission

Intercept incoming user prompts before attachment and skill resolution and durable inbox admission:

```ts
await ctx.session.hook("prompt", (event) => {
  event.prompt.text = event.prompt.text.replaceAll("company-secret", "[redacted]")
  event.prompt.files ??= []
  event.prompt.files.push({ uri: "file:///project/policy.md" })
  event.metadata = { ...event.metadata, source: "company-policy" }
  event.delivery = "queue"
})
```

The hook receives an owned, mutable draft:

- `prompt` contains `text`, `files`, agent mentions in `agents`, and selected `skills`.
- `metadata` contains application-defined admission metadata.
- `delivery` is `"steer"` by default and can be changed to `"queue"`.
- Session and message IDs are readonly; a hook cannot redirect admission.

Files and skills added by a hook follow the normal resolution and validation
path. When rewriting text, update or remove attachment `mention` offsets that no
longer match. Agent mentions do not switch the session's active agent.

Prompt hooks run under these conditions:

- Hooks run in registration order after the session's location plugins are ready.
- Commands that submit through `session.prompt` run the hook.
- Synthetic messages, shell messages, compaction controls, and move controls do not.
- The hook runs once during admission, not before every model call.
- Provider scoping is unavailable because model resolution happens after admission.

Edits become the canonical persisted user input. If preparation fails or is
interrupted, OpenCode does not admit the prompt.

Keep prompt hooks retry-safe. They are not an exactly-once side-effect boundary:

- Retrying an ID already pending or delivered returns the original admission without rerunning hooks.
- Concurrent submissions can run hooks more than once, but only the first successful admission wins.
- Prompt hooks transform input and do not expose a typed rejection API.

#### Model requests

Modify assembled system instructions, messages, tools, or request options immediately before model dispatch. Each
kind of request a session issues has its own hook, so a plugin can treat the agent loop and auxiliary requests
differently:

- `context` runs for the agent loop, including tool-driven continuations.
- `compaction` runs for checkpoint summaries. `messages` is the transcript being summarized; OpenCode appends its
  summary prompt after hooks run. Set `result` to record the compaction yourself and skip the model call; it takes the
  same fields as a completed compaction message.
- `generate` runs for transient `ctx.session.generate` calls.
- `title` runs for title generation. It has no `agent` or `tools`. Set `result` to supply the title yourself.

```ts
await ctx.session.hook("context", (event) => {
  event.system.push({ type: "text", text: "Keep the review focused on correctness." })
  delete event.tools.write
  event.options.temperature = 0.2
  event.options.maxTokens = 8_000
})

await ctx.session.hook("compaction", async (event) => {
  event.result = { summary: await summarize(event.messages) }
})
```

Changes affect only the outgoing model call, not persisted history or configuration. A hook that should apply to
every request must register for each kind.

Request overrides follow these rules:

- `options` starts empty for each model call; it does not contain resolved model settings.
- Typed keys are generation settings; any other key is passed to the selected protocol as a provider option.
- Hooks run in registration order and see overrides made by earlier hooks.
- Request overrides take precedence over model defaults, which take precedence over route defaults.
- Provider option objects merge recursively; arrays and scalar values replace earlier values.
- Deleting an override or setting it to `undefined` falls back to configured defaults rather than removing them.
- Raw HTTP body overlays apply after protocol lowering and can override the resulting fields.

#### Provider options

Provider options use the selected protocol's semantic option names, not raw HTTP body fields. Scope provider-specific
settings to the matching provider. For example, OpenAI Responses uses `reasoningEffort`:

```ts
await ctx.session.hook(
  "context",
  (event) => {
    event.options.reasoningEffort = "high"
  },
  { providerID: "openai" },
)
```

Generation options depend on the selected protocol and model:

- `maxTokens` is the semantic output-token limit.
- Gemini supports `topK`; OpenAI Responses does not expose it.

#### Model request

Modify model request settings and optionally scope the hook to one provider. The event carries the same `kind`
as the HTTP hooks below.

```ts
await ctx.session.hook(
  "model.request",
  (event) => {
    event.headers["x-plugin"] = "review"
  },
  { providerID: "anthropic" },
)
```

#### Native HTTP

Modify native provider requests or responses. Their bodies are one-shot streams; clone or replace a body before reading
it.

Both hooks run for every request a session issues. `event.kind` says which flow issued it: `"primary"` for the agent
loop, `"compaction"` for checkpoint summaries, `"title"` for title generation, and `"generate"` for transient
`ctx.session.generate` calls. Use it instead of the agent ID to tell auxiliary requests apart.

```ts
await ctx.session.hook("http.request", (event) => {
  event.request.headers.set("x-session-id", event.sessionID)
  if (event.kind === "title") event.request.headers.set("x-priority", "background")
})

await ctx.session.hook("http.response", (event) => {
  event.response = new Response(event.response.body, {
    status: event.response.status,
    headers: { ...Object.fromEntries(event.response.headers), "x-plugin": "review" },
  })
})
```

#### Native WebSocket (experimental)

Providers that stream over a WebSocket open one connection per session and reuse it across requests, so
`http.request` and `http.response` never see that traffic. The `experimental.ws.handshake` hook runs once per model
call before the connection is selected. It carries the same `sessionID`, `agent`, `model`, and `kind` as the HTTP
hooks, plus the connection `url` and `headers`. Changing `url` or `headers` changes which socket the request uses, so a
rotated bearer token reopens the connection.

HTTP hooks still run for every HTTP request, including the request a WebSocket route falls back to.

```ts
await ctx.session.hook(
  "experimental.ws.handshake",
  async (event) => {
    event.headers.authorization = `Bearer ${await mintToken(event.url)}`
    delete event.headers["api-key"]
  },
  { providerID: "azure" },
)
```

`experimental.ws.send` and `experimental.ws.receive` expose the frames themselves, the WebSocket counterpart of
editing an HTTP request or response body. `send` runs after the provider driver builds an outbound frame and before it
is written; `receive` runs on each inbound frame before the driver observes it. Both carry the frame as a string and
send whatever `frame` holds when the hook returns.

OpenCode does not validate rewritten frames. The driver tracks state from the provider's replies, so a rewrite that
changes protocol meaning is the plugin's responsibility, just as a rewritten HTTP body is.

```ts
await ctx.session.hook(
  "experimental.ws.send",
  (event) => {
    const body = JSON.parse(event.frame)
    if (body.type === "response.create") body.metadata = { ...body.metadata, session: event.sessionID }
    event.frame = JSON.stringify(body)
  },
  { providerID: "openai" },
)

await ctx.session.hook("experimental.ws.receive", (event) => {
  if (event.frame.includes('"type":"error"')) console.error(event.frame)
})
```

These hooks are experimental and their names or shapes may change.

#### Retry policy

Override the retry decision for a provider failure or replace its delay in milliseconds. The hook runs after OpenCode
classifies the failure and proposes its policy, but before any retry is scheduled. It does not expose how OpenCode
internally performs the next attempt.

```ts
await ctx.session.hook("retry", (event) => {
  if (event.error.status === 429) {
    event.decision = { retry: true, delay: 10_000 }
    return
  }
  if (event.error.type === "provider.invalid-request" && event.attempt === 2) {
    event.decision = { retry: true, delay: 0 }
    return
  }
  if (event.attempt >= 3) event.decision = { retry: false }
})
```

Retry hooks can change OpenCode's initial `decision` by making a terminal failure
retryable or vetoing a proposed retry.

Retry decisions follow these rules:

- Multiple hooks run in registration order, and later hooks see the current decision.
- The built-in maximum attempt count remains a hard limit.
- `attempt` is the physical attempt under consideration. The initial request is `1`, so the first retry is `2`.
- Invalid delays such as `NaN`, infinity, or negative values fall back to the computed delay.
- Context-overflow recovery is separate because it compacts the conversation instead of retrying the same request.

#### Session reference

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Permissions

Review permission decisions after configured rules are evaluated and before an
action runs or a permission prompt is published.

```ts
await ctx.permission.hook("evaluate", async (event) => {
  if (event.action === "read") return

  const messages = await ctx.session.context({ sessionID: event.sessionID })
  const review = await ctx.generate.text({
    model: { providerID: "anthropic", id: "claude-sonnet-4-6" },
    prompt: buildSafetyPrompt({ messages, action: event.action, resources: event.resources }),
  })
  const decision = parseDecision(review.text)

  event.effect = decision.effect
  event.message = decision.reason
})
```

Permission hooks follow these rules:

- Hooks run for `allow` and `ask` decisions.
- An explicit configured `deny` is final and does not invoke the hook.
- A hook may change `effect` to `allow`, `ask`, or `deny`.
- `message` appears in an escalated permission request or becomes the denial reason.

#### Reference

```ts
interface PermissionEvaluation {
  readonly sessionID: string
  readonly agent?: string
  readonly action: string
  readonly resources: readonly string[]
  readonly metadata?: Record<string, unknown>
  readonly source?: { type: "tool"; messageID: string; id: string }
  effect: "allow" | "ask" | "deny"
  message?: string
}
```

### Shell

Modify shell commands, working directories, timeouts, executables, or environment variables before execution.

```ts
await ctx.shell.hook("create.before", (event) => {
  event.timeout = Math.min(event.timeout, 60_000)
  event.env.COMPANY_ENV = "development"
})
```

#### Reference

```ts
interface ShellHookContext {
  hook(name: "create.before", callback: (event: ShellCreateBefore) => Promise<void> | void): Promise<Registration>
}

interface ShellCreateBefore {
  command: string
  cwd: string
  timeout: number
  shell: string
  env: Record<string, string | undefined>
}
```

### Tools

Inspect or replace tool input before execution.

```ts
await ctx.tool.hook("execute.before", (event) => {
  if (event.tool === "read") console.log(event.input)
})
```

Inspect successful results or failures after execution.

```ts
await ctx.tool.hook("execute.after", (event) => {
  if (event.status === "completed") event.result = { ...event.result, metadata: { observed: true } }
  if (event.status === "error") console.error(event.error.message)
})
```

#### Reference

```ts
interface ToolHooks {
  "execute.before": ToolExecuteBefore
  "execute.after": ToolExecuteCompleted | ToolExecuteFailed
}

interface ToolHookContext {
  hook<Name extends keyof ToolHooks>(
    name: Name,
    callback: (event: ToolHooks[Name]) => Promise<void> | void,
  ): Promise<Registration>
}
```

## Publish

A package plugin uses the same default export as a local plugin. A minimal
manifest is:

```json title="package.json"
{
  "name": "opencode-acme-plugin",
  "version": "1.0.0",
  "type": "module",
  "exports": {
    ".": "./src/index.ts",
    "./rpc": "./src/rpc.ts"
  },
  "dependencies": {
    "@opencode/plugin": "latest"
  }
}
```

The `./rpc` export is optional; include it when publishing a shared
[RPC contract](/build/plugins/rpc) for other plugins and clients to import
without loading your implementation.

Use versions compatible with the OpenCode release you target and test the
installed package, not only a workspace-linked copy. Publish a compatible
plugin update when you adopt a newer API contract.

## Support V1

A plugin can support V1 and V2 from the same package entrypoint. Default export
one object with a V1 `server()` function and a V2 `setup()` function:

```ts title="src/index.ts"
import { Plugin } from "@opencode/plugin"

export default {
  ...Plugin.define({
    id: "example",
    async setup(ctx) {
      await ctx.tool.hook("execute.before", () => {
        console.log("A tool is about to run")
      })
    },
  }),
  async server() {
    return {
      "tool.execute.before": async () => {
        console.log("A tool is about to run")
      },
    }
  },
}
```

- V1 calls `server()` and uses the returned hooks.
- V2 reads the default export's `id` and `setup()` (or `effect()` for Effect plugins), ignoring `server()`.
- Keep each implementation on its own API; sharing an export does not translate V1 hooks into V2 hooks.
- Spread `Plugin.define(...)` into the exported object so it type-checks the V2 definition separately from `server()`.

The V1 object form is supported in OpenCode `1.18.29`. Older V1 releases may
expect function exports instead; test the installed package with the oldest V1
release you intend to support and with V2.

---

### Services Www Src Docs Content Build Sdk Index (`services/www/src/docs/content/build/sdk/index.mdx`)

---
title: "Overview"
---

`@opencode/sdk` hosts OpenCode directly inside your application. Unlike the
[network client](/build/client), it assembles the OpenCode server and routes API
calls through its HTTP router in memory. It opens no HTTP listener and adds no
network hop between the client and server.

For Cloudflare Durable Objects, see the [Cloudflare guide](/build/sdk/cloudflare).

Install the SDK:

```sh
bun add @opencode/sdk
```

## Create a host

`OpenCode.create()` returns an explicitly owned host. Use `await using` to
release its router, Location services, fibers, and scoped plugin registrations:

```ts
import { OpenCode } from "@opencode/sdk"

await using opencode = await OpenCode.create()
const session = await opencode.sessions.create({
  location: { directory: "/workspace" },
})

await opencode.sessions.prompt({
  sessionID: session.id,
  text: "Review the current changes",
})
```

Call `await opencode.close()` explicitly when explicit resource management is
not available.

The embedded host uses the same Promise values, declared errors, request
options, and `AsyncIterable` streams as `@opencode/client`. It exposes the
full generated client and adds the convenience aliases `sessions` and `events`
for the session and event groups.

## Worktrees

Worktree operations require a `projectID`. Create and refresh load configuration and plugins from the project's saved
canonical checkout. List reads saved inventory only; remove activates canonical plugins and uses the recorded strategy,
failing if that strategy is unavailable.

```ts
const projectID = session.projectID
const worktree = await opencode.worktree.create({ projectID, name: "task" })
await opencode.worktree.refresh({ projectID })
await opencode.worktree.remove({ projectID, directory: worktree.directory, force: false })
```

Refresh discovers worktrees across known checkout roots using all available strategies. Register a custom strategy
through a [plugin's worktree transform](/build/plugins#worktrees).

## Stream events

```ts
for await (const event of opencode.events.subscribe()) {
  console.log(event.type)
}
```

Pass an `AbortSignal` through the generated request options, or leave an
iteration to cancel its response body.

## Customize

Customize your OpenCode instance by registering plugins. Pass plugins to
`OpenCode.create()` to customize agents, models, tools, and other behavior when
the embedded host starts:

```ts
import { Plugin } from "@opencode/plugin"
import { OpenCode } from "@opencode/sdk"

const plugin = Plugin.define({
  id: "customize-agent",
  async setup(ctx) {
    await ctx.agent.transform((agents) => {
      agents.update("build", (agent) => {
        agent.description = "Builds features and fixes bugs for our team"
      })
    })
  },
})

await using opencode = await OpenCode.create({ plugins: [plugin] })
```

Call `await opencode.plugin(plugin)` to register another plugin after startup.

See the [full plugins documentation](/build/plugins) for plugin hooks,
transforms, tools, and the complete plugin context.

---

### Services Www Src Docs Content Console Api Index (`services/www/src/docs/content/console/api/index.mdx`)

---
title: "API Overview"
description: "Authenticate with the OpenCode Console API using personal API keys or service account keys, and scope what each key can do."
---

The Console API lets your scripts and integrations call models and manage budgets. Every request authenticates with
an API key.

```bash
curl --fail-with-body "https://opencode.ai/console/api/v1/budgets/members" \
  --header "Authorization: Bearer oc_sk_..."
```

| API                                 | Endpoints                                  |
| ----------------------------------- | ------------------------------------------ |
| [Inference](/console/api/inference) | `https://opencode.ai/inference/...`        |
| [Providers](/console/api/providers) | `https://opencode.ai/inference/custom/...` |
| [Budgets](/console/api/budgets)     | `/api/v1/budgets/members`                  |

## API keys

Both workspace members and service accounts can have API keys. Send a key as a bearer token.

```text
Authorization: Bearer oc_sk_...
```

|                  | Personal API key                                       | Service account key                                                      |
| ---------------- | ------------------------------------------------------ | ------------------------------------------------------------------------ |
| Created by       | Any member, for themselves                             | Owners and admins                                                        |
| Created in       | **Account › Personal API keys**                        | **Settings › Service accounts**                                          |
| Acts as          | The member who created it                              | The service account                                                      |
| Usage counted to | The member's [budget](/console/budgets#member-budgets) | The service account's [budget](/console/budgets#service-account-budgets) |
| Best for         | Your own scripts and [harnesses](/console/harnesses)   | CI, shared machines, and integrations                                    |

- Each key works in one workspace, chosen when it is created. No workspace header is needed.
- The full key is shown only once, right after you create it. Afterward Console shows only its prefix.
- **Expiration** is optional: **Never**, **1 day**, **7 days**, **30 days**, or **Custom** (1 to 365 days). An expired
  key can't be renewed, so create a new one.

## Personal API keys

A personal key acts as you. Your role, [budgets](/console/budgets#member-budgets), and model rules apply to it.

1. Open **Account** from the account menu and find **Personal API keys**.
2. Click **Add API key**.
3. Choose the **Workspace**, a **Key name**, and an optional **Expiration**. Owners and admins also choose
   **Permissions**.
4. Click **Create** and copy the key.

```text
oc_sk_1a2b3c4d5e6f_...
```

The key follows your current access to the workspace. If your role changes, so does what the key can do. If the
workspace enforces [SSO](/console/sso#sso-enforcement), the key works only while you have an active SSO session, unless
you are an owner.

## Service accounts

A service account is a non-human member of the workspace with its own API keys, usage, and
[budget](/console/budgets#service-account-budgets). Use one for automation, so usage isn't tied to a person. Owners and
admins manage them.

1. Open **Settings › Service accounts** and click **Add Service Account**, then name it, for example `CI Pipeline`.
2. Open the service account and click **Add API Key**.
3. Choose a **Key name**, an optional **Expiration**, and **Permissions**, then click **Create**.
4. Copy the key.

```bash
export SERVICE_API_KEY="oc_sk_..."
```

Owners and admins can rename a service account key or change its permissions later with **Edit…** in the key's actions
menu.

## Permissions

Each key has a permission level, chosen under **Permissions** when you create it.

| Permissions    | Allows                                                                               |
| -------------- | ------------------------------------------------------------------------------------ |
| **All**        | Everything the member or service account can do, except **This account's API keys**. |
| **Restricted** | Only the resources you choose.                                                       |
| **Read only**  | Read access to every resource. The key can list models but not call them.            |

A key never does more than whoever it acts as. A personal key is capped by the member's current role, and a service
account key by what [service accounts can do](#limitations).

### Restricted keys

Set each resource to **None**, **Read**, or **Write**. **Write** includes **Read**.

| Resource                    | Levels                |
| --------------------------- | --------------------- |
| **Models**                  | **Read**, **Request** |
| **Usage**                   | **Read**              |
| **Budgets**                 | **Read**, **Write**   |
| **Members**                 | **Read**, **Write**   |
| **Providers**               | **Read**, **Write**   |
| **Billing**                 | **Read**, **Write**   |
| **Workspace settings**      | **Read**, **Write**   |
| **SSO**                     | **Read**              |
| **Service accounts**        | **Read**              |
| **This account's API keys** | **Write**             |

**Models › Read** lists models, and **Models › Request** also calls them through the [Inference](/console/api/inference)
and [Providers](/console/api/providers) APIs. For example, a key for a budget integration only needs:

```text
Permissions: Restricted
Budgets:     Write
```

Keys created as **Inference only** before scoped permissions show as **Restricted** with **Models** set to **Request**.

### Who can grant what

- **Members** can only create personal keys that list and call models. Console shows "This key can list and call
  models as you." instead of permission choices.
- **Owners and admins** can give their personal keys **All**, **Restricted**, or **Read only**, up to their own role.
  The default is **Restricted** with **Models** set to **Request**. If they are later demoted, their keys shrink to
  match.
- **Service account keys** default to **All**. Owners and admins choose their permissions.

### Limitations

Some actions always need a person signed in to the Console, and creating keys with a key is tightly limited.

- No API key can change SSO settings or delete the workspace.
- Service account keys can't invite members, change roles, remove members, manage billing, change workspace settings,
  manage models, or create or remove service accounts, even with **All**.
- **This account's API keys** is only available on service account keys, and **All** doesn't include it. A key with it
  can create and revoke keys for its own service account only. New keys must be **Restricted**, stay within the
  creating key's permissions, and can't include **This account's API keys**.
- Personal keys can never get **This account's API keys**, and no API key can create or revoke personal API keys.

Requests outside a key's permissions return HTTP `403`.

## Revocation

| Key                 | Who can revoke it      | Where                                                                             |
| ------------------- | ---------------------- | --------------------------------------------------------------------------------- |
| Personal API key    | The member who owns it | **Account › Personal API keys**, then **Revoke**                                  |
| Personal API key    | Owners and admins      | The member's page in **Settings › Members**, under **API Keys**                   |
| Service account key | Owners and admins      | The service account's page in **Settings › Service accounts**, under **API Keys** |

Keys are also revoked automatically:

- Leaving or being removed from a workspace, or being deprovisioned through [SCIM](/console/scim), revokes every key
  that person created in it, including service account keys. Other keys on the same service account keep working.
- Removing a service account revokes all its keys.

Revoked and expired keys stop working immediately and return HTTP `401`.

---

### Services Www Src Docs Content Console Harnesses Index (`services/www/src/docs/content/console/harnesses/index.mdx`)

---
title: "Harnesses"
description: "Use Console and Go models from other coding agents and AI apps."
---

Console works with coding agents other than OpenCode. Point a harness at the Console gateway with an API key, and usage
is billed to your workspace like any other request.

| Harness                                       | Pay-as-you-go | Go        | Models                    | MCP |
| --------------------------------------------- | ------------- | --------- | ------------------------- | --- |
| [Claude Code](/console/harnesses/claude-code) | Yes           | Yes       | Anthropic Messages models | Yes |
| [Codex](/console/harnesses/codex)             | Yes           | Yes       | OpenAI Responses models   | Yes |
| [Hermes](/console/harnesses/hermes)           | Built in      | Built in  | All models                | Yes |
| [Pi](/console/harnesses/pi)                   | Built in      | Built in  | All models                | Yes |
| [Raycast](/console/harnesses/raycast)         | Extension     | Extension | All models                | Yes |

## Get an API key

Harnesses authenticate with a Console API key. The quickest option is a
[personal API key](/console/api#personal-api-keys), which calls models as you.

1. Open **Account** from the account menu in the [Console](https://opencode.ai/console).
2. Under **Personal API keys**, click **Add API key**.
3. Choose the workspace, name the key, and click **Create**.
4. Copy the key. It is shown only once.

```text
oc_sk_1a2b3c4d5e6f_...
```

Usage counts toward your [member budget](/console/budgets#member-budgets). Use a key from a workspace with credits for
pay-as-you-go, or from a workspace subscribed to [Go](/console/go) for Go.

For shared machines or CI, owners and admins can create a [service account](/console/api#service-accounts) key instead,
so usage isn't tied to one person.

## Base URLs

Pay-as-you-go and Go are served from different base URLs. Use the one that matches your plan.

| Plan          | Base URL                           |
| ------------- | ---------------------------------- |
| Pay-as-you-go | `https://opencode.ai/inference`    |
| Go            | `https://opencode.ai/inference/go` |

Append the path for the API your harness speaks.

| API                     | Path                                            |
| ----------------------- | ----------------------------------------------- |
| OpenAI Responses        | `/openai/v1/responses`                          |
| OpenAI Chat Completions | `/openai/v1/chat/completions`                   |
| Anthropic Messages      | `/anthropic/v1/messages`                        |
| Gemini                  | `/google/v1beta/models/<model>:generateContent` |

```text
https://opencode.ai/inference/go/openai/v1/chat/completions
```

## Choose an API

A harness can only use the models that accept the API it speaks. Most models accept one API, and some accept several.
The endpoint column in the [Console](/console/models#endpoints) and [Go](/console/go#endpoints) tables lists one API per
model, so check the harness page for the full list.

Hermes, Pi, and the Raycast extension pick the right API for each model, so they can use every model. Claude Code and
Codex speak a single API and only reach part of the catalog.

| Harness     | API                | Models                                                           |
| ----------- | ------------------ | ---------------------------------------------------------------- |
| Claude Code | Anthropic Messages | Claude and Qwen, plus Kimi K3, DeepSeek V4, and MiniMax M3 on Go |
| Codex       | OpenAI Responses   | GPT, Grok, and Muse Spark, plus DeepSeek V4 on Go                |

<Callout>Support for every model in every harness is coming soon.</Callout>

## Sessions

Send a stable session ID with every request so Console can route a conversation consistently and reuse its prompt
cache. Go [requires it](/console/go#where-can-i-use-it).

```text
x-opencode-session: ses_...
```

Console also recognizes the native session headers sent by Claude Code, Codex, Hermes, and Pi, so they need no extra
configuration.

## Console MCP

Harnesses with MCP support can manage your workspace through the Console MCP server. It uses OAuth with dynamic client
registration, so you sign in from the browser instead of pasting a key.

```text
https://opencode.ai/console/mcp
```

Each harness page shows how to add it.

---

### Packages Util Docs Layer Node (`packages/util/docs/layer-node.md`)

# Layer Graphs

`LayerNode` describes replaceable wiring for ordinary Effect Layers. Declarations
and compilation do not acquire resources. Effect still owns acquisition,
memoization, scopes, and finalization.

There are three values to compose:

- A **Node** is a replaceable declaration with a fixed output, error, and tag
  contract. `make` supplies its default implementation; `unbound` leaves that
  implementation for the caller to supply.
- A **Graph** is a node or an ordered `group` of graphs. Grouping exposes the
  selected roots, not their transitive dependencies. Groups are not replacement
  targets.
- A **Replacement** is a checked instruction made by `node.replace(...)`.
  Replacement arrays can be stored and concatenated without losing their checks.

```ts
import { Context, Effect, Layer } from "effect"
import { LayerNode } from "@opencode/util/effect/layer-node"

class Database extends Context.Service<Database, { readonly name: string }>()("example/Database") {}
class Users extends Context.Service<Users, { readonly name: string }>()("example/Users") {}

const tags = LayerNode.tags({ global: [], location: ["global"] })
const global = tags.make("global")
const location = tags.make("location")

const database = global({
  service: Database,
  layer: Layer.succeed(Database, { name: "live" }),
  deps: [],
})
const users = location({
  service: Users,
  layer: Layer.effect(
    Users,
    Effect.map(Database, (db) => ({ name: db.name })),
  ),
  deps: [database],
})

const replacements: LayerNode.Replacements = [database.replace(Layer.succeed(Database, { name: "test" }))]

const layer = LayerNode.compile(LayerNode.group([database, users]), {
  replacements,
  shared: tags.values.global,
})
// Layer<Database | Users>: both selected roots remain available.
```

## Substitution

Replacements target the exact declaration, not its display name or service key.
Two independently declared nodes can provide the same service in different
branches without capturing each other's overrides.

Keep the original declaration as the target when configuring a default:

```ts
const replacements = [Database.node.replace(Database.configured(options.database)), ...profile.replacements]
```

The replacement may be a closed Layer or another node. It must provide all the
source's outputs, may provide additional outputs, must not introduce new errors,
and must retain the source's tag. An open Layer must first be wired into a node.
Replacing a node prunes its original dependencies; replacing it with another node
uses that node's dependencies instead.

The rules are:

- The last replacement for the same source wins, before any traversal.
- Replacements also apply inside replacement dependency graphs and through
  replacement chains.
- Replacing a node with itself is the identity operation.
- Unreachable replacements neither acquire resources nor traverse their graphs.
- Unbound nodes and cycles in the effective graph fail during compilation.

A node's contract is invariant. It cannot be widened or narrowed to authorize a
replacement that would violate another use of the original declaration. A graph
can forget outputs like an ordinary Layer, but cannot be used as a weaker
replacement handle.

Choice and composition are different: `group([a, b])` provides both roots, while
`group([condition ? a : b])` promises only outputs common to both alternatives.
The same rule applies to conditional implementation Layers. Use tuples for known
roots; a dynamic array can be empty and therefore guarantees no service outputs.
Every alternative of a conditional replacement must satisfy the source contract.

## Decoration

Use `mapLayer` to decorate a default implementation without duplicating or
inspecting its dependencies:

```ts
const observed = database.mapLayer((layer) => layer.pipe(Layer.tap(() => Effect.logDebug("database ready"))))
const replacements = [database.replace(observed)]
```

The callback is parametric in the Layer's requirements: it must preserve the
declared wiring and service/error contract. `mapLayer` returns a new node; it does
not mutate or automatically override the original. Only implemented nodes offer
this operation, not unbound slots or groups.

## Lifetimes

Without `shared`, compilation uses Effect's enclosing memo map throughout.
With `shared: tag`, matching nodes and their dependency subgraphs use that map;
remaining wiring uses one fresh map per build. A shared service's dependencies
must live at least as long as the service, including untagged helpers. This keeps application globals shared while isolating each
Location, without exposing incomplete graphs or losing shared root outputs.

The enclosing memo map remains ambient during construction, so a lazy LayerMap
captures the shared ancestry rather than a Location's private cache. Cache
selection is internal metadata, not an extra service output of each dependency.

Native Layer identity still controls acquisition within each memo map. Use a
distinct implementation Layer for differently wired definitions; compilation
rejects conflicting wiring of the same Layer within one graph's memo domain.
Compiled wiring is memoized once per build and memo domain, so a shared dependency
graph is not expanded into a tree during acquisition. Original Layer identities
still determine service sharing across separately compiled builds. An explicitly
fresh implementation refreshes its acquisition when its wiring is built.

Groups preserve root startup order and associate transparently. A node's
dependencies are built concurrently through native `Layer.provide`. Named
startup actions and Context references are supported even when their required
service output type is `never`.

## Migration

| Previous API                                     | Current API                                     |
| ------------------------------------------------ | ----------------------------------------------- |
| `[source, replacement]`                          | `source.replace(replacement)`                   |
| `compile(graph, replacements)`                   | `compile(graph, { replacements })`              |
| `hoist`, compile both halves, `fresh`, `provide` | `compile(graph, { replacements, shared: tag })` |
| Spread a node and overwrite `implementation`     | `node.mapLayer(transform)`                      |
| Generic root parameter `Node<A, E, any>`         | `Graph<A, E>`                                   |

An application can prepend a default binding and append caller overrides instead
of inspecting the original graph with `hasUnbound`. Unused defaults are pruned,
and defaults introduced as dependencies by an override are found naturally.

Code that reconstructed a replacement source by name must retain the original
declaration instead. Compiler representation fields are no longer public.

`PersistentPty.configured(options)` now returns a wired node, like the other Core
configuration factories. `PersistentPty.layer` remains the default raw Layer.

## Verification

Run `bun run typecheck:dist` in `packages/util` to build the package and check the
same positive and negative contract tests against its emitted declarations.
This ensures package consumers receive the same inference and replacement checks
as callers importing the source.

---

### Services Www Src Docs AGENTS (`services/www/src/docs/AGENTS.md`)

# Documentation feature guide

## Structure

- This folder owns the documentation data model, content, frontend, and styling.
- Documentation content lives in `content/` and is loaded by `../content.config.ts`.
- `lib/navigation.ts` is the source of truth for header sections and sidebar ordering.
- The thin route entrypoints live in `../pages/docs/`; keep docs implementation details here.
- Do not add a documentation frontend framework; this folder owns the UI directly.
- Keep internal Markdown links docs-root-relative, for example `/config`; `remark-links.ts` applies the site and docs base paths.

## Writing Style

- Keep prose sections brief and focused on one idea. Prefer one to three sentences over large paragraphs.
- Interleave explanations with concrete code, configuration, command, or output examples so pages do not become walls of text.
- Put the relevant example immediately after the text that introduces it, following `content/build/plugins/cli.mdx` as the reference pattern.
- Every subsection that explains syntax, fields, or an API concept must include its own minimal example. A larger example earlier on the page does not count.
- Split long explanations with meaningful headings and examples rather than accumulating caveats in one paragraph.
- Lead with the common task and working example; place edge cases and supporting details afterward.
- Do not stack several prose paragraphs without a visual break. After introducing a concept, use an example, list, table, or task-oriented subheading before covering the next concern.
- Use bullets or tables for independent rules, options, and constraints. Do not hide reference material in narrative paragraphs.
- Organize workflow documentation in the order readers perform it, with a working example at each major step.

## Validation

- Run `bun typecheck` and `bun run build` from `services/www` after changes.
- Check desktop and mobile layouts when changing navigation or shared styles.

---

### Packages Web Src Content Docs Acp (`packages/web/src/content/docs/acp.mdx`)

---
title: ACP Support
description: Use OpenCode in any ACP-compatible editor.
---

OpenCode supports the [Agent Client Protocol](https://agentclientprotocol.com) or (ACP), allowing you to use it directly in compatible editors and IDEs.

:::tip
For a list of editors and tools that support ACP, check out the [ACP progress report](https://zed.dev/blog/acp-progress-report#available-now).
:::

ACP is an open protocol that standardizes communication between code editors and AI coding agents.

---

## Configure

To use OpenCode via ACP, configure your editor to run the `opencode acp` command.

The command starts OpenCode as an ACP-compatible subprocess that communicates with your editor over JSON-RPC via stdio.

Below are examples for popular editors that support ACP.

---

### Zed

Install OpenCode from the [Zed ACP Registry](https://zed.dev/docs/ai/external-agents#registry) by running `zed: acp registry` in the Command Palette.

To use a custom OpenCode executable instead, add it to your [Zed](https://zed.dev) configuration (`~/.config/zed/settings.json`):

```json title="~/.config/zed/settings.json"
{
  "agent_servers": {
    "OpenCode": {
      "type": "custom",
      "command": "opencode",
      "args": ["acp"]
    }
  }
}
```

To open it, use the `agent: new thread` action in the **Command Palette**.

You can also bind a keyboard shortcut by editing your `keymap.json`:

```json title="keymap.json"
[
  {
    "bindings": {
      "cmd-alt-o": [
        "agent::NewExternalAgentThread",
        {
          "agent": {
            "custom": {
              "name": "OpenCode",
              "command": {
                "command": "opencode",
                "args": ["acp"]
              }
            }
          }
        }
      ]
    }
  }
]
```

---

### JetBrains IDEs

Add to your [JetBrains IDE](https://www.jetbrains.com/) acp.json according to the [documentation](https://www.jetbrains.com/help/ai-assistant/acp.html):

```json title="acp.json"
{
  "agent_servers": {
    "OpenCode": {
      "command": "/absolute/path/bin/opencode",
      "args": ["acp"]
    }
  }
}
```

To open it, use the new 'OpenCode' agent in the AI Chat agent selector.

---

### Avante.nvim

Add to your [Avante.nvim](https://github.com/yetone/avante.nvim) configuration:

```lua
{
  acp_providers = {
    ["opencode"] = {
      command = "opencode",
      args = { "acp" }
    }
  }
}
```

If you need to pass environment variables:

```lua {6-8}
{
  acp_providers = {
    ["opencode"] = {
      command = "opencode",
      args = { "acp" },
      env = {
        OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY")
      }
    }
  }
}
```

---

### CodeCompanion.nvim

To use OpenCode as an ACP agent in [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim), add the following to your Neovim config:

```lua
require("codecompanion").setup({
  interactions = {
    chat = {
      adapter = {
        name = "opencode",
        model = "claude-sonnet-4",
      },
    },
  },
})
```

This config sets up CodeCompanion to use OpenCode as the ACP agent for chat.

If you need to pass environment variables (like `OPENCODE_API_KEY`), refer to [Configuring Adapters: Environment Variables](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) in the CodeCompanion.nvim documentation for full details.

## Support

OpenCode works the same via ACP as it does in the terminal. All features are supported:

:::note
Some built-in slash commands like `/undo` and `/redo` are currently unsupported.
:::

- Built-in tools (file operations, terminal commands, etc.)
- Custom tools and slash commands
- MCP servers configured in your OpenCode config
- Project-specific rules from `AGENTS.md`
- Custom formatters and linters
- Agents and permissions system

---

### Packages Web Src Content Docs Agents (`packages/web/src/content/docs/agents.mdx`)

---
title: Agents
description: Configure and use specialized agents.
---

Agents are specialized AI assistants that can be configured for specific tasks and workflows. They allow you to create focused tools with custom prompts, models, and tool access.

:::tip
Use the plan agent to analyze code and review suggestions without making any code changes.
:::

You can switch between agents during a session or invoke them with the `@` mention.

---

## Types

There are two types of agents in OpenCode; primary agents and subagents.

---

### Primary agents

Primary agents are the main assistants you interact with directly. You can cycle through them using the **Tab** key, or your configured `switch_agent` keybind. These agents handle your main conversation. Tool access is configured via permissions — for example, Build has all tools enabled while Plan is restricted.

:::tip
You can use the **Tab** key to switch between primary agents during a session.
:::

OpenCode comes with two built-in primary agents, **Build** and **Plan**. We'll
look at these below.

---

### Subagents

Subagents are specialized assistants that primary agents can invoke for specific tasks. You can also manually invoke them by **@ mentioning** them in your messages.

OpenCode comes with three built-in subagents, **General**, **Explore**, and **Scout**. We'll look at this below.

---

## Built-in

OpenCode comes with two built-in primary agents and three built-in subagents.

---

### Use build

_Mode_: `primary`

Build is the **default** primary agent with all tools enabled. This is the standard agent for development work where you need full access to file operations and system commands.

---

### Use plan

_Mode_: `primary`

A restricted agent designed for planning and analysis. This agent is useful when you want the LLM to analyze code, suggest changes, or create plans without making any actual modifications to your codebase.

By default, Plan:

- Denies file edits, writes, and patches outside its plan directory, `~/.opencode/plan/`. These are refused without prompting.
- Allows the `question` tool, so it can ask you clarifying questions.
- Does not restrict shell commands. They follow your [permission](/docs/permissions) config.

Plan's defaults are applied before your top-level `permission` config, and the last matching rule wins. A global rule such as `"edit": "allow"` or `"*": "allow"` therefore also applies to Plan. To keep Plan read-only, or to require approval for its shell commands, set its permissions directly:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "edit": "allow"
  },
  "agent": {
    "plan": {
      "permission": {
        "edit": {
          "*": "deny",
          "~/.opencode/plan/*": "allow"
        },
        "shell": "ask"
      }
    }
  }
}
```

---

### Use general

_Mode_: `subagent`

A general-purpose agent for researching complex questions and executing multi-step tasks. Has full tool access, so it can make file changes when needed. Use this to run multiple units of work in parallel.

---

### Use explore

_Mode_: `subagent`

A fast, read-only agent for exploring codebases. Cannot modify files. Use this when you need to quickly find files by patterns, search code for keywords, or answer questions about the codebase.

---

### Use scout

_Mode_: `subagent`

A read-only agent for external docs and dependency research. Use this when you need to clone a dependency repository into OpenCode's managed cache, inspect library source, or cross-reference local code against upstream implementations without modifying your workspace.

---

### Use compaction

_Mode_: `primary`

Hidden system agent that compacts long context into a smaller summary. It runs automatically when needed and is not selectable in the UI.

---

### Use title

_Mode_: `primary`

Hidden system agent that generates short session titles. It runs automatically and is not selectable in the UI.

---

### Use summary

_Mode_: `primary`

Hidden system agent that creates session summaries. It runs automatically and is not selectable in the UI.

---

## Usage

1. For primary agents, use the **Tab** key to cycle through them during a session. You can also use your configured `switch_agent` keybind.

2. Subagents can be invoked:
   - **Automatically** by primary agents for specialized tasks based on their descriptions.
   - Manually by **@ mentioning** a subagent in your message. For example.

     ```txt frame="none"
     @general help me search for this function
     ```

3. **Navigation between sessions**: When subagents create child sessions, use `session_child_first` (default: **\<Leader>+Down**) to enter the first child session from the parent.

4. Once you are in a child session, use:
   - `session_child_cycle` (default: **Right**) to cycle to the next child session
   - `session_child_cycle_reverse` (default: **Left**) to cycle to the previous child session
   - `session_parent` (default: **Up**) to return to the parent session

   This lets you switch between the main conversation and specialized subagent work.

---

## Configure

You can customize the built-in agents or create your own through configuration. Agents can be configured in two ways:

---

### JSON

Configure agents in your `opencode.json` config file:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "agent": {
    "build": {
      "mode": "primary",
      "model": "anthropic/claude-sonnet-4-20250514",
      "prompt": "{file:./prompts/build.txt}",
      "permission": {
        "edit": "allow",
        "shell": "allow"
      }
    },
    "plan": {
      "mode": "primary",
      "model": "anthropic/claude-haiku-4-20250514",
      "permission": {
        "edit": "deny",
        "shell": "deny"
      }
    },
    "code-reviewer": {
      "description": "Reviews code for best practices and potential issues",
      "mode": "subagent",
      "model": "anthropic/claude-sonnet-4-20250514",
      "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.",
      "permission": {
        "edit": "deny"
      }
    }
  }
}
```

---

### Markdown

You can also define agents using markdown files. Place them in:

- Global: `~/.config/opencode/agents/`
- Per-project: `.opencode/agents/`

```markdown title="~/.config/opencode/agents/review.md"
---
description: Reviews code for quality and best practices
mode: subagent
model: anthropic/claude-sonnet-4-20250514
temperature: 0.1
permission:
  edit: deny
  shell: deny
---

You are in code review mode. Focus on:

- Code quality and best practices
- Potential bugs and edge cases
- Performance implications
- Security considerations

Provide constructive feedback without making direct changes.
```

The markdown file name becomes the agent name. For example, `review.md` creates a `review` agent.

---

## Options

Let's look at these configuration options in detail.

---

### Description

Use the `description` option to provide a brief description of what the agent does and when to use it.

```json title="opencode.json"
{
  "agent": {
    "review": {
      "description": "Reviews code for best practices and potential issues"
    }
  }
}
```

This is a **required** config option.

---

### Temperature

Control the randomness and creativity of the LLM's responses with the `temperature` config.

Lower values make responses more focused and deterministic, while higher values increase creativity and variability.

```json title="opencode.json"
{
  "agent": {
    "plan": {
      "temperature": 0.1
    },
    "creative": {
      "temperature": 0.8
    }
  }
}
```

Temperature values typically range from 0.0 to 1.0:

- **0.0-0.2**: Very focused and deterministic responses, ideal for code analysis and planning
- **0.3-0.5**: Balanced responses with some creativity, good for general development tasks
- **0.6-1.0**: More creative and varied responses, useful for brainstorming and exploration

```json title="opencode.json"
{
  "agent": {
    "analyze": {
      "temperature": 0.1,
      "prompt": "{file:./prompts/analysis.txt}"
    },
    "build": {
      "temperature": 0.3
    },
    "brainstorm": {
      "temperature": 0.7,
      "prompt": "{file:./prompts/creative.txt}"
    }
  }
}
```

If no temperature is specified, OpenCode uses model-specific defaults; typically 0 for most models, 0.55 for Qwen models.

---

### Max steps

Control the maximum number of agentic iterations an agent can perform before being forced to respond with text only. This allows users who wish to control costs to set a limit on agentic actions.

If this is not set, the agent will continue to iterate until the model chooses to stop or the user interrupts the session.

```json title="opencode.json"
{
  "agent": {
    "quick-thinker": {
      "description": "Fast reasoning with limited iterations",
      "prompt": "You are a quick thinker. Solve problems with minimal steps.",
      "steps": 5
    }
  }
}
```

When the limit is reached, the agent receives a special system prompt instructing it to respond with a summarization of its work and recommended remaining tasks.

:::caution
The legacy `maxSteps` field is deprecated. Use `steps` instead.
:::

---

### Disable

Set to `true` to disable the agent.

```json title="opencode.json"
{
  "agent": {
    "review": {
      "disable": true
    }
  }
}
```

---

### Prompt

Specify a custom system prompt file for this agent with the `prompt` config. The prompt file should contain instructions specific to the agent's purpose.

```json title="opencode.json"
{
  "agent": {
    "review": {
      "prompt": "{file:./prompts/code-review.txt}"
    }
  }
}
```

This path is relative to where the config file is located. So this works for both the global OpenCode config and the project specific config.

---

### Model

Use the `model` config to override the model for this agent. Useful for using different models optimized for different tasks. For example, a faster model for planning, a more capable model for implementation.

:::tip
If you don’t specify a model, primary agents use the [model globally configured](/docs/config#models) while subagents will use the model of the primary agent that invoked the subagent.
:::

```json title="opencode.json"
{
  "agent": {
    "plan": {
      "model": "anthropic/claude-haiku-4-20250514"
    }
  }
}
```

The model ID in your OpenCode config uses the format `provider/model-id`. For example, if you're using [OpenCode Zen](https://opencode.ai/v2/docs/console/), you would use `opencode/gpt-5.1-codex` for GPT 5.1 Codex.

---

### Tools (deprecated)

`tools` is **deprecated**. Prefer the agent's [`permission`](#permissions) field for new configs, updates and more fine-grained control.

Allows you to control which tools are available in this agent. You can enable or disable specific tools by setting them to `true` or `false`. In an agent's `tools` config, `true` is equivalent to `{"*": "allow"}` permission and `false` is equivalent to `{"*": "deny"}` permission.

```json title="opencode.json" {3-6,9-12}
{
  "$schema": "https://opencode.ai/config.json",
  "tools": {
    "write": true,
    "shell": true
  },
  "agent": {
    "plan": {
      "tools": {
        "write": false,
        "shell": false
      }
    }
  }
}
```

:::note
The agent-specific config overrides the global config.
:::

You can also use wildcards in legacy `tools` entries to control multiple tools at once. For example, to disable all tools from an MCP server:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "agent": {
    "readonly": {
      "tools": {
        "mymcp_*": false,
        "write": false,
        "edit": false
      }
    }
  }
}
```

[Learn more about tools](/docs/tools).

---

### Permissions

You can configure permissions to manage what actions an agent can take. Each permission key can be set to:

- `"ask"` — Prompt for approval before running the tool
- `"allow"` — Allow all operations without approval
- `"deny"` — Disable the tool

The available permission keys are:

| Key                  | Tools it gates                                                   |
| -------------------- | ---------------------------------------------------------------- |
| `read`               | `read`                                                           |
| `edit`               | `write`, `edit`, `apply_patch`                                   |
| `glob`               | `glob`                                                           |
| `grep`               | `grep`                                                           |
| `list`               | `list`                                                           |
| `shell`              | `shell`                                                          |
| `task`               | `task`                                                           |
| `external_directory` | Any tool that reads or writes files outside the project worktree |
| `webfetch`           | `webfetch`                                                       |
| `websearch`          | `websearch`                                                      |
| `lsp`                | `lsp`                                                            |
| `skill`              | `skill`                                                          |
| `question`           | `question`                                                       |
| `doom_loop`          | Recovery prompts when an agent appears stuck                     |

`read`, `edit`, `glob`, `grep`, `list`, `shell`, `task`, `external_directory`, `lsp`, and `skill` accept either a shorthand action (`"allow" | "ask" | "deny"`) or an object of glob/pattern → action for fine-grained control. The remaining keys accept the shorthand action only.

:::note
Permission keys are matched as wildcard patterns against the underlying tool name, so the same syntax works for built-ins, custom tools, and MCP tools — for example `"mymcp_*": "deny"` denies every tool from an MCP server, and `"mymcp_search": "ask"` targets a single one.
:::

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "edit": "deny"
  }
}
```

You can override these permissions per agent.

```json title="opencode.json" {3-5,8-10}
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "edit": "deny"
  },
  "agent": {
    "build": {
      "permission": {
        "edit": "ask"
      }
    }
  }
}
```

You can also set permissions in Markdown agents.

```markdown title="~/.config/opencode/agents/review.md"
---
description: Code review without edits
mode: subagent
permission:
  edit: deny
  shell:
    "*": ask
    "git diff": allow
    "git log*": allow
    "grep *": allow
  webfetch: deny
---

Only analyze code and suggest changes.
```

You can set permissions for specific shell commands.

```json title="opencode.json" {7}
{
  "$schema": "https://opencode.ai/config.json",
  "agent": {
    "build": {
      "permission": {
        "shell": {
          "git push": "ask",
          "grep *": "allow"
        }
      }
    }
  }
}
```

This can take a glob pattern.

```json title="opencode.json" {7}
{
  "$schema": "https://opencode.ai/config.json",
  "agent": {
    "build": {
      "permission": {
        "shell": {
          "git *": "ask"
        }
      }
    }
  }
}
```

And you can also use the `*` wildcard to manage permissions for all commands.
Since the last matching rule takes precedence, put the `*` wildcard first and specific rules after.

```json title="opencode.json" {8}
{
  "$schema": "https://opencode.ai/config.json",
  "agent": {
    "build": {
      "permission": {
        "shell": {
          "*": "ask",
          "git status *": "allow"
        }
      }
    }
  }
}
```

[Learn more about permissions](/docs/permissions).

---

### Mode

Control the agent's mode with the `mode` config. The `mode` option is used to determine how the agent can be used.

```json title="opencode.json"
{
  "agent": {
    "review": {
      "mode": "subagent"
    }
  }
}
```

The `mode` option can be set to `primary`, `subagent`, or `all`. If no `mode` is specified, it defaults to `all`.

---

### Hidden

Hide a subagent from the `@` autocomplete menu with `hidden: true`. Useful for internal subagents that should only be invoked programmatically by other agents via the Task tool.

```json title="opencode.json"
{
  "agent": {
    "internal-helper": {
      "mode": "subagent",
      "hidden": true
    }
  }
}
```

This only affects user visibility in the autocomplete menu. Hidden agents can still be invoked by the model via the Task tool if permissions allow.

:::note
Only applies to `mode: subagent` agents.
:::

---

### Task permissions

Control which subagents an agent can invoke via the Task tool with `permission.task`. Uses glob patterns for flexible matching.

```json title="opencode.json"
{
  "agent": {
    "orchestrator": {
      "mode": "primary",
      "permission": {
        "task": {
          "*": "deny",
          "orchestrator-*": "allow",
          "code-reviewer": "ask"
        }
      }
    }
  }
}
```

When set to `deny`, the subagent is removed from the Task tool description entirely, so the model won't attempt to invoke it.

:::tip
Rules are evaluated in order, and the **last matching rule wins**. In the example above, `orchestrator-planner` matches both `*` (deny) and `orchestrator-*` (allow), but since `orchestrator-*` comes after `*`, the result is `allow`.
:::

:::tip
Users can always invoke any subagent directly via the `@` autocomplete menu, even if the agent's task permissions would deny it.
:::

---

### Color

Customize the agent's visual appearance in the UI with the `color` option. This affects how the agent appears in the interface.

Use a valid hex color (e.g., `#FF5733`) or theme color: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`.

```json title="opencode.json"
{
  "agent": {
    "creative": {
      "color": "#ff6b6b"
    },
    "code-reviewer": {
      "color": "accent"
    }
  }
}
```

---

### Top P

Control response diversity with the `top_p` option. Alternative to temperature for controlling randomness.

```json title="opencode.json"
{
  "agent": {
    "brainstorm": {
      "top_p": 0.9
    }
  }
}
```

Values range from 0.0 to 1.0. Lower values are more focused, higher values more diverse.

---

### Additional

Any other options you specify in your agent configuration will be **passed through directly** to the provider as model options. This allows you to use provider-specific features and parameters.

For example, with OpenAI's reasoning models, you can control the reasoning effort:

```json title="opencode.json" {6,7}
{
  "agent": {
    "deep-thinker": {
      "description": "Agent that uses high reasoning effort for complex problems",
      "model": "openai/gpt-5",
      "reasoningEffort": "high",
      "textVerbosity": "low"
    }
  }
}
```

These additional options are model and provider-specific. Check your provider's documentation for available parameters.

:::tip
Run `opencode models` to see a list of the available models.
:::

---

## Create agents

Create a new agent by adding a markdown file to `.opencode/agents/` for the project or `~/.config/opencode/agents/` globally. The file name becomes the agent name, and the frontmatter configures its description, mode, model, and permissions. See [Markdown](#markdown) above for the file format.

Run `opencode debug agents` to list the agents that OpenCode has loaded.

---

## Use cases

Here are some common use cases for different agents.

- **Build agent**: Full development work with all tools enabled
- **Plan agent**: Analysis and planning without making changes
- **Review agent**: Code review with read-only access plus documentation tools
- **Debug agent**: Focused on investigation with shell and read tools enabled
- **Docs agent**: Documentation writing with file operations but no system commands

---

## Examples

Here are some example agents you might find useful.

:::tip
Do you have an agent you'd like to share? [Submit a PR](https://github.com/anomalyco/opencode).
:::

---

### Documentation agent

```markdown title="~/.config/opencode/agents/docs-writer.md"
---
description: Writes and maintains project documentation
mode: subagent
permission:
  shell: deny
---

You are a technical writer. Create clear, comprehensive documentation.

Focus on:

- Clear explanations
- Proper structure
- Code examples
- User-friendly language
```

---

### Security auditor

```markdown title="~/.config/opencode/agents/security-auditor.md"
---
description: Performs security audits and identifies vulnerabilities
mode: subagent
permission:
  edit: deny
---

You are a security expert. Focus on identifying potential security issues.

Look for:

- Input validation vulnerabilities
- Authentication and authorization flaws
- Data exposure risks
- Dependency vulnerabilities
- Configuration security issues
```

---

### Packages Web Src Content Docs Cli (`packages/web/src/content/docs/cli.mdx`)

---
title: CLI
description: OpenCode CLI options and commands.
---

import { Tabs, TabItem } from "@astrojs/starlight/components"

The OpenCode CLI by default starts the [TUI](/docs/tui) when run without any arguments.

```bash
opencode
```

But it also accepts commands as documented on this page. This allows you to interact with OpenCode programmatically.

```bash
opencode run "Explain how closures work in JavaScript"
```

---

### tui

Start the OpenCode terminal user interface.

```bash
opencode [project]
```

#### Flags

| Flag                                        | Short | Description                                                             |
| ------------------------------------------- | ----- | ----------------------------------------------------------------------- |
| <nobr><code>{"--continue"}</code></nobr>    | `-c`  | Continue the last session                                               |
| <nobr><code>{"--session"}</code></nobr>     | `-s`  | Session ID to continue                                                  |
| <nobr><code>{"--fork"}</code></nobr>        |       | Fork the session when continuing (use with `--continue` or `--session`) |
| <nobr><code>{"--prompt"}</code></nobr>      |       | Prompt to use                                                           |
| <nobr><code>{"--model"}</code></nobr>       | `-m`  | Model to use in the form of provider/model                              |
| <nobr><code>{"--agent"}</code></nobr>       |       | Agent to use                                                            |
| <nobr><code>{"--auto"}</code></nobr>        |       | Auto-approve permissions that are not explicitly denied                 |
| <nobr><code>{"--port"}</code></nobr>        |       | Port to listen on                                                       |
| <nobr><code>{"--hostname"}</code></nobr>    |       | Hostname to listen on                                                   |
| <nobr><code>{"--mdns"}</code></nobr>        |       | Enable mDNS discovery                                                   |
| <nobr><code>{"--mdns-domain"}</code></nobr> |       | Custom mDNS domain name                                                 |
| <nobr><code>{"--cors"}</code></nobr>        |       | Additional browser origin(s) to allow CORS                              |

---

## Commands

The OpenCode CLI also has the following commands.

---

### attach

Attach a terminal to an already running OpenCode backend server started via `serve` or `web` commands.

```bash
opencode attach [url]
```

This allows using the TUI with a remote OpenCode backend. For example:

```bash
# Start the backend server for web/mobile access
opencode web --port 4096 --hostname 0.0.0.0

# In another terminal, attach the TUI to the running backend
opencode attach http://10.20.30.40:4096
```

#### Flags

| Flag                                     | Short | Description                                                                |
| ---------------------------------------- | ----- | -------------------------------------------------------------------------- |
| <nobr><code>{"--dir"}</code></nobr>      |       | Working directory to start TUI in                                          |
| <nobr><code>{"--continue"}</code></nobr> | `-c`  | Continue the last session                                                  |
| <nobr><code>{"--session"}</code></nobr>  | `-s`  | Session ID to continue                                                     |
| <nobr><code>{"--fork"}</code></nobr>     |       | Fork the session when continuing (use with `--continue` or `--session`)    |
| <nobr><code>{"--password"}</code></nobr> | `-p`  | Basic auth password (defaults to `OPENCODE_SERVER_PASSWORD`)               |
| <nobr><code>{"--username"}</code></nobr> | `-u`  | Basic auth username (defaults to `OPENCODE_SERVER_USERNAME` or `opencode`) |

---

### auth

Command to manage credentials and login for providers.

```bash
opencode auth [command]
```

---

#### login

OpenCode is powered by the provider list at [Models.dev](https://models.dev), so you can use `opencode auth login` to configure API keys for any provider you'd like to use. This is stored in `~/.local/share/opencode/auth.json`.

```bash
opencode auth login
```

When OpenCode starts up it loads the providers from the credentials file. And if there are any keys defined in your environments or a `.env` file in your project.

##### Flags

| Flag                                     | Short | Description                                          |
| ---------------------------------------- | ----- | ---------------------------------------------------- |
| <nobr><code>{"--provider"}</code></nobr> | `-p`  | Provider ID or name to log in to                     |
| <nobr><code>{"--method"}</code></nobr>   | `-m`  | Login method label to use, skipping method selection |

---

#### list

Lists all the authenticated providers as stored in the credentials file.

```bash
opencode auth list
```

Or the short version.

```bash
opencode auth ls
```

---

#### logout

Logs you out of a provider by clearing it from the credentials file.

```bash
opencode auth logout
```

---

### github

Manage the GitHub agent for repository automation.

```bash
opencode github [command]
```

---

#### install

Install the GitHub agent in your repository.

```bash
opencode github install
```

This sets up the necessary GitHub Actions workflow and guides you through the configuration process. [Learn more](/docs/github).

---

#### run

Run the GitHub agent. This is typically used in GitHub Actions.

```bash
opencode github run
```

##### Flags

| Flag                                  | Description                            |
| ------------------------------------- | -------------------------------------- |
| <nobr><code>{"--event"}</code></nobr> | GitHub mock event to run the agent for |
| <nobr><code>{"--token"}</code></nobr> | GitHub personal access token           |

---

### mcp

Manage Model Context Protocol servers.

```bash
opencode mcp [command]
```

---

#### add

Add an MCP server to your configuration.

```bash
opencode mcp add
```

This command will guide you through adding either a local or remote MCP server.

---

#### list

List all configured MCP servers and their connection status.

```bash
opencode mcp list
```

Or use the short version.

```bash
opencode mcp ls
```

---

#### auth

Authenticate with an OAuth-enabled MCP server.

```bash
opencode mcp auth [name]
```

If you don't provide a server name, you'll be prompted to select from available OAuth-capable servers.

You can also list OAuth-capable servers and their authentication status.

```bash
opencode mcp auth list
```

Or use the short version.

```bash
opencode mcp auth ls
```

---

#### logout

Remove OAuth credentials for an MCP server.

```bash
opencode mcp logout [name]
```

---

#### debug

Debug OAuth connection issues for an MCP server.

```bash
opencode mcp debug <name>
```

---

### models

List all available models from configured providers.

```bash
opencode models [provider]
```

This command displays all models available across your configured providers in the format `provider/model`.

This is useful for figuring out the exact model name to use in [your config](/docs/config/).

You can optionally pass a provider ID to filter models by that provider.

```bash
opencode models anthropic
```

#### Flags

| Flag                                    | Description                                                  |
| --------------------------------------- | ------------------------------------------------------------ |
| <nobr><code>{"--refresh"}</code></nobr> | Refresh the models cache from models.dev                     |
| <nobr><code>{"--verbose"}</code></nobr> | Use more verbose model output (includes metadata like costs) |

Use the `--refresh` flag to update the cached model list. This is useful when new models have been added to a provider and you want to see them in OpenCode.

```bash
opencode models --refresh
```

---

### run

Run opencode in non-interactive mode by passing a prompt directly.

```bash
opencode run [message..]
```

This is useful for scripting, automation, or when you want a quick answer without launching the full TUI. For example.

```bash "opencode run"
opencode run Explain the use of context in Go
```

You can also attach to a running `opencode serve` instance to avoid MCP server cold boot times on every run:

```bash
# Start a headless server in one terminal
opencode serve

# In another terminal, run commands that attach to it
opencode run --attach http://localhost:4096 "Explain async/await in JavaScript"
```

#### Flags

| Flag                                     | Short | Description                                                                |
| ---------------------------------------- | ----- | -------------------------------------------------------------------------- |
| <nobr><code>{"--command"}</code></nobr>  |       | The command to run, use message for args                                   |
| <nobr><code>{"--continue"}</code></nobr> | `-c`  | Continue the last session                                                  |
| <nobr><code>{"--session"}</code></nobr>  | `-s`  | Session ID to continue                                                     |
| <nobr><code>{"--fork"}</code></nobr>     |       | Fork the session when continuing (use with `--continue` or `--session`)    |
| <nobr><code>{"--model"}</code></nobr>    | `-m`  | Model to use in the form of provider/model                                 |
| <nobr><code>{"--agent"}</code></nobr>    |       | Agent to use                                                               |
| <nobr><code>{"--file"}</code></nobr>     | `-f`  | File(s) to attach to message                                               |
| <nobr><code>{"--format"}</code></nobr>   |       | Format: default (formatted) or json (raw JSON events)                      |
| <nobr><code>{"--title"}</code></nobr>    |       | Title for the session (uses truncated prompt if no value provided)         |
| <nobr><code>{"--attach"}</code></nobr>   |       | Attach to a running opencode server (e.g., http://localhost:4096)          |
| <nobr><code>{"--password"}</code></nobr> | `-p`  | Basic auth password (defaults to `OPENCODE_SERVER_PASSWORD`)               |
| <nobr><code>{"--username"}</code></nobr> | `-u`  | Basic auth username (defaults to `OPENCODE_SERVER_USERNAME` or `opencode`) |
| <nobr><code>{"--dir"}</code></nobr>      |       | Directory to run in, or path on the remote server when attaching           |
| <nobr><code>{"--port"}</code></nobr>     |       | Port for the local server (defaults to random port)                        |
| <nobr><code>{"--variant"}</code></nobr>  |       | Model variant (provider-specific reasoning effort)                         |
| <nobr><code>{"--thinking"}</code></nobr> |       | Show thinking blocks                                                       |
| <nobr><code>{"--auto"}</code></nobr>     |       | Auto-approve permissions that are not explicitly denied                    |

---

### serve

Start a headless OpenCode server for API access. Check out the [server docs](/docs/server) for the full HTTP interface.

```bash
opencode serve
```

This starts an HTTP server that provides API access to opencode functionality without the TUI interface. Set `OPENCODE_SERVER_PASSWORD` to enable HTTP basic auth (username defaults to `opencode`).

#### Flags

| Flag                                        | Description                                |
| ------------------------------------------- | ------------------------------------------ |
| <nobr><code>{"--port"}</code></nobr>        | Port to listen on                          |
| <nobr><code>{"--hostname"}</code></nobr>    | Hostname to listen on                      |
| <nobr><code>{"--mdns"}</code></nobr>        | Enable mDNS discovery                      |
| <nobr><code>{"--mdns-domain"}</code></nobr> | Custom mDNS domain name                    |
| <nobr><code>{"--cors"}</code></nobr>        | Additional browser origin(s) to allow CORS |

---

### session

Manage OpenCode sessions.

```bash
opencode session [command]
```

---

#### list

List all OpenCode sessions.

```bash
opencode session list
```

##### Flags

| Flag                                      | Short | Description                          |
| ----------------------------------------- | ----- | ------------------------------------ |
| <nobr><code>{"--max-count"}</code></nobr> | `-n`  | Limit to N most recent sessions      |
| <nobr><code>{"--format"}</code></nobr>    |       | Output format: table or json (table) |

---

#### delete

Delete an OpenCode session.

```bash
opencode session delete <sessionID>
```

---

### stats

Show token usage and cost statistics for your OpenCode sessions.

```bash
opencode stats
```

#### Flags

| Flag                                    | Description                                                                 |
| --------------------------------------- | --------------------------------------------------------------------------- |
| <nobr><code>{"--days"}</code></nobr>    | Show stats for the last N days (all time)                                   |
| <nobr><code>{"--tools"}</code></nobr>   | Number of tools to show (all)                                               |
| <nobr><code>{"--models"}</code></nobr>  | Show model usage breakdown (hidden by default). Pass a number to show top N |
| <nobr><code>{"--project"}</code></nobr> | Filter by project (all projects, empty string: current project)             |

---

### export

Export session data as JSON.

```bash
opencode export [sessionID]
```

If you don't provide a session ID, you'll be prompted to select from available sessions.

#### Flags

| Flag                                     | Description                           |
| ---------------------------------------- | ------------------------------------- |
| <nobr><code>{"--sanitize"}</code></nobr> | Redact sensitive transcript/file data |

---

### import

Import session data from a JSON file.

```bash
opencode import <file>
```

```bash
opencode import session.json
```

---

### web

Start a headless OpenCode server with a web interface.

```bash
opencode web
```

This starts an HTTP server and opens a web browser to access OpenCode through a web interface. Set `OPENCODE_SERVER_PASSWORD` to enable HTTP basic auth (username defaults to `opencode`).

#### Flags

| Flag                                        | Description                                |
| ------------------------------------------- | ------------------------------------------ |
| <nobr><code>{"--port"}</code></nobr>        | Port to listen on                          |
| <nobr><code>{"--hostname"}</code></nobr>    | Hostname to listen on                      |
| <nobr><code>{"--mdns"}</code></nobr>        | Enable mDNS discovery                      |
| <nobr><code>{"--mdns-domain"}</code></nobr> | Custom mDNS domain name                    |
| <nobr><code>{"--cors"}</code></nobr>        | Additional browser origin(s) to allow CORS |

---

### acp

Start an ACP (Agent Client Protocol) server.

```bash
opencode acp
```

This command starts an ACP server that communicates via stdin/stdout using nd-JSON.

#### Flags

| Flag                                        | Description                                |
| ------------------------------------------- | ------------------------------------------ |
| <nobr><code>{"--cwd"}</code></nobr>         | Working directory                          |
| <nobr><code>{"--port"}</code></nobr>        | Port to listen on                          |
| <nobr><code>{"--hostname"}</code></nobr>    | Hostname to listen on                      |
| <nobr><code>{"--mdns"}</code></nobr>        | Enable mDNS discovery                      |
| <nobr><code>{"--mdns-domain"}</code></nobr> | Custom mDNS domain name                    |
| <nobr><code>{"--cors"}</code></nobr>        | Additional browser origin(s) to allow CORS |

---

### plugin

Install a plugin and update your config.

```bash
opencode plugin <module>
```

Or use the alias.

```bash
opencode plug <module>
```

#### Flags

| Flag                                   | Short | Description                     |
| -------------------------------------- | ----- | ------------------------------- |
| <nobr><code>{"--global"}</code></nobr> | `-g`  | Install in global config        |
| <nobr><code>{"--force"}</code></nobr>  | `-f`  | Replace existing plugin version |

---

### pr

Fetch and checkout a GitHub PR branch, then run OpenCode.

```bash
opencode pr <number>
```

---

### db

Database tools.

```bash
opencode db [query]
```

#### Flags

| Flag                                   | Description                    |
| -------------------------------------- | ------------------------------ |
| <nobr><code>{"--format"}</code></nobr> | Output format: `json` or `tsv` |

---

#### path

Print the database path.

```bash
opencode db path
```

---

### debug

Debugging and troubleshooting tools.

```bash
opencode debug [command]
```

---

#### agents

List all agents.

```bash
opencode debug agents
```

---

#### config

List configuration sources.

```bash
opencode debug config
```

---

#### paths

Show global paths (data, config, cache, state).

```bash
opencode debug paths
```

Pass a name to print a single path: `db`, `home`, `data`, `config`, `cache`, `state`, `tmp`, `bin`, `log` or `repos`.

```bash
opencode debug paths db
```

---

### uninstall

Uninstall OpenCode and remove all related files.

```bash
opencode uninstall
```

#### Flags

| Flag                                        | Short | Description                                 |
| ------------------------------------------- | ----- | ------------------------------------------- |
| <nobr><code>{"--keep-config"}</code></nobr> | `-c`  | Keep configuration files                    |
| <nobr><code>{"--keep-data"}</code></nobr>   | `-d`  | Keep session data and snapshots             |
| <nobr><code>{"--dry-run"}</code></nobr>     |       | Show what would be removed without removing |
| <nobr><code>{"--force"}</code></nobr>       | `-f`  | Skip confirmation prompts                   |

---

### upgrade

Updates opencode to the latest version or a specific version.

```bash
opencode upgrade [target]
```

To upgrade to the latest version.

```bash
opencode upgrade
```

To upgrade to a specific version.

```bash
opencode upgrade v0.1.48
```

#### Flags

| Flag                                   | Short | Description                                                       |
| -------------------------------------- | ----- | ----------------------------------------------------------------- |
| <nobr><code>{"--method"}</code></nobr> | `-m`  | The installation method that was used; curl, npm, pnpm, bun, brew |

---

## Global Flags

The opencode CLI takes the following global flags.

| Flag                                       | Short | Description                          |
| ------------------------------------------ | ----- | ------------------------------------ |
| <nobr><code>{"--help"}</code></nobr>       | `-h`  | Display help                         |
| <nobr><code>{"--version"}</code></nobr>    | `-v`  | Print version number                 |
| <nobr><code>{"--print-logs"}</code></nobr> |       | Print logs to stderr                 |
| <nobr><code>{"--log-level"}</code></nobr>  |       | Log level (DEBUG, INFO, WARN, ERROR) |
| <nobr><code>{"--pure"}</code></nobr>       |       | Run without external plugins         |

---

## Environment variables

OpenCode can be configured using environment variables.

| Variable                              | Type    | Description                                       |
| ------------------------------------- | ------- | ------------------------------------------------- |
| `OPENCODE_GIT_BASH_PATH`              | string  | Path to Git Bash executable on Windows            |
| `OPENCODE_CONFIG`                     | string  | Path to config file                               |
| `OPENCODE_TUI_CONFIG`                 | string  | Path to TUI config file                           |
| `OPENCODE_CONFIG_DIR`                 | string  | Path to config directory                          |
| `OPENCODE_CONFIG_CONTENT`             | string  | Inline json config content                        |
| `OPENCODE_DISABLE_AUTOUPDATE`         | boolean | Disable automatic update checks                   |
| `OPENCODE_DISABLE_PRUNE`              | boolean | Disable pruning of old data                       |
| `OPENCODE_DISABLE_TERMINAL_TITLE`     | boolean | Disable automatic terminal title updates          |
| `OPENCODE_PERMISSION`                 | string  | Inlined json permissions config                   |
| `OPENCODE_DISABLE_DEFAULT_PLUGINS`    | boolean | Disable default plugins                           |
| `OPENCODE_DISABLE_LSP_DOWNLOAD`       | boolean | Disable automatic LSP server downloads            |
| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolean | Enable experimental models                        |
| `OPENCODE_DISABLE_AUTOCOMPACT`        | boolean | Disable automatic context compaction              |
| `OPENCODE_DISABLE_CLAUDE_CODE`        | boolean | Disable reading from `.claude` (prompt + skills)  |
| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | boolean | Disable reading `~/.claude/CLAUDE.md`             |
| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | boolean | Disable loading `.claude/skills`                  |
| `OPENCODE_DISABLE_MODELS_FETCH`       | boolean | Disable fetching models from remote sources       |
| `OPENCODE_DISABLE_MOUSE`              | boolean | Disable mouse capture in the TUI                  |
| `OPENCODE_FAKE_VCS`                   | string  | Fake VCS provider for testing purposes            |
| `OPENCODE_CLIENT`                     | string  | Client identifier (defaults to `cli`)             |
| `OPENCODE_ENABLE_EXA`                 | boolean | Enable Exa web search tools                       |
| `OPENCODE_ENABLE_PARALLEL`            | boolean | Enable Parallel web search tools                  |
| `OPENCODE_SERVER_PASSWORD`            | string  | Enable basic auth for `serve`/`web`               |
| `OPENCODE_SERVER_USERNAME`            | string  | Override basic auth username (default `opencode`) |
| `OPENCODE_MODELS_URL`                 | string  | Custom URL for fetching models configuration      |

---

### Experimental

These environment variables enable experimental features that may change or be removed.

| Variable                                        | Type    | Description                             |
| ----------------------------------------------- | ------- | --------------------------------------- |
| `OPENCODE_EXPERIMENTAL`                         | boolean | Enable the experimental umbrella flag   |
| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY`          | boolean | Enable icon discovery                   |
| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT`  | boolean | Disable copy on select in TUI           |
| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | number  | Default timeout for bash commands in ms |
| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX`        | number  | Max output tokens for LLM responses     |
| `OPENCODE_EXPERIMENTAL_FILEWATCHER`             | boolean | Enable file watcher for entire dir      |
| `OPENCODE_EXPERIMENTAL_OXFMT`                   | boolean | Enable oxfmt formatter                  |
| `OPENCODE_EXPERIMENTAL_LSP_TOOL`                | boolean | Enable experimental LSP tool            |
| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER`     | boolean | Disable file watcher                    |
| `OPENCODE_EXPERIMENTAL_EXA`                     | boolean | Enable experimental Exa features        |
| `OPENCODE_EXPERIMENTAL_LSP_TY`                  | boolean | Enable TY LSP for python files          |
| `OPENCODE_EXPERIMENTAL_PLAN_MODE`               | boolean | Enable plan mode                        |
| `OPENCODE_EXPERIMENTAL_EVENT_SYSTEM`            | boolean | Enable experimental event system        |
| `OPENCODE_EXPERIMENTAL_NATIVE_LLM`              | boolean | Enable native LLM request path          |
| `OPENCODE_EXPERIMENTAL_PARALLEL`                | boolean | Enable parallel web search execution    |
| `OPENCODE_EXPERIMENTAL_SCOUT`                   | boolean | Enable Scout subagent                   |
| `OPENCODE_EXPERIMENTAL_WORKSPACES`              | boolean | Enable workspace support                |

---

### Packages Web Src Content Docs Commands (`packages/web/src/content/docs/commands.mdx`)

---
title: Commands
description: Create custom commands for repetitive tasks.
---

Custom commands let you specify a prompt you want to run when that command is executed in the TUI.

```bash frame="none"
/my-command
```

Custom commands are in addition to the built-in commands like `/init`, `/undo`, `/redo`, `/help`. [Learn more](/docs/tui#commands).

---

## Create command files

Create markdown files in the `commands/` directory to define custom commands.

Create `.opencode/commands/test.md`:

```md title=".opencode/commands/test.md"
---
description: Run tests with coverage
agent: build
model: anthropic/claude-3-5-sonnet-20241022
---

Run the full test suite with coverage report and show any failures.
Focus on the failing tests and suggest fixes.
```

The frontmatter defines command properties. The content becomes the template.

Use the command by typing `/` followed by the command name.

```bash frame="none"
"/test"
```

---

## Configure

You can add custom commands through the OpenCode config or by creating markdown files in the `commands/` directory.

---

### JSON

Use the `command` option in your OpenCode [config](/docs/config):

```json title="opencode.jsonc" {4-12}
{
  "$schema": "https://opencode.ai/config.json",
  "command": {
    // This becomes the name of the command
    "test": {
      // This is the prompt that will be sent to the LLM
      "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.",
      // This is shown as the description in the TUI
      "description": "Run tests with coverage",
      "agent": "build",
      "model": "anthropic/claude-3-5-sonnet-20241022"
    }
  }
}
```

Now you can run this command in the TUI:

```bash frame="none"
/test
```

---

### Markdown

You can also define commands using markdown files. Place them in:

- Global: `~/.config/opencode/commands/`
- Per-project: `.opencode/commands/`

```markdown title="~/.config/opencode/commands/test.md"
---
description: Run tests with coverage
agent: build
model: anthropic/claude-3-5-sonnet-20241022
---

Run the full test suite with coverage report and show any failures.
Focus on the failing tests and suggest fixes.
```

The markdown file name becomes the command name. For example, `test.md` lets
you run:

```bash frame="none"
/test
```

---

## Prompt config

The prompts for the custom commands support several special placeholders and syntax.

---

### Arguments

Pass arguments to commands using the `$ARGUMENTS` placeholder.

```md title=".opencode/commands/component.md"
---
description: Create a new component
---

Create a new React component named $ARGUMENTS with TypeScript support.
Include proper typing and basic structure.
```

Run the command with arguments:

```bash frame="none"
/component Button
```

And `$ARGUMENTS` will be replaced with `Button`.

You can also access individual arguments using positional parameters:

- `$1` - First argument
- `$2` - Second argument
- `$3` - Third argument
- And so on...

For example:

```md title=".opencode/commands/create-file.md"
---
description: Create a new file with content
---

Create a file named $1 in the directory $2
with the following content: $3
```

Run the command:

```bash frame="none"
/create-file config.json src "{ \"key\": \"value\" }"
```

This replaces:

- `$1` with `config.json`
- `$2` with `src`
- `$3` with `{ "key": "value" }`

---

### Shell output

Use _!`command`_ to inject [shell command](/docs/tui#shell-commands) output into your prompt.

For example, to create a custom command that analyzes test coverage:

```md title=".opencode/commands/analyze-coverage.md"
---
description: Analyze test coverage
---

Here are the current test results:
!`npm test`

Based on these results, suggest improvements to increase coverage.
```

Or to review recent changes:

```md title=".opencode/commands/review-changes.md"
---
description: Review recent changes
---

Recent git commits:
!`git log --oneline -10`

Review these changes and suggest any improvements.
```

Commands run in your project's root directory and their output becomes part of the prompt.

---

### File references

Include files in your command using `@` followed by the filename.

```md title=".opencode/commands/review-component.md"
---
description: Review component
---

Review the component in @src/components/Button.tsx.
Check for performance issues and suggest improvements.
```

The file content gets included in the prompt automatically.

---

## Options

Let's look at the configuration options in detail.

---

### Template

The `template` option defines the prompt that will be sent to the LLM when the command is executed.

```json title="opencode.json"
{
  "command": {
    "test": {
      "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes."
    }
  }
}
```

This is a **required** config option.

---

### Description

Use the `description` option to provide a brief description of what the command does.

```json title="opencode.json"
{
  "command": {
    "test": {
      "description": "Run tests with coverage"
    }
  }
}
```

This is shown as the description in the TUI when you type in the command.

---

### Agent

Use the `agent` config to optionally specify which [agent](/docs/agents) should execute this command.
If this is a [subagent](/docs/agents/#subagents) the command will trigger a subagent invocation by default.
To disable this behavior, set `subtask` to `false`.

```json title="opencode.json"
{
  "command": {
    "review": {
      "agent": "plan"
    }
  }
}
```

This is an **optional** config option. If not specified, defaults to your current agent.

---

### Subtask

Use the `subtask` boolean to force the command to trigger a [subagent](/docs/agents/#subagents) invocation.
This is useful if you want the command to not pollute your primary context and will **force** the agent to act as a subagent,
even if `mode` is set to `primary` on the [agent](/docs/agents) configuration.

```json title="opencode.json"
{
  "command": {
    "analyze": {
      "subtask": true
    }
  }
}
```

This is an **optional** config option.

---

### Model

Use the `model` config to override the default model for this command.

```json title="opencode.json"
{
  "command": {
    "analyze": {
      "model": "anthropic/claude-3-5-sonnet-20241022"
    }
  }
}
```

This is an **optional** config option.

---

## Built-in

opencode includes several built-in commands like `/init`, `/undo`, `/redo`, `/help`; [learn more](/docs/tui#commands).

:::note
Custom commands can override built-in commands.
:::

If you define a custom command with the same name, it will override the built-in command.

---

### Packages Web Src Content Docs Config (`packages/web/src/content/docs/config.mdx`)

---
title: Config
description: Using the OpenCode JSON config.
---

You can configure OpenCode using a JSON config file.

---

## Format

OpenCode supports both **JSON** and **JSONC** (JSON with Comments) formats.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "model": "anthropic/claude-sonnet-4-5",
  "autoupdate": true,
  "server": {
    "port": 4096,
  },
}
```

---

## Locations

You can place your config in a couple of different locations and they have a
different order of precedence.

:::note
Configuration files are **merged together**, not replaced.
:::

Configuration files are merged together, not replaced. Settings from the following config locations are combined. Later configs override earlier ones only for conflicting keys. Non-conflicting settings from all configs are preserved.

For example, if your global config sets `autoupdate: true` and your project config sets `model: "anthropic/claude-sonnet-4-5"`, the final configuration will include both settings.

---

### Precedence order

Config sources are loaded in this order (later sources override earlier ones):

1. **Remote config** (from `.well-known/opencode`) - organizational defaults
2. **Global config** (`~/.config/opencode/opencode.json`) - user preferences
3. **Custom config** (`OPENCODE_CONFIG` env var) - custom overrides
4. **Project config** (`opencode.json` in project) - project-specific settings
5. **`.opencode` directories** - agents, commands, plugins
6. **Inline config** (`OPENCODE_CONFIG_CONTENT` env var) - runtime overrides
7. **Managed config files** (`/Library/Application Support/opencode/` on macOS) - admin-controlled
8. **macOS managed preferences** (`.mobileconfig` via MDM) - highest priority, not user-overridable

This means project configs can override global defaults, and global configs can override remote organizational defaults. Managed settings override everything.

:::note
The `.opencode` and `~/.config/opencode` directories use **plural names** for subdirectories: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/`, and `themes/`. Singular names (e.g., `agent/`) are also supported for backwards compatibility.
:::

---

### Remote

Organizations can provide default configuration via the `.well-known/opencode` endpoint. This is fetched automatically when you authenticate with a provider that supports it.

Remote config is loaded first, serving as the base layer. All other config sources (global, project) can override these defaults.

For example, if your organization provides MCP servers that are disabled by default:

```json title="Remote config from .well-known/opencode"
{
  "mcp": {
    "jira": {
      "type": "remote",
      "url": "https://jira.example.com/mcp",
      "enabled": false
    }
  }
}
```

You can enable specific servers in your local config:

```json title="opencode.json"
{
  "mcp": {
    "jira": {
      "type": "remote",
      "url": "https://jira.example.com/mcp",
      "enabled": true
    }
  }
}
```

---

### Global

Place your global OpenCode config in `~/.config/opencode/opencode.json`. Use global config for user-wide server/runtime preferences like providers, models, and permissions.

For TUI-specific settings, use `~/.config/opencode/tui.json`.

Global config overrides remote organizational defaults.

---

### Per project

Add `opencode.json` in your project root. Project config has the highest precedence among standard config files - it overrides both global and remote configs.

For project-specific TUI settings, add `tui.json` alongside it.

:::tip
Place project specific config in the root of your project.
:::

When OpenCode starts up, it first looks for a config file in the current directory, then traverses up to the nearest Git directory.

This is also safe to be checked into Git and uses the same schema as the global one.

---

### Custom path

Specify a custom config file path using the `OPENCODE_CONFIG` environment variable.

```bash
export OPENCODE_CONFIG=/path/to/my/custom-config.json
opencode run "Hello world"
```

Custom config is loaded between global and project configs in the precedence order.

---

### Custom directory

Specify a custom config directory using the `OPENCODE_CONFIG_DIR`
environment variable. This directory will be searched for agents, commands,
modes, and plugins just like the standard `.opencode` directory, and should
follow the same structure.

```bash
export OPENCODE_CONFIG_DIR=/path/to/my/config-directory
opencode run "Hello world"
```

The custom directory is loaded after the global config and `.opencode` directories, so it **can override** their settings.

---

### Managed settings

Organizations can enforce configuration that users cannot override. Managed settings are loaded at the highest priority tier.

#### File-based

Drop an `opencode.json` or `opencode.jsonc` file in the system managed config directory:

| Platform | Path                                     |
| -------- | ---------------------------------------- |
| macOS    | `/Library/Application Support/opencode/` |
| Linux    | `/etc/opencode/`                         |
| Windows  | `%ProgramData%\opencode`                 |

These directories require admin/root access to write, so users cannot modify them.

#### macOS managed preferences

On macOS, OpenCode reads managed preferences from the `ai.opencode.managed` preference domain. Deploy a `.mobileconfig` via MDM (Jamf, Kandji, FleetDM) and the settings are enforced automatically.

OpenCode checks these paths:

1. `/Library/Managed Preferences/<user>/ai.opencode.managed.plist`
2. `/Library/Managed Preferences/ai.opencode.managed.plist`

The plist keys map directly to `opencode.json` fields. MDM metadata keys (`PayloadUUID`, `PayloadType`, etc.) are stripped automatically.

**Creating a `.mobileconfig`**

Use the `ai.opencode.managed` PayloadType. The OpenCode config keys go directly in the payload dict:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>PayloadContent</key>
  <array>
    <dict>
      <key>PayloadType</key>
      <string>ai.opencode.managed</string>
      <key>PayloadIdentifier</key>
      <string>com.example.opencode.config</string>
      <key>PayloadUUID</key>
      <string>GENERATE-YOUR-OWN-UUID</string>
      <key>PayloadVersion</key>
      <integer>1</integer>
      <key>server</key>
      <dict>
        <key>hostname</key>
        <string>127.0.0.1</string>
      </dict>
      <key>permission</key>
      <dict>
        <key>*</key>
        <string>ask</string>
        <key>shell</key>
        <dict>
          <key>*</key>
          <string>ask</string>
          <key>rm -rf *</key>
          <string>deny</string>
        </dict>
      </dict>
    </dict>
  </array>
  <key>PayloadType</key>
  <string>Configuration</string>
  <key>PayloadIdentifier</key>
  <string>com.example.opencode</string>
  <key>PayloadUUID</key>
  <string>GENERATE-YOUR-OWN-UUID</string>
  <key>PayloadVersion</key>
  <integer>1</integer>
</dict>
</plist>
```

Generate unique UUIDs with `uuidgen`. Customize the settings to match your organization's requirements.

**Deploying via MDM**

- **Jamf Pro:** Computers > Configuration Profiles > Upload > scope to target devices or smart groups
- **FleetDM:** Add the `.mobileconfig` to your gitops repo under `mdm.macos_settings.custom_settings` and run `fleetctl apply`

**Verifying on a device**

Double-click the `.mobileconfig` to install locally for testing (shows in System Settings > Privacy & Security > Profiles), then run:

```bash
opencode debug config
```

All managed preference keys appear in the resolved config and cannot be overridden by user or project configuration.

---

## Schema

The server/runtime config schema is defined in [**`opencode.ai/config.json`**](https://opencode.ai/config.json).

TUI config uses [**`opencode.ai/tui.json`**](https://opencode.ai/tui.json).

Your editor should be able to validate and autocomplete based on the schema.

---

### TUI

Use a dedicated `tui.json` (or `tui.jsonc`) file for TUI-specific settings.

```json title="tui.json"
{
  "$schema": "https://opencode.ai/tui.json",
  "scroll_speed": 3,
  "scroll_acceleration": {
    "enabled": true
  },
  "diff_style": "auto",
  "cursor": {
    "style": "block",
    "blinking": true
  },
  "mouse": true,
  "attention": {
    "enabled": true,
    "notifications": true,
    "sound": true,
    "volume": 0.4
  }
}
```

Use `OPENCODE_TUI_CONFIG` to point to a custom TUI config file.

When `cursor.style` is `"default"`, the terminal default cursor is restored, so `cursor.blinking` has no effect.

Set `attention.enabled` to turn on TUI desktop notifications and sounds. See [TUI attention](/docs/tui#attention).

Legacy `theme`, `keybinds`, and `tui` keys in `opencode.json` are deprecated and automatically migrated when possible.

---

### Server

You can configure server settings for the `opencode serve` and `opencode web` commands through the `server` option.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "server": {
    "port": 4096,
    "hostname": "0.0.0.0",
    "mdns": true,
    "mdnsDomain": "myproject.local",
    "cors": ["http://localhost:5173"]
  }
}
```

Available options:

- `port` - Port to listen on.
- `hostname` - Hostname to listen on. When `mdns` is enabled and no hostname is set, defaults to `0.0.0.0`.
- `mdns` - Enable mDNS service discovery. This allows other devices on the network to discover your OpenCode server.
- `mdnsDomain` - Custom domain name for mDNS service. Defaults to `opencode.local`. Useful for running multiple instances on the same network.
- `cors` - Additional origins to allow for CORS when using the HTTP server from a browser-based client. Values must be full origins (scheme + host + optional port), eg `https://app.example.com`.

[Learn more about the server here](/docs/server).

---

### Shell

You can configure the shell used for the interactive terminal using the `shell` option. Compatible shells are also used for agent tool calls.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "shell": "pwsh"
}
```

If not specified, OpenCode will automatically discover and use a sensible default based on your operating system (e.g. `pwsh` or `cmd.exe` on Windows, `/bin/zsh` or `/bin/bash` on macOS/Linux). You can provide an absolute path or a short name.

---

### Tools

You can manage the tools an LLM can use through the `tools` option.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "tools": {
    "write": false,
    "shell": false
  }
}
```

[Learn more about tools here](/docs/tools).

---

### Models

You can configure the providers and models you want to use in your OpenCode config through the `provider`, `model` and `small_model` options.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {},
  "model": "anthropic/claude-sonnet-4-5",
  "small_model": "anthropic/claude-haiku-4-5"
}
```

The `small_model` option configures a separate model for lightweight tasks like title generation. By default, OpenCode tries to use a cheaper model if one is available from your provider, otherwise it falls back to your main model.

Provider options can include `timeout`, `headerTimeout`, `chunkTimeout`, and `setCacheKey`:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "anthropic": {
      "options": {
        "timeout": 600000,
        "chunkTimeout": 30000,
        "setCacheKey": true
      }
    }
  }
}
```

- `timeout` - Request timeout in milliseconds (default: 300000). Set to `false` to disable.
- `headerTimeout` - Timeout in milliseconds to wait for response headers (default: 300000, or 5 minutes). This timer stops once headers arrive and does not limit the streamed response body. Set to `false` to disable.
- `chunkTimeout` - Timeout in milliseconds between streamed response chunks (default: 900000, or 15 minutes). If no chunk arrives in time, the request is aborted. Set to `false` to disable.
- `setCacheKey` - Ensure a cache key is always set for designated provider.

You can also configure [local models](/docs/models#local). [Learn more](/docs/models).

---

### Policies

Use the `experimental.policies` option to allow or deny OpenCode actions on configured resources. Currently, policies can control which providers OpenCode may use.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "experimental": {
    "policies": [
      {
        "effect": "deny",
        "action": "provider.use",
        "resource": "openai"
      }
    ]
  }
}
```

[Learn more about policies here](/docs/policies).

---

### Image attachments

OpenCode normalizes image attachments before sending them to the model. By default, images are resized when they exceed `2000x2000` pixels or `5242880` base64 bytes.

Configure image attachment limits with the `attachment.image` option:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "attachment": {
    "image": {
      "auto_resize": true,
      "max_width": 2000,
      "max_height": 2000,
      "max_base64_bytes": 5242880
    }
  }
}
```

- `auto_resize` - Resize images that exceed the configured limits before provider requests. Set to `false` to reject oversized images instead.
- `max_width` - Maximum image width in pixels before resizing or rejection.
- `max_height` - Maximum image height in pixels before resizing or rejection.
- `max_base64_bytes` - Maximum encoded image payload size. This is the base64 payload size, not the original file size.

If an image still cannot fit after resizing, OpenCode omits oversized tool-result images or fails oversized user-provided images with an image size error.

---

#### Provider-Specific Options

Some providers support additional configuration options beyond the generic `timeout` and `apiKey` settings.

##### Amazon Bedrock

Amazon Bedrock supports AWS-specific configuration:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "amazon-bedrock": {
      "options": {
        "region": "us-east-1",
        "profile": "my-aws-profile",
        "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com"
      }
    }
  }
}
```

- `region` - AWS region for Bedrock (defaults to `AWS_REGION` env var or `us-east-1`)
- `profile` - AWS named profile from `~/.aws/credentials` (defaults to `AWS_PROFILE` env var)
- `endpoint` - Custom endpoint URL for VPC endpoints. This is an alias for the generic `baseURL` option using AWS-specific terminology. If both are specified, `endpoint` takes precedence.

:::note
Bearer tokens (`AWS_BEARER_TOKEN_BEDROCK` or `/connect`) take precedence over profile-based authentication. See [authentication precedence](/docs/providers#authentication-precedence) for details.
:::

[Learn more about Amazon Bedrock configuration](/docs/providers#amazon-bedrock).

---

### Themes

Set your UI theme in `tui.json`.

```json title="tui.json"
{
  "$schema": "https://opencode.ai/tui.json",
  "theme": "tokyonight"
}
```

[Learn more here](/docs/themes).

---

### Agents

You can configure specialized agents for specific tasks through the `agent` option.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "agent": {
    "code-reviewer": {
      "description": "Reviews code for best practices and potential issues",
      "model": "anthropic/claude-sonnet-4-5",
      "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.",
      "tools": {
        // Disable file modification tools for review-only agent
        "write": false,
        "edit": false,
      },
    },
  },
}
```

You can also define agents using markdown files in `~/.config/opencode/agents/` or `.opencode/agents/`. [Learn more here](/docs/agents).

---

### Default agent

You can set the default agent using the `default_agent` option. This determines which agent is used when none is explicitly specified.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "default_agent": "plan"
}
```

The default agent must be a primary agent (not a subagent). This can be a built-in agent like `"build"` or `"plan"`, or a [custom agent](/docs/agents) you've defined. If the specified agent doesn't exist or is a subagent, OpenCode will fall back to `"build"` with a warning.

This setting applies across all interfaces: TUI, CLI (`opencode run`), desktop app, and GitHub Action.

---

### Subagent depth

You can control how deeply subagents can invoke other subagents using the `subagent_depth` option.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "subagent_depth": 2
}
```

The default is `1`, which allows primary agents to launch subagents but prevents those subagents from launching additional subagents. Set it to `2` to allow one additional level of nested subagents, or `0` to prevent all subagent launches.

---

### Commands

You can configure custom commands for repetitive tasks through the `command` option.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "command": {
    "test": {
      "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.",
      "description": "Run tests with coverage",
      "agent": "build",
      "model": "anthropic/claude-haiku-4-5",
    },
    "component": {
      "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.",
      "description": "Create a new component",
    },
  },
}
```

You can also define commands using markdown files in `~/.config/opencode/commands/` or `.opencode/commands/`. [Learn more here](/docs/commands).

---

### Keybinds

Customize TUI keyboard shortcuts in `tui.json` with `keybinds`.

```json title="tui.json"
{
  "$schema": "https://opencode.ai/tui.json",
  "keybinds": {
    "command_list": "ctrl+p"
  }
}
```

`keybinds` is merged with built-in defaults, so you only need to configure the shortcuts you want to change.

[Learn more here](/docs/keybinds).

---

### Snapshot

OpenCode uses snapshots to track file changes during agent operations, enabling you to undo and revert changes within a session. Snapshots are enabled by default.

For large repositories or projects with many submodules, the snapshot system can cause slow indexing and significant disk usage as it tracks all changes using an internal git repository. You can disable snapshots using the `snapshot` option.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "snapshot": false
}
```

Note that disabling snapshots means changes made by the agent cannot be rolled back through the UI.

---

### Autoupdate

OpenCode will automatically download any new updates when it starts up. You can disable this with the `autoupdate` option.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "autoupdate": false
}
```

If you don't want updates but want to be notified when a new version is available, set `autoupdate` to `"notify"`.
Notice that this only works if it was not installed using a package manager such as Homebrew.

---

### Formatters

You can enable and configure code formatters through the `formatter` option. Omit it to keep formatters disabled.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": true
}
```

Use an object to keep built-ins enabled while configuring overrides or custom formatters.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": {
    "prettier": {
      "disabled": true
    },
    "custom-prettier": {
      "command": ["npx", "prettier", "--write", "$FILE"],
      "environment": {
        "NODE_ENV": "development"
      },
      "extensions": [".js", ".ts", ".jsx", ".tsx"]
    }
  }
}
```

[Learn more about formatters here](/docs/formatters).

---

### LSP Servers

You can enable and configure LSP servers through the `lsp` option. Omit it to keep LSP disabled.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "lsp": true
}
```

Use an object to keep built-ins enabled while configuring overrides or custom LSP servers.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "lsp": {
    "typescript": {
      "disabled": true
    }
  }
}
```

[Learn more about LSP servers here](/docs/lsp).

---

### Permissions

By default, opencode **allows all operations** without requiring explicit approval. You can change this using the `permission` option.

For example, to ensure that the `edit` and `shell` tools require user approval:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "edit": "ask",
    "shell": "ask"
  }
}
```

[Learn more about permissions here](/docs/permissions).

---

### Compaction

You can control context compaction behavior through the `compaction` option.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "compaction": {
    "auto": true,
    "prune": false,
    "reserved": 10000
  }
}
```

- `auto` - Automatically compact the session when context is full (default: `true`).
- `prune` - Remove old tool outputs to save tokens (default: `false`). Set to `true` to enable pruning.
- `reserved` - Token buffer for compaction. Leaves enough window to avoid overflow during compaction.

---

### Watcher

You can configure file watcher ignore patterns through the `watcher` option.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "watcher": {
    "ignore": ["**/generated/**"]
  }
}
```

Patterns follow glob syntax. Common dependency, VCS, build, and cache directories are ignored automatically at any depth.

---

### MCP servers

You can configure MCP servers you want to use through the `mcp` option.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {}
}
```

[Learn more here](/docs/mcp-servers).

---

### Plugins

[Plugins](/docs/plugins) extend OpenCode with custom tools, hooks, and integrations.

Place plugin files in `.opencode/plugins/` or `~/.config/opencode/plugins/`. You can also load plugins from npm through the `plugin` option.

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

[Learn more here](/docs/plugins).

---

### Instructions

You can configure the instructions for the model you're using through the `instructions` option.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"]
}
```

This takes an array of paths and glob patterns to instruction files. [Learn more
about rules here](/docs/rules).

---

### Disabled providers

You can disable providers that are loaded automatically through the `disabled_providers` option. This is useful when you want to prevent certain providers from being loaded even if their credentials are available.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "disabled_providers": ["openai", "gemini"]
}
```

:::note
The `disabled_providers` takes priority over `enabled_providers`.
:::

The `disabled_providers` option accepts an array of provider IDs. When a provider is disabled:

- It won't be loaded even if environment variables are set.
- It won't be loaded even if API keys are configured through the `/connect` command.
- The provider's models won't appear in the model selection list.

---

### Enabled providers

You can specify an allowlist of providers through the `enabled_providers` option. When set, only the specified providers will be enabled and all others will be ignored.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "enabled_providers": ["anthropic", "openai"]
}
```

This is useful when you want to restrict OpenCode to only use specific providers rather than disabling them one by one.

:::note
The `disabled_providers` takes priority over `enabled_providers`.
:::

If a provider appears in both `enabled_providers` and `disabled_providers`, the `disabled_providers` takes priority for backwards compatibility.

---

### Experimental

The `experimental` key contains options that are under active development.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "experimental": {}
}
```

:::caution
Experimental options are not stable. They may change or be removed without notice.
:::

---

## Variables

You can use variable substitution in your config files to reference environment variables and file contents.

---

### Env vars

Use `{env:VARIABLE_NAME}` to substitute environment variables:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "model": "{env:OPENCODE_MODEL}",
  "provider": {
    "anthropic": {
      "models": {},
      "options": {
        "apiKey": "{env:ANTHROPIC_API_KEY}"
      }
    }
  }
}
```

If the environment variable is not set, it will be replaced with an empty string.

---

### Files

Use `{file:path/to/file}` to substitute the contents of a file:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "instructions": ["./custom-instructions.md"],
  "provider": {
    "openai": {
      "options": {
        "apiKey": "{file:~/.secrets/openai-key}"
      }
    }
  }
}
```

File paths can be:

- Relative to the config file directory
- Or absolute paths starting with `/` or `~`

These are useful for:

- Keeping sensitive data like API keys in separate files.
- Including large instruction files without cluttering your config.
- Sharing common configuration snippets across multiple config files.

---

### Packages Web Src Content Docs Custom Tools (`packages/web/src/content/docs/custom-tools.mdx`)

---
title: Custom Tools
description: Create tools the LLM can call in opencode.
---

Custom tools are functions you create that the LLM can call during conversations. They work alongside opencode's [built-in tools](/docs/tools) like `read`, `write`, and `shell`.

---

## Creating a tool

Tools are defined as **TypeScript** or **JavaScript** files. However, the tool definition can invoke scripts written in **any language** — TypeScript or JavaScript is only used for the tool definition itself.

---

### Location

They can be defined:

- Locally by placing them in the `.opencode/tools/` directory of your project.
- Or globally, by placing them in `~/.config/opencode/tools/`.

---

### Structure

The easiest way to create tools is using the `tool()` helper which provides type-safety and validation.

```ts title=".opencode/tools/database.ts" {1}
import { tool } from "@opencode-ai/plugin"

export default tool({
  description: "Query the project database",
  args: {
    query: tool.schema.string().describe("SQL query to execute"),
  },
  async execute(args) {
    // Your database logic here
    return `Executed query: ${args.query}`
  },
})
```

The **filename** becomes the **tool name**. The above creates a `database` tool.

---

#### Multiple tools per file

You can also export multiple tools from a single file. Each export becomes **a separate tool** with the name **`<filename>_<exportname>`**:

```ts title=".opencode/tools/math.ts"
import { tool } from "@opencode-ai/plugin"

export const add = tool({
  description: "Add two numbers",
  args: {
    a: tool.schema.number().describe("First number"),
    b: tool.schema.number().describe("Second number"),
  },
  async execute(args) {
    return (args.a + args.b).toString()
  },
})

export const multiply = tool({
  description: "Multiply two numbers",
  args: {
    a: tool.schema.number().describe("First number"),
    b: tool.schema.number().describe("Second number"),
  },
  async execute(args) {
    return (args.a * args.b).toString()
  },
})
```

This creates two tools: `math_add` and `math_multiply`.

---

#### Name collisions with built-in tools

Custom tools are keyed by tool name. If a custom tool uses the same name as a built-in tool, the custom tool takes precedence.

For example, this file replaces the built-in `shell` tool:

```ts title=".opencode/tools/shell.ts"
import { tool } from "@opencode-ai/plugin"

export default tool({
  description: "Restricted shell wrapper",
  args: {
    command: tool.schema.string(),
  },
  async execute(args) {
    return `blocked: ${args.command}`
  },
})
```

:::note
Prefer unique names unless you intentionally want to replace a built-in tool. If you want to disable a built in tool but not override it, use [permissions](/docs/permissions).
:::

---

### Arguments

You can use `tool.schema`, which is just [Zod](https://zod.dev), to define argument types.

```ts "tool.schema"
args: {
  query: tool.schema.string().describe("SQL query to execute")
}
```

You can also import [Zod](https://zod.dev) directly and return a plain object:

```ts {6}
import { z } from "zod"

export default {
  description: "Tool description",
  args: {
    param: z.string().describe("Parameter description"),
  },
  async execute(args, context) {
    // Tool implementation
    return "result"
  },
}
```

---

### Context

Tools receive context about the current session:

```ts title=".opencode/tools/project.ts" {8}
import { tool } from "@opencode-ai/plugin"

export default tool({
  description: "Get project information",
  args: {},
  async execute(args, context) {
    // Access context information
    const { agent, sessionID, messageID, directory, worktree } = context
    return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}`
  },
})
```

Use `context.directory` for the session working directory.
Use `context.worktree` for the git worktree root.

---

## Examples

### Write a tool in Python

You can write your tools in any language you want. Here's an example that adds two numbers using Python.

First, create the tool as a Python script:

```python title=".opencode/tools/add.py"
import sys

a = int(sys.argv[1])
b = int(sys.argv[2])
print(a + b)
```

Then create the tool definition that invokes it:

```ts title=".opencode/tools/python-add.ts" {10}
import { tool } from "@opencode-ai/plugin"
import path from "path"

export default tool({
  description: "Add two numbers using Python",
  args: {
    a: tool.schema.number().describe("First number"),
    b: tool.schema.number().describe("Second number"),
  },
  async execute(args, context) {
    const script = path.join(context.worktree, ".opencode/tools/add.py")
    const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text()
    return result.trim()
  },
})
```

Here we are using the [`Bun.$`](https://bun.com/docs/runtime/shell) utility to run the Python script.

---

### Packages Web Src Content Docs Ecosystem (`packages/web/src/content/docs/ecosystem.mdx`)

---
title: Ecosystem
description: Projects and integrations built with OpenCode.
---

A collection of community projects built on OpenCode.

:::note
Want to add your OpenCode related project to this list? Submit a PR.
:::

You can also check out [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) and [opencode.cafe](https://opencode.cafe), a community that aggregates the ecosystem and community.

---

## Plugins

| Name                                                                                               | Description                                                                                                                      |
| -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| [opencode-daytona](https://github.com/daytona/integrations/tree/main/packages/opencode-plugin)     | Automatically run OpenCode sessions in isolated Daytona sandboxes with git sync and live previews                                |
| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session)                  | Automatically inject Helicone session headers for request grouping                                                               |
| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject)                            | Auto-inject TypeScript/Svelte types into file reads with lookup tools                                                            |
| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth)             | Use your ChatGPT Plus/Pro subscription instead of API credits                                                                    |
| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth)                            | Use your existing Gemini plan instead of API billing                                                                             |
| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth)                | Use Antigravity's free models instead of API billing                                                                             |
| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers)                         | Multi-branch devcontainer isolation with shallow clones and auto-assigned ports                                                  |
| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth)   | Google Antigravity OAuth Plugin, with support for Google Search, and more robust API handling                                    |
| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning)  | Optimize token usage by pruning obsolete tool outputs                                                                            |
| [opencode-vibeguard](https://github.com/inkdust2021/opencode-vibeguard)                            | Redact secrets/PII into VibeGuard-style placeholders before LLM calls; restore locally                                           |
| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git)                 | Add native websearch support for supported providers with Google grounded style                                                  |
| [opencode-pty](https://github.com/shekohex/opencode-pty.git)                                       | Enables AI agents to run background processes in a PTY, send interactive input to them.                                          |
| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy)                     | Instructions for non-interactive shell commands - prevents hangs from TTY-dependent operations                                   |
| [opencode-wakatime](https://github.com/angristan/opencode-wakatime)                                | Track OpenCode usage with Wakatime                                                                                               |
| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main)    | Clean up markdown tables produced by LLMs                                                                                        |
| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply)                 | 10x faster code editing with Morph Fast Apply API and lazy edit markers                                                          |
| [opencode-morph-plugin](https://github.com/morphllm/opencode-morph-plugin)                         | Fast Apply editing, WarpGrep codebase search, and context compaction via Morph                                                   |
| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode)                                   | Background agents, pre-built LSP/AST/MCP tools, curated agents, Claude Code compatible                                           |
| [opencode-notificator](https://github.com/panta82/opencode-notificator)                            | Desktop notifications and sound alerts for OpenCode sessions                                                                     |
| [opencode-notifier](https://github.com/mohak34/opencode-notifier)                                  | Desktop notifications and sound alerts for permission, completion, and error events                                              |
| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer)                            | AI-powered automatic Zellij session naming based on OpenCode context                                                             |
| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful)                                | Allow OpenCode agents to lazy load prompts on demand with skill discovery and injection                                          |
| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory)                      | Persistent memory across sessions using Supermemory                                                                              |
| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | Interactive plan review with visual annotation and private/offline sharing                                                       |
| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2)                              | Extend opencode /commands into a powerful orchestration system with granular flow control                                        |
| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler)                           | Schedule recurring jobs using launchd (Mac) or systemd (Linux) with cron syntax                                                  |
| [opencode-conductor](https://github.com/derekbar90/opencode-conductor)                             | Protocol-Driven Workflow: Automation of the Context -> Spec -> Plan -> Implement lifecycle.                                      |
| [micode](https://github.com/vtemian/micode)                                                        | Structured Brainstorm → Plan → Implement workflow with session continuity                                                        |
| [octto](https://github.com/vtemian/octto)                                                          | Interactive browser UI for AI brainstorming with multi-question forms                                                            |
| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents)              | Claude Code-style background agents with async delegation and context persistence                                                |
| [opencode-notify](https://github.com/kdcokenny/opencode-notify)                                    | Native OS notifications for OpenCode – know when tasks complete                                                                  |
| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace)                              | Bundled multi-agent orchestration harness – 16 components, one install                                                           |
| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree)                                | Zero-friction git worktrees for OpenCode                                                                                         |
| [opencode-sentry-monitor](https://github.com/stolinski/opencode-sentry-monitor)                    | Trace and debug your AI agents with Sentry AI Monitoring                                                                         |
| [opencode-firecrawl](https://github.com/firecrawl/opencode-firecrawl)                              | Web scraping, crawling, and search via the Firecrawl CLI                                                                         |
| [opencode-jfrog-plugin](https://github.com/jfrog/opencode-jfrog-plugin)                            | JFrog Plugin for seamless integration of Opencode users to JFrog platform                                                        |
| [opencode-goal-plugin](https://github.com/willytop8/OpenCode-goal-plugin)                          | Session-scoped `/goal` workflow that keeps objectives in context and auto-continues until complete                               |
| [opencode-tavily](https://github.com/tavily-ai/opencode-tavily)                                    | Web search, extraction, crawling, and deep research via the Tavily CLI                                                           |
| [opencode-supabase](https://github.com/supabase-community/opencode-supabase)                       | Supabase plugin for OpenCode: account login, Management API tools, bundled Supabase agent skills, and guided Supabase MCP setup. |

---

## Projects

| Name                                                                                       | Description                                                      |
| ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------- |
| [kimaki](https://kimaki.dev)                                                               | Discord bot to control OpenCode sessions, built on the SDK       |
| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim)                              | Neovim plugin for editor-aware prompts, built on the API         |
| [portal](https://github.com/hosenur/portal)                                                | Mobile-first web UI for OpenCode over Tailscale/VPN              |
| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/)         | Template for building OpenCode plugins                           |
| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim)                                 | Neovim frontend for opencode - a terminal-based AI coding agent  |
| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | Vercel AI SDK provider for using OpenCode via @opencode-ai/sdk   |
| [OpenChamber](https://github.com/btriapitsyn/openchamber)                                  | Web / Desktop App and VS Code Extension for OpenCode             |
| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian)                           | Obsidian plugin that embeds OpenCode in Obsidian's UI            |
| [OpenWork](https://github.com/different-ai/openwork)                                       | An open-source alternative to Claude Cowork, powered by OpenCode |
| [ocx](https://github.com/kdcokenny/ocx)                                                    | OpenCode extension manager with portable, isolated profiles.     |
| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad)                                   | Desktop, Web, Mobile and Remote Client App for OpenCode          |

---

## Agents

| Name                                                              | Description                                                  |
| ----------------------------------------------------------------- | ------------------------------------------------------------ |
| [Agentic](https://github.com/Cluster444/agentic)                  | Modular AI agents and commands for structured development    |
| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | Configs, prompts, agents, and plugins for enhanced workflows |

---

### Packages Web Src Content Docs Enterprise (`packages/web/src/content/docs/enterprise.mdx`)

---
title: Enterprise
description: Using OpenCode securely in your organization.
---

export const enterprise = "https://opencode.ai/enterprise"

OpenCode Enterprise is for organizations that want to ensure that their code and data never leaves their infrastructure. It can do this by using a centralized config that integrates with your SSO and internal AI gateway.

:::note
OpenCode does not store any of your code or context data.
:::

To get started with OpenCode Enterprise:

1. Do a trial internally with your team.
2. **<a href={enterprise}>Contact us</a>** to discuss pricing and implementation options.

---

## Trial

OpenCode is open source and does not store any of your code or context data, so your developers can simply [get started](/docs/) and carry out a trial.

---

### Data handling

**OpenCode does not store your code or context data.** All processing happens locally or through direct API calls to your AI provider.

This means that as long as you are using a provider you trust, or an internal
AI gateway, you can use OpenCode securely.

---

### Code ownership

**You own all code produced by OpenCode.** There are no licensing restrictions or ownership claims.

---

## Pricing

We use a per-seat model for OpenCode Enterprise. If you have your own LLM gateway, we do not charge for tokens used. For further details about pricing and implementation options, **<a href={enterprise}>contact us</a>**.

---

## Deployment

Once you have completed your trial and you are ready to use OpenCode at
your organization, you can **<a href={enterprise}>contact us</a>** to discuss
pricing and implementation options.

---

### Central Config

We can set up OpenCode to use a single central config for your entire organization.

This centralized config can integrate with your SSO provider and ensures all users access only your internal AI gateway.

---

### SSO integration

Through the central config, OpenCode can integrate with your organization's SSO provider for authentication.

This allows OpenCode to obtain credentials for your internal AI gateway through your existing identity management system.

---

### Internal AI gateway

With the central config, OpenCode can also be configured to use only your internal AI gateway.

You can also disable all other AI providers, ensuring all requests go through your organization's approved infrastructure.

---

### Self-hosting

While we recommend disabling the share pages to ensure your data never leaves
your organization, we can also help you self-host them on your infrastructure.

This is currently on our roadmap. If you're interested, **<a href={enterprise}>let us know</a>**.

---

## FAQ

<details>
<summary>What is OpenCode Enterprise?</summary>

OpenCode Enterprise is for organizations that want to ensure that their code and data never leaves their infrastructure. It can do this by using a centralized config that integrates with your SSO and internal AI gateway.

</details>

<details>
<summary>How do I get started with OpenCode Enterprise?</summary>

Simply start with an internal trial with your team. OpenCode by default does not store your code or context data, making it easy to get started.

Then **<a href={enterprise}>contact us</a>** to discuss pricing and implementation options.

</details>

<details>
<summary>How does enterprise pricing work?</summary>

We offer per-seat enterprise pricing. If you have your own LLM gateway, we do not charge for tokens used. For further details, **<a href={enterprise}>contact us</a>** for a custom quote based on your organization's needs.

</details>

<details>
<summary>Is my data secure with OpenCode Enterprise?</summary>

Yes. OpenCode does not store your code or context data. All processing happens locally or through direct API calls to your AI provider. With central config and SSO integration, your data remains secure within your organization's infrastructure.

</details>

<details>
<summary>Can we use our own private NPM registry?</summary>

OpenCode supports private npm registries through Bun's native `.npmrc` file support. If your organization uses a private registry, such as JFrog Artifactory, Nexus, or similar, ensure developers are authenticated before running OpenCode.

To set up authentication with your private registry:

```bash
npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/
```

This creates `~/.npmrc` with authentication details. OpenCode will automatically
pick this up.

:::caution
You must be logged into the private registry before running OpenCode.
:::

Alternatively, you can manually configure a `.npmrc` file:

```bash title="~/.npmrc"
registry=https://your-company.jfrog.io/api/npm/npm-virtual/
//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN}
```

Developers must be logged into the private registry before running OpenCode to ensure packages can be installed from your enterprise registry.

</details>

---

### Packages Web Src Content Docs Formatters (`packages/web/src/content/docs/formatters.mdx`)

---
title: Formatters
description: OpenCode uses language specific formatters.
---

OpenCode can format files after they are written or edited using language-specific formatters. Formatters are disabled by default; enable them in your config before OpenCode will run them.

---

## Built-in

OpenCode comes with several built-in formatters for popular languages and frameworks. Below is a list of the formatters, supported file extensions, and commands or config options it needs.

| Formatter            | Extensions                                                                                               | Requirements                                                                                          |
| -------------------- | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| air                  | .R                                                                                                       | `air` command available                                                                               |
| biome                | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, and [more](https://biomejs.dev/)                   | `biome.json(c)` config file                                                                           |
| cargofmt             | .rs                                                                                                      | `cargo fmt` command available                                                                         |
| clang-format         | .c, .cpp, .h, .hpp, .ino, and [more](https://clang.llvm.org/docs/ClangFormat.html)                       | `.clang-format` config file                                                                           |
| cljfmt               | .clj, .cljs, .cljc, .edn                                                                                 | `cljfmt` command available                                                                            |
| dart                 | .dart                                                                                                    | `dart` command available                                                                              |
| dfmt                 | .d                                                                                                       | `dfmt` command available                                                                              |
| gleam                | .gleam                                                                                                   | `gleam` command available                                                                             |
| gofmt                | .go                                                                                                      | `gofmt` command available                                                                             |
| htmlbeautifier       | .erb, .html.erb                                                                                          | `htmlbeautifier` command available                                                                    |
| ktlint               | .kt, .kts                                                                                                | `ktlint` command available                                                                            |
| mix                  | .ex, .exs, .eex, .heex, .leex, .neex, .sface                                                             | `mix` command available                                                                               |
| nixfmt               | .nix                                                                                                     | `nixfmt` command available                                                                            |
| ocamlformat          | .ml, .mli                                                                                                | `ocamlformat` command available and `.ocamlformat` config file                                        |
| ormolu               | .hs                                                                                                      | `ormolu` command available                                                                            |
| oxfmt (Experimental) | .js, .jsx, .ts, .tsx                                                                                     | `oxfmt` dependency in `package.json` and an [experimental env variable flag](/docs/cli/#experimental) |
| pint                 | .php                                                                                                     | `laravel/pint` dependency in `composer.json`                                                          |
| prettier             | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, and [more](https://prettier.io/docs/en/index.html) | `prettier` dependency in `package.json`                                                               |
| rubocop              | .rb, .rake, .gemspec, .ru                                                                                | `rubocop` command available                                                                           |
| ruff                 | .py, .pyi                                                                                                | `ruff` command available with config                                                                  |
| rustfmt              | .rs                                                                                                      | `rustfmt` command available                                                                           |
| shfmt                | .sh, .bash                                                                                               | `shfmt` command available                                                                             |
| standardrb           | .rb, .rake, .gemspec, .ru                                                                                | `standardrb` command available                                                                        |
| terraform            | .tf, .tfvars                                                                                             | `terraform` command available                                                                         |
| uv                   | .py, .pyi                                                                                                | `uv` command available                                                                                |
| zig                  | .zig, .zon                                                                                               | `zig` command available                                                                               |

When formatters are enabled, OpenCode will use `prettier` for matching files if your project has `prettier` in `package.json`.

---

## How it works

When OpenCode writes or edits a file and formatters are enabled, it:

1. Checks the file extension against all enabled formatters.
2. Runs the appropriate formatter command on the file.
3. Applies the formatting changes.

This process happens in the background for enabled formatters.

---

## Configure

You can enable and customize formatters through the `formatter` section in your OpenCode config.

To enable all built-in formatters, set `formatter` to `true`.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": true
}
```

Use an object to keep built-ins enabled while configuring overrides or custom formatters.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": {}
}
```

Each formatter configuration supports the following:

| Property      | Type     | Description                                                                                |
| ------------- | -------- | ------------------------------------------------------------------------------------------ |
| `disabled`    | boolean  | Set this to `true` to disable the formatter                                                |
| `command`     | string[] | The command to run for formatting. Required for custom formatters; optional for built-ins. |
| `environment` | object   | Environment variables to set when running the formatter                                    |
| `extensions`  | string[] | File extensions this formatter should handle                                               |

Let's look at some examples.

---

### Disabling formatters

If `formatter` is omitted, all formatters are disabled. To disable all formatters after another config enabled them, set `formatter` to `false`:

```json title="opencode.json" {3}
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": false
}
```

To disable a **specific** formatter, set `disabled` to `true`:

```json title="opencode.json" {5}
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": {
    "prettier": {
      "disabled": true
    }
  }
}
```

---

### Custom formatters

You can configure built-in formatters with options like `environment` or `extensions`. To add a custom formatter, specify a `command` and `extensions`:

```json title="opencode.json" {4-14}
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": {
    "prettier": {
      "command": ["npx", "prettier", "--write", "$FILE"],
      "environment": {
        "NODE_ENV": "development"
      },
      "extensions": [".js", ".ts", ".jsx", ".tsx"]
    },
    "custom-markdown-formatter": {
      "command": ["deno", "fmt", "$FILE"],
      "extensions": [".md"]
    }
  }
}
```

The **`$FILE` placeholder** in the command will be replaced with the path to the file being formatted.

---

### Packages Web Src Content Docs Github (`packages/web/src/content/docs/github.mdx`)

---
title: GitHub
description: Use OpenCode in GitHub issues and pull-requests.
---

OpenCode integrates with your GitHub workflow. Mention `/opencode` or `/oc` in your comment, and OpenCode will execute tasks within your GitHub Actions runner.

---

## Features

- **Triage issues**: Ask OpenCode to look into an issue and explain it to you.
- **Fix and implement**: Ask OpenCode to fix an issue or implement a feature. And it will work in a new branch and submits a PR with all the changes.
- **Secure**: OpenCode runs inside your GitHub's runners.

---

## Installation

Run the following command in a project that is in a GitHub repo:

```bash
opencode github install
```

This will walk you through installing the GitHub app, creating the workflow, and setting up secrets.

---

### Manual Setup

Or you can set it up manually.

1. **Install the GitHub app**

   Head over to [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent). Make sure it's installed on the target repository.

2. **Add the workflow**

   Add the following workflow file to `.github/workflows/opencode.yml` in your repo. Make sure to set the appropriate `model` and required API keys in `env`.

   ```yml title=".github/workflows/opencode.yml" {24,26}
   name: opencode

   on:
     issue_comment:
       types: [created]
     pull_request_review_comment:
       types: [created]

   jobs:
     opencode:
       if: |
         contains(github.event.comment.body, '/oc') ||
         contains(github.event.comment.body, '/opencode')
       runs-on: ubuntu-latest
       permissions:
         id-token: write
       steps:
         - name: Checkout repository
           uses: actions/checkout@v6
           with:
             fetch-depth: 1
             persist-credentials: false

         - name: Run OpenCode
           uses: anomalyco/opencode/github@latest
           env:
             ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
           with:
             model: anthropic/claude-sonnet-4-20250514
   ```

3. **Store the API keys in secrets**

   In your organization or project **settings**, expand **Secrets and variables** on the left and select **Actions**. And add the required API keys.

---

## Configuration

- `model`: The model to use with OpenCode. Takes the format of `provider/model`. This is **required**.
- `agent`: The agent to use. Must be a primary agent. Falls back to `default_agent` from config or `"build"` if not found.
- `prompt`: Optional custom prompt to override the default behavior. Use this to customize how OpenCode processes requests.
- `mentions`: Comma-separated list of trigger phrases, case-insensitive. Defaults to `/opencode,/oc`.
- `variant`: Model variant for provider-specific reasoning effort, for example `high`, `max`, or `minimal`.
- `oidc_base_url`: Base URL for the OIDC token exchange API. Only needed when running a custom GitHub App install. Defaults to `https://api.opencode.ai`.
- `use_github_token`: Set to `true` to use a caller-provided `GITHUB_TOKEN` instead of exchanging an OIDC token for an OpenCode App installation token. Defaults to `false`.

  Use this mode to run without installing the OpenCode GitHub App. Pass the token through `env` and grant the permissions required by your workflow:

  ```yaml
  permissions:
    contents: write
    pull-requests: write
    issues: write

  steps:
    - uses: anomalyco/opencode/github@latest
      env:
        ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        model: anthropic/claude-sonnet-4-20250514
        use_github_token: true
  ```

  `id-token: write` is not required in this mode because OIDC exchange is skipped. To use a [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) or another GitHub App token, store it as a secret and pass that secret as `GITHUB_TOKEN` instead.

---

## Supported Events

OpenCode can be triggered by the following GitHub events:

| Event Type                    | Triggered By                           | Details                                                                                                           |
| ----------------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `issue_comment`               | Comment on an issue or PR              | Mention `/opencode` or `/oc` in your comment. OpenCode reads context and can create branches, open PRs, or reply. |
| `pull_request_review_comment` | Comment on specific code lines in a PR | Mention `/opencode` or `/oc` while reviewing code. OpenCode receives file path, line numbers, and diff context.   |
| `issues`                      | Issue opened or edited                 | Automatically trigger OpenCode when issues are created or modified. Requires `prompt` input.                      |
| `pull_request`                | PR opened or updated                   | Automatically trigger OpenCode when PRs are opened, synchronized, or reopened. Useful for automated reviews.      |
| `schedule`                    | Cron-based schedule                    | Run OpenCode on a schedule. Requires `prompt` input. Output goes to logs and PRs (no issue to comment on).        |
| `workflow_dispatch`           | Manual trigger from GitHub UI          | Trigger OpenCode on demand via Actions tab. Requires `prompt` input. Output goes to logs and PRs.                 |

### Schedule Example

Run OpenCode on a schedule to perform automated tasks:

```yaml title=".github/workflows/opencode-scheduled.yml"
name: Scheduled OpenCode Task

on:
  schedule:
    - cron: "0 9 * * 1" # Every Monday at 9am UTC

jobs:
  opencode:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: write
      pull-requests: write
      issues: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
        with:
          persist-credentials: false

      - name: Run OpenCode
        uses: anomalyco/opencode/github@latest
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        with:
          model: anthropic/claude-sonnet-4-20250514
          prompt: |
            Review the codebase for any TODO comments and create a summary.
            If you find issues worth addressing, open an issue to track them.
```

For scheduled events, the `prompt` input is **required** since there's no comment to extract instructions from. Scheduled workflows run without a user context to permission-check, so the workflow must grant `contents: write` and `pull-requests: write` if you expect OpenCode to create branches or PRs.

---

### Pull Request Example

Automatically review PRs when they are opened or updated:

```yaml title=".github/workflows/opencode-review.yml"
name: opencode-review

on:
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]

jobs:
  review:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
      pull-requests: read
      issues: read
    steps:
      - uses: actions/checkout@v6
        with:
          persist-credentials: false
      - uses: anomalyco/opencode/github@latest
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          model: anthropic/claude-sonnet-4-20250514
          use_github_token: true
          prompt: |
            Review this pull request:
            - Check for code quality issues
            - Look for potential bugs
            - Suggest improvements
```

For `pull_request` events, if no `prompt` is provided, OpenCode defaults to reviewing the pull request.

---

### Issues Triage Example

Automatically triage new issues. This example filters to accounts older than 30 days to reduce spam:

```yaml title=".github/workflows/opencode-triage.yml"
name: Issue Triage

on:
  issues:
    types: [opened]

jobs:
  triage:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: write
      pull-requests: write
      issues: write
    steps:
      - name: Check account age
        id: check
        uses: actions/github-script@v7
        with:
          script: |
            const user = await github.rest.users.getByUsername({
              username: context.payload.issue.user.login
            });
            const created = new Date(user.data.created_at);
            const days = (Date.now() - created) / (1000 * 60 * 60 * 24);
            return days >= 30;
          result-encoding: string

      - uses: actions/checkout@v6
        if: steps.check.outputs.result == 'true'
        with:
          persist-credentials: false

      - uses: anomalyco/opencode/github@latest
        if: steps.check.outputs.result == 'true'
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        with:
          model: anthropic/claude-sonnet-4-20250514
          prompt: |
            Review this issue. If there's a clear fix or relevant docs:
            - Provide documentation links
            - Add error handling guidance for code examples
            Otherwise, do not comment.
```

For `issues` events, the `prompt` input is **required** since there's no comment to extract instructions from.

---

## Custom prompts

Override the default prompt to customize OpenCode's behavior for your workflow.

```yaml title=".github/workflows/opencode.yml"
- uses: anomalyco/opencode/github@latest
  with:
    model: anthropic/claude-sonnet-4-5
    prompt: |
      Review this pull request:
      - Check for code quality issues
      - Look for potential bugs
      - Suggest improvements
```

This is useful for enforcing specific review criteria, coding standards, or focus areas relevant to your project.

---

## Examples

Here are some examples of how you can use OpenCode in GitHub.

- **Explain an issue**

  Add this comment in a GitHub issue.

  ```
  /opencode explain this issue
  ```

  OpenCode will read the entire thread, including all comments, and reply with a clear explanation.

- **Fix an issue**

  In a GitHub issue, say:

  ```
  /opencode fix this
  ```

  And OpenCode will create a new branch, implement the changes, and open a PR with the changes.

- **Review PRs and make changes**

  Leave the following comment on a GitHub PR.

  ```
  Delete the attachment from S3 when the note is removed /oc
  ```

  OpenCode will implement the requested change and commit it to the same PR.

- **Review specific code lines**

  Leave a comment directly on code lines in the PR's "Files" tab. OpenCode automatically detects the file, line numbers, and diff context to provide precise responses.

  ```
  [Comment on specific lines in Files tab]
  /oc add error handling here
  ```

  When commenting on specific lines, OpenCode receives:
  - The exact file being reviewed
  - The specific lines of code
  - The surrounding diff context
  - Line number information

  This allows for more targeted requests without needing to specify file paths or line numbers manually.

---

### Packages Web Src Content Docs Gitlab (`packages/web/src/content/docs/gitlab.mdx`)

---
title: GitLab
description: Use OpenCode in GitLab issues and merge requests.
---

OpenCode integrates with your GitLab workflow through your GitLab CI/CD pipeline or with GitLab Duo.

In both cases, OpenCode will run on your GitLab runners.

---

## GitLab CI

OpenCode works in a regular GitLab pipeline. You can build it into a pipeline as a [CI component](https://docs.gitlab.com/ee/ci/components/)

Here we are using a community-created CI/CD component for OpenCode — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode).

---

### Features

- **Use custom configuration per job**: Configure OpenCode with a custom configuration directory, for example `./config/#custom-directory` to enable or disable functionality per OpenCode invocation.
- **Minimal setup**: The CI component sets up OpenCode in the background, you only need to create the OpenCode configuration and the initial prompt.
- **Flexible**: The CI component supports several inputs for customizing its behavior

---

### Setup

1. Store your OpenCode authentication JSON as a File type CI environment variables under **Settings** > **CI/CD** > **Variables**. Make sure to mark them as "Masked and hidden".
2. Add the following to your `.gitlab-ci.yml` file.

   ```yaml title=".gitlab-ci.yml"
   include:
     - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2
       inputs:
         config_dir: ${CI_PROJECT_DIR}/opencode-config
         auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON
         command: optional-custom-command
         message: "Your prompt here"
   ```

For more inputs and use cases [check out the docs](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) for this component.

---

## GitLab Duo

OpenCode integrates with your GitLab workflow.
Mention `@opencode` in a comment, and OpenCode will execute tasks within your GitLab CI pipeline.

---

### Features

- **Triage issues**: Ask OpenCode to look into an issue and explain it to you.
- **Fix and implement**: Ask OpenCode to fix an issue or implement a feature.
  It will create a new branch and raise a merge request with the changes.
- **Secure**: OpenCode runs on your GitLab runners.

---

### Setup

OpenCode runs in your GitLab CI/CD pipeline, here's what you'll need to set it up:

:::tip
Check out the [**GitLab docs**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) for up to date instructions.
:::

1.  Configure your GitLab environment
2.  Set up CI/CD
3.  Get an AI model provider API key
4.  Create a service account
5.  Configure CI/CD variables
6.  Create a flow config file, here's an example:

        <details>

    <summary>Flow configuration</summary>

    ```
/* Detailed source-code truncated for AI context efficiency. */
```

        </details>

You can refer to the [GitLab CLI agents docs](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) for detailed instructions.

---

### Examples

Here are some examples of how you can use OpenCode in GitLab.

:::tip
You can configure to use a different trigger phrase than `@opencode`.
:::

- **Explain an issue**

  Add this comment in a GitLab issue.

  ```
  @opencode explain this issue
  ```

  OpenCode will read the issue and reply with a clear explanation.

- **Fix an issue**

  In a GitLab issue, say:

  ```
  @opencode fix this
  ```

  OpenCode will create a new branch, implement the changes, and open a merge request with the changes.

- **Review merge requests**

  Leave the following comment on a GitLab merge request.

  ```
  @opencode review this merge request
  ```

  OpenCode will review the merge request and provide feedback.

---

### Packages Web Src Content Docs Ide (`packages/web/src/content/docs/ide.mdx`)

---
title: IDE
description: The OpenCode extension for VS Code, Cursor, and other IDEs
---

OpenCode integrates with VS Code, Cursor, or any IDE that supports a terminal. Just run `opencode` in the terminal to get started.

---

## Usage

- **Quick Launch**: Use `Cmd+Esc` (Mac) or `Ctrl+Esc` (Windows/Linux) to open OpenCode in a split terminal view, or focus an existing terminal session if one is already running.
- **New Session**: Use `Cmd+Shift+Esc` (Mac) or `Ctrl+Shift+Esc` (Windows/Linux) to start a new OpenCode terminal session, even if one is already open. You can also click the OpenCode button in the UI.
- **Context Awareness**: Automatically share your current selection or tab with OpenCode.
- **File Reference Shortcuts**: Use `Cmd+Option+K` (Mac) or `Alt+Ctrl+K` (Linux/Windows) to insert file references. For example, `@File#L37-42`.

---

## Installation

To install OpenCode on VS Code and popular forks like Cursor, Windsurf, VSCodium:

1. Open VS Code
2. Open the integrated terminal
3. Run `opencode` - the extension installs automatically

If on the other hand you want to use your own IDE when you run `/editor` or `/export` from the TUI, you'll need to set `export EDITOR="code --wait"`. [Learn more](/docs/tui/#editor-setup).

---

### Manual Install

Search for **OpenCode** in the Extension Marketplace and click **Install**.

---

### Troubleshooting

If the extension fails to install automatically:

- Ensure you’re running `opencode` in the integrated terminal.
- Confirm the CLI for your IDE is installed:
  - For VS Code: `code` command
  - For Cursor: `cursor` command
  - For Windsurf: `windsurf` command
  - For VSCodium: `codium` command
  - If not, run `Cmd+Shift+P` (Mac) or `Ctrl+Shift+P` (Windows/Linux) and search for "Shell Command: Install 'code' command in PATH" (or the equivalent for your IDE)
- Ensure VS Code has permission to install extensions

---

### Packages Web Src Content Docs Keybinds (`packages/web/src/content/docs/keybinds.mdx`)

---
title: Keybinds
description: Customize your keybinds.
---

OpenCode has a list of keybinds that you can customize through `tui.json`.

```
/* Detailed source-code truncated for AI context efficiency. */
```

:::note
On Windows, the defaults for `input_undo` and `terminal_suspend` are different:

- `input_undo` defaults to `ctrl+z,ctrl+-,super+z` when it is not explicitly configured. The `ctrl+z` binding is added because Windows terminals do not support POSIX suspend.
- `terminal_suspend` is forced to `none` because native Windows terminals do not support POSIX suspend.
  :::

---

## Leader Key

OpenCode uses a `leader` key for many keybinds. This avoids conflicts in your terminal.

By default, `ctrl+x` is the leader key and many actions require you to first press the leader key and then the shortcut. For example, to start a new session you first press `ctrl+x` and then press `n`.

You don't need to use a leader key for your keybinds but we recommend doing so.

Some navigation keybinds intentionally do not use the leader key by default. For subagent sessions, the defaults are `session_child_first` = `<leader>down`, `session_child_cycle` = `right`, `session_child_cycle_reverse` = `left`, and `session_parent` = `up`.

`leader_timeout` controls how long OpenCode waits for the next key after the leader key. It defaults to `2000` milliseconds.

---

## Binding Values

A string can contain one shortcut or multiple comma-separated shortcuts. You can also use an array for multiple shortcuts.

For advanced cases, use an object with `key`, `event`, `preventDefault`, or `fallthrough`.

```json title="tui.json"
{
  "$schema": "https://opencode.ai/tui.json",
  "keybinds": {
    "messages_copy": ["<leader>y", "ctrl+shift+c"],
    "input_paste": {
      "key": "ctrl+v",
      "preventDefault": false
    }
  }
}
```

---

## Disable Keybind

You can disable a keybind by adding the key to `tui.json` with a value of `"none"` or `false`.

```json title="tui.json"
{
  "$schema": "https://opencode.ai/tui.json",
  "keybinds": {
    "session_compact": "none"
  }
}
```

---

## Desktop Prompt Shortcuts

The OpenCode desktop app prompt input supports common Readline/Emacs-style shortcuts for editing text. These are built-in and currently not configurable via `opencode.json`.

| Shortcut | Action                                   |
| -------- | ---------------------------------------- |
| `ctrl+a` | Move to start of current line            |
| `ctrl+e` | Move to end of current line              |
| `ctrl+b` | Move cursor back one character           |
| `ctrl+f` | Move cursor forward one character        |
| `alt+b`  | Move cursor back one word                |
| `alt+f`  | Move cursor forward one word             |
| `ctrl+d` | Delete character under cursor            |
| `ctrl+k` | Kill to end of line                      |
| `ctrl+u` | Kill to start of line                    |
| `ctrl+w` | Kill previous word                       |
| `alt+d`  | Kill next word                           |
| `ctrl+t` | Transpose characters                     |
| `ctrl+g` | Cancel popovers / abort running response |

---

## Shift+Enter

Some terminals don't send modifier keys with Enter by default. You may need to configure your terminal to send `Shift+Enter` as an escape sequence.

### Windows Terminal

Open your `settings.json` at:

```
%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json
```

Add this to the root-level `actions` array:

```json
"actions": [
  {
    "command": {
      "action": "sendInput",
      "input": "\u001b[13;2u"
    },
    "id": "User.sendInput.ShiftEnterCustom"
  }
]
```

Add this to the root-level `keybindings` array:

```json
"keybindings": [
  {
    "keys": "shift+enter",
    "id": "User.sendInput.ShiftEnterCustom"
  }
]
```

Save the file and restart Windows Terminal or open a new tab.

---

### Packages Web Src Content Docs Lsp (`packages/web/src/content/docs/lsp.mdx`)

---
title: LSP Servers
description: OpenCode integrates with your LSP servers.
---

OpenCode can integrate with Language Server Protocol (LSP) servers to use diagnostics as feedback for the agent.

---

## Built-in

OpenCode comes with several built-in LSP servers for popular languages:

| LSP Server         | Extensions                                                          | Requirements                                                 |
| ------------------ | ------------------------------------------------------------------- | ------------------------------------------------------------ |
| astro              | .astro                                                              | Auto-installs for Astro projects                             |
| bash               | .sh, .bash, .zsh, .ksh                                              | Auto-installs bash-language-server                           |
| clangd             | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++                | Auto-installs for C/C++ projects                             |
| csharp             | .cs, .csx                                                           | `.NET SDK` installed                                         |
| clojure-lsp        | .clj, .cljs, .cljc, .edn                                            | `clojure-lsp` command available                              |
| dart               | .dart                                                               | `dart` command available                                     |
| deno               | .ts, .tsx, .js, .jsx, .mjs                                          | `deno` command available (auto-detects deno.json/deno.jsonc) |
| elixir-ls          | .ex, .exs                                                           | `elixir` command available                                   |
| eslint             | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue                  | `eslint` dependency in project                               |
| fsharp             | .fs, .fsi, .fsx, .fsscript                                          | `.NET SDK` installed                                         |
| gleam              | .gleam                                                              | `gleam` command available                                    |
| gopls              | .go                                                                 | `go` command available                                       |
| hls                | .hs, .lhs                                                           | `haskell-language-server-wrapper` command available          |
| jdtls              | .java                                                               | `Java SDK (version 21+)` installed                           |
| julials            | .jl                                                                 | `julia` and `LanguageServer.jl` installed                    |
| kotlin-ls          | .kt, .kts                                                           | Auto-installs for Kotlin projects                            |
| lua-ls             | .lua                                                                | Auto-installs for Lua projects                               |
| nixd               | .nix                                                                | `nixd` command available                                     |
| ocaml-lsp          | .ml, .mli                                                           | `ocamllsp` command available                                 |
| oxlint             | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | `oxlint` dependency in project                               |
| php intelephense   | .php                                                                | Auto-installs for PHP projects                               |
| prisma             | .prisma                                                             | `prisma` command available                                   |
| pyright            | .py, .pyi                                                           | `pyright` dependency installed                               |
| razor              | .razor, .cshtml                                                     | `.NET SDK` and VS Code C# extension installed                |
| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru                                           | `ruby` and `gem` commands available                          |
| rust               | .rs                                                                 | `rust-analyzer` command available                            |
| sourcekit-lsp      | .swift, .objc, .objcpp                                              | `swift` installed (`xcode` on macOS)                         |
| svelte             | .svelte                                                             | Auto-installs for Svelte projects                            |
| terraform          | .tf, .tfvars                                                        | Auto-installs from GitHub releases                           |
| tinymist           | .typ, .typc                                                         | Auto-installs from GitHub releases                           |
| typescript         | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts                        | `typescript` dependency in project                           |
| vue                | .vue                                                                | Auto-installs for Vue projects                               |
| yaml-ls            | .yaml, .yml                                                         | Auto-installs Red Hat yaml-language-server                   |
| zls                | .zig, .zon                                                          | `zig` command available                                      |

LSP is disabled by default. When enabled, servers start when one of the above file extensions is detected and the requirements are met.

:::note
You can disable automatic LSP server downloads by setting the `OPENCODE_DISABLE_LSP_DOWNLOAD` environment variable to `true`.
:::

---

## How It Works

When LSP is enabled and opencode opens a file, it:

1. Checks the file extension against all enabled LSP servers.
2. Starts the appropriate LSP server if not already running.

---

## Best Practices

LSP can help the agent find and fix issues by providing diagnostics from language servers. This is useful in some projects, but it is not always a net positive.

Language servers can get out of sync, use significant memory, vary by version or project, and slow down agent workflows. In many projects it is better to have the agent run lint, typecheck, or other diagnostic CLI tools directly, so errors are fed back into the agent loop without those tradeoffs. Document those commands in instruction files such as `AGENTS.md` or skills so the agent knows what to run. Enable LSP when your project benefits from additional language-server feedback.

---

## Configure

You can enable and customize LSP servers through the `lsp` section in your opencode config.

To enable all built-in LSP servers, set `lsp` to `true`.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "lsp": true
}
```

Use an object to keep built-ins enabled while configuring overrides or custom servers.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "lsp": {}
}
```

Each configured LSP server entry supports the following:

Server entries need `command` unless they only disable a server.

| Property         | Type     | Description                                       |
| ---------------- | -------- | ------------------------------------------------- |
| `disabled`       | boolean  | Set this to `true` to disable the LSP server      |
| `command`        | string[] | The command to start the LSP server               |
| `extensions`     | string[] | File extensions this LSP server should handle     |
| `env`            | object   | Environment variables to set when starting server |
| `initialization` | object   | Initialization options to send to the LSP server  |

Let's look at some examples.

---

### Environment variables

Use the `env` property to set environment variables when starting the LSP server:

```json title="opencode.json" {5-8}
{
  "$schema": "https://opencode.ai/config.json",
  "lsp": {
    "rust": {
      "command": ["rust-analyzer"],
      "env": {
        "RUST_LOG": "debug"
      }
    }
  }
}
```

---

### Initialization options

Use the `initialization` property to pass initialization options to the LSP server. These are server-specific settings sent during the LSP `initialize` request:

```json title="opencode.json" {5-13}
{
  "$schema": "https://opencode.ai/config.json",
  "lsp": {
    "custom-lsp": {
      "command": ["custom-lsp-server", "--stdio"],
      "extensions": [".custom"],
      "initialization": {
        "preferences": {
          "importModuleSpecifierPreference": "relative"
        }
      }
    }
  }
}
```

:::note
Initialization options vary by LSP server. Check your LSP server's documentation for available options.
:::

---

### Disabling LSP servers

If `lsp` is omitted, all LSP servers are disabled. To disable all LSP servers after another config enabled them, set `lsp` to `false`:

```json title="opencode.json" {3}
{
  "$schema": "https://opencode.ai/config.json",
  "lsp": false
}
```

To disable a **specific** LSP server, set `disabled` to `true`:

```json title="opencode.json" {5}
{
  "$schema": "https://opencode.ai/config.json",
  "lsp": {
    "typescript": {
      "disabled": true
    }
  }
}
```

---

### Custom LSP servers

You can add custom LSP servers by specifying the command and file extensions:

```json title="opencode.json" {4-7}
{
  "$schema": "https://opencode.ai/config.json",
  "lsp": {
    "custom-lsp": {
      "command": ["custom-lsp-server", "--stdio"],
      "extensions": [".custom"]
    }
  }
}
```

---

## Additional Information

### PHP Intelephense

PHP Intelephense offers premium features through a license key. You can provide a license key by placing (only) the key in a text file at:

- On macOS/Linux: `$HOME/intelephense/license.txt`
- On Windows: `%USERPROFILE%/intelephense/license.txt`

The file should contain only the license key with no additional content.

---

### Packages Web Src Content Docs Mcp Servers (`packages/web/src/content/docs/mcp-servers.mdx`)

---
title: MCP servers
description: Add local and remote MCP tools.
---

You can add external tools to OpenCode using the _Model Context Protocol_, or MCP. OpenCode supports both local and remote servers.

Once added, MCP tools are automatically available to the LLM alongside built-in tools.

---

#### Caveats

When you use an MCP server, it adds to the context. This can quickly add up if you have a lot of tools. So we recommend being careful with which MCP servers you use.

:::tip
MCP servers add to your context, so you want to be careful with which ones you enable.
:::

Certain MCP servers, like the GitHub MCP server, tend to add a lot of tokens and can easily exceed the context limit.

---

## Enable

You can define MCP servers in your [OpenCode Config](https://opencode.ai/docs/config/) under `mcp`. Add each MCP with a unique name. You can refer to that MCP by name when prompting the LLM.

```jsonc title="opencode.jsonc" {6}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "name-of-mcp-server": {
      // ...
      "enabled": true,
    },
    "name-of-other-mcp-server": {
      // ...
    },
  },
}
```

You can also disable a server by setting `enabled` to `false`. This is useful if you want to temporarily disable a server without removing it from your config.

---

### Overriding remote defaults

Organizations can provide default MCP servers via their `.well-known/opencode` endpoint. These servers may be disabled by default, allowing users to opt-in to the ones they need.

To enable a specific server from your organization's remote config, add it to your local config with `enabled: true`:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "jira": {
      "type": "remote",
      "url": "https://jira.example.com/mcp",
      "enabled": true
    }
  }
}
```

Your local config values override the remote defaults. See [config precedence](/docs/config#precedence-order) for more details.

---

## Local

Add local MCP servers using `type` to `"local"` within the MCP object.

```jsonc title="opencode.jsonc" {15}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "my-local-mcp-server": {
      "type": "local",
      // Or ["bun", "x", "my-mcp-command"]
      "command": ["npx", "-y", "my-mcp-command"],
      "enabled": true,
      "environment": {
        "MY_ENV_VAR": "my_env_var_value",
      },
    },
  },
}
```

The command is how the local MCP server is started. You can also pass in a list of environment variables as well.

For example, here's how you can add the test [`@modelcontextprotocol/server-everything`](https://www.npmjs.com/package/@modelcontextprotocol/server-everything) MCP server.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "mcp_everything": {
      "type": "local",
      "command": ["npx", "-y", "@modelcontextprotocol/server-everything"],
    },
  },
}
```

And to use it I can add `use the mcp_everything tool` to my prompts.

```txt "mcp_everything"
use the mcp_everything tool to add the number 3 and 4
```

---

#### Options

Here are all the options for configuring a local MCP server.

| Option        | Type    | Required | Description                                                                              |
| ------------- | ------- | -------- | ---------------------------------------------------------------------------------------- |
| `type`        | String  | Y        | Type of MCP server connection, must be `"local"`.                                        |
| `command`     | Array   | Y        | Command and arguments to run the MCP server.                                             |
| `cwd`         | String  |          | Working directory for the MCP server process. Relative paths resolve from the workspace. |
| `environment` | Object  |          | Environment variables to set when running the server.                                    |
| `enabled`     | Boolean |          | Enable or disable the MCP server on startup.                                             |
| `timeout`     | Number  |          | Timeout in ms for fetching tools from the MCP server. Defaults to 5000 (5 seconds).      |

---

## Remote

Add remote MCP servers by setting `type` to `"remote"`.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "my-remote-mcp": {
      "type": "remote",
      "url": "https://my-mcp-server.com",
      "enabled": true,
      "headers": {
        "Authorization": "Bearer MY_API_KEY"
      }
    }
  }
}
```

The `url` is the URL of the remote MCP server and with the `headers` option you can pass in a list of headers.

---

#### Options

| Option    | Type    | Required | Description                                                                         |
| --------- | ------- | -------- | ----------------------------------------------------------------------------------- |
| `type`    | String  | Y        | Type of MCP server connection, must be `"remote"`.                                  |
| `url`     | String  | Y        | URL of the remote MCP server.                                                       |
| `enabled` | Boolean |          | Enable or disable the MCP server on startup.                                        |
| `headers` | Object  |          | Headers to send with the request.                                                   |
| `oauth`   | Object  |          | OAuth authentication configuration. See [OAuth](#oauth) section below.              |
| `timeout` | Number  |          | Timeout in ms for fetching tools from the MCP server. Defaults to 5000 (5 seconds). |

---

## OAuth

OpenCode automatically handles OAuth authentication for remote MCP servers. When a server requires authentication, OpenCode will:

1. Detect the 401 response and initiate the OAuth flow
2. Use **Dynamic Client Registration (RFC 7591)** if supported by the server
3. Store tokens securely for future requests

---

### Automatic

For most OAuth-enabled MCP servers, no special configuration is needed. Just configure the remote server:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "my-oauth-server": {
      "type": "remote",
      "url": "https://mcp.example.com/mcp"
    }
  }
}
```

If the server requires authentication, OpenCode will prompt you to authenticate when you first try to use it. If not, you can [manually trigger the flow](#authenticating) with `opencode mcp auth <server-name>`.

---

### Pre-registered

If you have client credentials from the MCP server provider, you can configure them:

```json title="opencode.json" {7-11}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "my-oauth-server": {
      "type": "remote",
      "url": "https://mcp.example.com/mcp",
      "oauth": {
        "clientId": "{env:MY_MCP_CLIENT_ID}",
        "clientSecret": "{env:MY_MCP_CLIENT_SECRET}",
        "scope": "tools:read tools:execute"
      }
    }
  }
}
```

---

### Authenticating

You can manually trigger authentication or manage credentials.

Authenticate with a specific MCP server:

```bash
opencode mcp auth my-oauth-server
```

List all MCP servers and their auth status:

```bash
opencode mcp list
```

Remove stored credentials:

```bash
opencode mcp logout my-oauth-server
```

The `mcp auth` command will open your browser for authorization. After you authorize, OpenCode will store the tokens securely in `~/.local/share/opencode/mcp-auth.json`.

---

#### Disabling OAuth

If you want to disable automatic OAuth for a server (e.g., for servers that use API keys instead), set `oauth` to `false`:

```json title="opencode.json" {7}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "my-api-key-server": {
      "type": "remote",
      "url": "https://mcp.example.com/mcp",
      "oauth": false,
      "headers": {
        "Authorization": "Bearer {env:MY_API_KEY}"
      }
    }
  }
}
```

---

#### OAuth Options

| Option         | Type            | Description                                                                      |
| -------------- | --------------- | -------------------------------------------------------------------------------- |
| `oauth`        | Object \| false | OAuth config object, or `false` to disable OAuth auto-detection.                 |
| `clientId`     | String          | OAuth client ID. If not provided, dynamic client registration will be attempted. |
| `clientSecret` | String          | OAuth client secret, if required by the authorization server.                    |
| `scope`        | String          | OAuth scopes to request during authorization.                                    |

#### Debugging

If a remote MCP server is failing to authenticate, you can diagnose issues with:

```bash
# View auth status for all OAuth-capable servers
opencode mcp auth list

# Debug connection and OAuth flow for a specific server
opencode mcp debug my-oauth-server
```

The `mcp debug` command shows the current auth status, tests HTTP connectivity, and attempts the OAuth discovery flow.

---

## Manage

Tools from your MCP servers are available in OpenCode alongside built-in tools. You can manage them through the OpenCode config like any other tool.

---

### Global

This means that you can enable or disable them globally.

```json title="opencode.json" {14}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "my-mcp-foo": {
      "type": "local",
      "command": ["bun", "x", "my-mcp-command-foo"]
    },
    "my-mcp-bar": {
      "type": "local",
      "command": ["bun", "x", "my-mcp-command-bar"]
    }
  },
  "tools": {
    "my-mcp-foo": false
  }
}
```

We can also use a glob pattern to disable all matching MCP tools.

```json title="opencode.json" {14}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "my-mcp-foo": {
      "type": "local",
      "command": ["bun", "x", "my-mcp-command-foo"]
    },
    "my-mcp-bar": {
      "type": "local",
      "command": ["bun", "x", "my-mcp-command-bar"]
    }
  },
  "tools": {
    "my-mcp*": false
  }
}
```

Here we are using the glob pattern `my-mcp*` to disable all matching MCP tools.

---

### Per agent

If you have a large number of MCP servers you may want to only enable them per agent and disable them globally. To do this:

1. Disable it as a tool globally.
2. In your [agent config](/docs/agents#tools), enable the MCP server as a tool.

```json title="opencode.json" {11, 14-18}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "my-mcp": {
      "type": "local",
      "command": ["bun", "x", "my-mcp-command"],
      "enabled": true
    }
  },
  "tools": {
    "my-mcp*": false
  },
  "agent": {
    "my-agent": {
      "tools": {
        "my-mcp*": true
      }
    }
  }
}
```

---

#### Glob patterns

The glob pattern uses simple regex globbing patterns:

- `*` matches zero or more of any character (e.g., `"my-mcp*"` matches `my-mcp_search`, `my-mcp_list`, etc.)
- `?` matches exactly one character
- All other characters match literally

:::note
MCP server tools are registered with server name as prefix, so to disable all tools for a server simply use:

```
"mymcpservername_*": false
```

:::

---

## Examples

Below are examples of some common MCP servers. You can submit a PR if you want to document other servers.

---

### Sentry

Add the [Sentry MCP server](https://mcp.sentry.dev) to interact with your Sentry projects and issues.

```json title="opencode.json" {4-8}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "sentry": {
      "type": "remote",
      "url": "https://mcp.sentry.dev/mcp",
      "oauth": {}
    }
  }
}
```

After adding the configuration, authenticate with Sentry:

```bash
opencode mcp auth sentry
```

This will open a browser window to complete the OAuth flow and connect OpenCode to your Sentry account.

Once authenticated, you can use Sentry tools in your prompts to query issues, projects, and error data.

```txt "use sentry"
Show me the latest unresolved issues in my project. use sentry
```

---

### Context7

Add the [Context7 MCP server](https://github.com/upstash/context7) to search through docs.

```json title="opencode.json" {4-7}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "context7": {
      "type": "remote",
      "url": "https://mcp.context7.com/mcp"
    }
  }
}
```

If you have signed up for a free account, you can use your API key and get higher rate-limits.

```json title="opencode.json" {7-9}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "context7": {
      "type": "remote",
      "url": "https://mcp.context7.com/mcp",
      "headers": {
        "CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}"
      }
    }
  }
}
```

Here we are assuming that you have the `CONTEXT7_API_KEY` environment variable set.

Add `use context7` to your prompts to use Context7 MCP server.

```txt "use context7"
Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7
```

Alternatively, you can add something like this to your [AGENTS.md](/docs/rules/).

```md title="AGENTS.md"
When you need to search docs, use `context7` tools.
```

---

### Grep by Vercel

Add the [Grep by Vercel](https://grep.app) MCP server to search through code snippets on GitHub.

```json title="opencode.json" {4-7}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "gh_grep": {
      "type": "remote",
      "url": "https://mcp.grep.app"
    }
  }
}
```

Since we named our MCP server `gh_grep`, you can add `use the gh_grep tool` to your prompts to get the agent to use it.

```txt "use the gh_grep tool"
What's the right way to set a custom domain in an SST Astro component? use the gh_grep tool
```

Alternatively, you can add something like this to your [AGENTS.md](/docs/rules/).

```md title="AGENTS.md"
If you are unsure how to do something, use `gh_grep` to search code examples from GitHub.
```

---

### Packages Web Src Content Docs Models (`packages/web/src/content/docs/models.mdx`)

---
title: Models
description: Configuring an LLM provider and model.
---

OpenCode uses the [AI SDK](https://ai-sdk.dev/) and [Models.dev](https://models.dev) to support **75+ LLM providers** and it supports running local models.

---

## Providers

Most popular providers are preloaded by default. If you've added the credentials for a provider through the `/connect` command, they'll be available when you start OpenCode.

Learn more about [providers](/docs/providers).

---

## Select a model

Once you've configured your provider you can select the model you want by typing in:

```bash frame="none"
/models
```

---

## Recommended models

There are a lot of models out there, with new models coming out every week.

:::tip
Consider using one of the models we recommend.
:::

However, there are only a few of them that are good at both generating code and tool calling.

Here are several models that work well with OpenCode, in no particular order. (This is not an exhaustive list nor is it necessarily up to date):

- GPT 5.2
- GPT 5.1 Codex
- Claude Opus 4.5
- Claude Sonnet 4.5
- Minimax M2.1
- Gemini 3 Pro

---

## Set a default

To set one of these as the default model, you can set the `model` key in your
OpenCode config.

```json title="opencode.json" {3}
{
  "$schema": "https://opencode.ai/config.json",
  "model": "lmstudio/google/gemma-3n-e4b"
}
```

Here the full ID is `provider_id/model_id`. For example, if you're using [OpenCode Zen](https://opencode.ai/v2/docs/console/), you would use `opencode/gpt-5.1-codex` for GPT 5.1 Codex.

If you've configured a [custom provider](/docs/providers#custom), the `provider_id` is key from the `provider` part of your config, and the `model_id` is the key from `provider.models`.

---

## Configure models

You can globally configure a model's options through the config.

```jsonc title="opencode.jsonc" {7-12,19-24}
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "openai": {
      "models": {
        "gpt-5": {
          "options": {
            "reasoningEffort": "high",
            "textVerbosity": "low",
            "reasoningSummary": "auto",
            "include": ["reasoning.encrypted_content"],
          },
        },
      },
    },
    "anthropic": {
      "models": {
        "claude-sonnet-4-5-20250929": {
          "options": {
            "thinking": {
              "type": "enabled",
              "budgetTokens": 16000,
            },
          },
        },
      },
    },
  },
}
```

Here we're configuring global settings for two built-in models: `gpt-5` when accessed via the `openai` provider, and `claude-sonnet-4-20250514` when accessed via the `anthropic` provider.
The built-in provider and model names can be found on [Models.dev](https://models.dev).

You can also configure these options for any agents that you are using. The agent config overrides any global options here. [Learn more](/docs/agents/#additional).

You can also define custom variants that extend built-in ones. Variants let you configure different settings for the same model without creating duplicate entries:

```jsonc title="opencode.jsonc" {6-21}
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "opencode": {
      "models": {
        "gpt-5": {
          "variants": {
            "high": {
              "reasoningEffort": "high",
              "textVerbosity": "low",
              "reasoningSummary": "auto",
            },
            "low": {
              "reasoningEffort": "low",
              "textVerbosity": "low",
              "reasoningSummary": "auto",
            },
          },
        },
      },
    },
  },
}
```

---

## Variants

Many models support multiple variants with different configurations. OpenCode ships with built-in default variants for popular providers.

### Built-in variants

OpenCode ships with default variants for many providers:

**Anthropic**:

- `high` - High thinking budget (default)
- `max` - Maximum thinking budget

**OpenAI**:

Varies by model but roughly:

- `none` - No reasoning
- `minimal` - Minimal reasoning effort
- `low` - Low reasoning effort
- `medium` - Medium reasoning effort
- `high` - High reasoning effort
- `xhigh` - Extra high reasoning effort

**Google**:

- `low` - Lower effort/token budget
- `high` - Higher effort/token budget

:::tip
This list is not comprehensive. Many other providers have built-in defaults too.
:::

### Custom variants

You can override existing variants or add your own:

```jsonc title="opencode.jsonc" {7-18}
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "openai": {
      "models": {
        "gpt-5": {
          "variants": {
            "thinking": {
              "reasoningEffort": "high",
              "textVerbosity": "low",
            },
            "fast": {
              "disabled": true,
            },
          },
        },
      },
    },
  },
}
```

### Cycle variants

Use the keybind `variant_cycle` to quickly switch between variants. [Learn more](/docs/keybinds).

---

## Loading models

When OpenCode starts up, it checks for models in the following priority order:

1. The `--model` or `-m` command line flag. The format is the same as in the config file: `provider_id/model_id`.

2. The model list in the OpenCode config.

   ```json title="opencode.json"
   {
     "$schema": "https://opencode.ai/config.json",
     "model": "anthropic/claude-sonnet-4-20250514"
   }
   ```

   The format here is `provider/model`.

3. The last used model.

4. The first model using an internal priority.

---

### Packages Web Src Content Docs Network (`packages/web/src/content/docs/network.mdx`)

---
title: Network
description: Configure proxies and custom certificates.
---

OpenCode supports standard proxy environment variables and custom certificates for enterprise network environments.

---

## Proxy

OpenCode respects standard proxy environment variables.

```bash
# HTTPS proxy (recommended)
export HTTPS_PROXY=https://proxy.example.com:8080

# HTTP proxy (if HTTPS not available)
export HTTP_PROXY=http://proxy.example.com:8080

# Bypass proxy for local server (required)
export NO_PROXY=localhost,127.0.0.1
```

:::caution
The TUI communicates with a local HTTP server. You must bypass the proxy for this connection to prevent routing loops.
:::

You can configure the server's port and hostname using [CLI flags](/docs/cli#run).

---

### Authenticate

If your proxy requires basic authentication, include credentials in the URL.

```bash
export HTTPS_PROXY=http://username:password@proxy.example.com:8080
```

:::caution
Avoid hardcoding passwords. Use environment variables or secure credential storage.
:::

For proxies requiring advanced authentication like NTLM or Kerberos, consider using an LLM Gateway that supports your authentication method.

---

## Custom certificates

If your enterprise uses custom CAs for HTTPS connections, configure OpenCode to trust them.

```bash
export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem
```

This works for both proxy connections and direct API access.

---

### Packages Web Src Content Docs Permissions (`packages/web/src/content/docs/permissions.mdx`)

---
title: Permissions
description: Control which actions require approval to run.
---

OpenCode uses the `permission` config to decide whether a given action should run automatically, prompt you, or be blocked.

As of `v1.1.1`, the legacy `tools` boolean config is deprecated and has been merged into `permission`. The old `tools` config is still supported for backwards compatibility.

---

## Actions

Each permission rule resolves to one of:

- `"allow"` — run without approval
- `"ask"` — prompt for approval
- `"deny"` — block the action

---

## Auto mode

Start OpenCode with `--auto` to automatically approve permission requests that are not explicitly denied.

```bash
opencode --auto
```

You can also use auto mode with [`opencode run`](/docs/cli#run).

```bash
opencode run --auto "Refactor this module"
```

Explicit `"deny"` rules are still enforced. Auto mode only changes requests that would otherwise ask for approval.

In the TUI, open the command palette and select **Enable auto-approve permissions** or **Disable auto-approve permissions** to change modes. When auto mode is active, the prompt displays a muted `auto` indicator next to the current agent.

---

## Configuration

You can set permissions globally (with `*`), and override specific tools.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "*": "ask",
    "shell": "allow",
    "edit": "deny"
  }
}
```

You can also set all permissions at once:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "permission": "allow"
}
```

---

## Granular Rules (Object Syntax)

For most permissions, you can use an object to apply different actions based on the tool input.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "shell": {
      "*": "ask",
      "git *": "allow",
      "npm *": "allow",
      "rm *": "deny",
      "grep *": "allow"
    },
    "edit": {
      "*": "deny",
      "packages/web/src/content/docs/*.mdx": "allow"
    },
    "webfetch": {
      "*": "ask",
      "https://en.wikipedia.org/*": "allow"
    }
  }
}
```

Rules are evaluated by pattern match, with the **last matching rule winning**. A common pattern is to put the catch-all `"*"` rule first, and more specific rules after it.

### Wildcards

Permission patterns use simple wildcard matching:

- `*` matches zero or more of any character
- `?` matches exactly one character
- All other characters match literally

### Home Directory Expansion

You can use `~` or `$HOME` at the start of a pattern to reference your home directory. This is particularly useful for [`external_directory`](#external-directories) rules.

- `~/projects/*` -> `/Users/username/projects/*`
- `$HOME/projects/*` -> `/Users/username/projects/*`
- `~` -> `/Users/username`

### External Directories

Use `external_directory` to allow tool calls that touch paths outside the working directory where OpenCode was started. This applies to any tool that takes a path as input (for example `read`, `edit`, `glob`, `grep`, and many `shell` commands).

Home expansion (like `~/...`) only affects how a pattern is written. It does not make an external path part of the current workspace, so paths outside the working directory must still be allowed via `external_directory`.

For example, this allows access to everything under `~/projects/personal/`:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "external_directory": {
      "~/projects/personal/**": "allow"
    }
  }
}
```

Any directory allowed here inherits the same defaults as the current workspace. Since [`read` defaults to `allow`](#defaults), reads are also allowed for entries under `external_directory` unless overridden. Add explicit rules when a tool should be restricted in these paths, such as blocking edits while keeping reads:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "external_directory": {
      "~/projects/personal/**": "allow"
    },
    "edit": {
      "~/projects/personal/**": "deny"
    }
  }
}
```

Keep the list focused on trusted paths, and layer extra allow or deny rules as needed for other tools (for example `shell`).

---

## Available Permissions

OpenCode permissions are keyed by tool name, plus a couple of safety guards:

- `read` — reading a file (matches the file path)
- `edit` — all file modifications (covers `edit`, `write`, `patch`)
- `glob` — file globbing (matches the glob pattern)
- `grep` — content search (matches the regex pattern)
- `shell` — running shell commands (matches parsed commands like `git status --porcelain`)
- `task` — launching subagents (matches the subagent type)
- `skill` — loading a skill (matches the skill name)
- `lsp` — running LSP queries (currently non-granular)
- `question` — asking the user questions during execution
- `webfetch` — fetching a URL (matches the URL)
- `websearch` — web search
- `external_directory` — triggered when a tool touches paths outside the project working directory
- `doom_loop` — triggered when the same tool call repeats 3 times with identical input

---

## Defaults

If you don’t specify anything, OpenCode starts from permissive defaults:

- Most permissions default to `"allow"`.
- `doom_loop` and `external_directory` default to `"ask"`.
- `read` is `"allow"`, but `.env` files are denied by default:

```json title="opencode.json"
{
  "permission": {
    "read": {
      "*": "allow",
      "*.env": "deny",
      "*.env.*": "deny",
      "*.env.example": "allow"
    }
  }
}
```

---

## What “Ask” Does

When OpenCode prompts for approval, the UI offers three outcomes:

- `once` — approve just this request
- `always` — approve future requests matching the suggested patterns (for the rest of the current OpenCode session)
- `reject` — deny the request

The set of patterns that `always` would approve is provided by the tool (for example, shell approvals typically whitelist a safe command prefix like `git status*`).

---

## Agents

You can override permissions per agent. Agent permissions are merged with the global config, and agent rules take precedence. [Learn more](/docs/agents#permissions) about agent permissions.

:::note
Refer to the [Granular Rules (Object Syntax)](#granular-rules-object-syntax) section above for more detailed pattern matching examples.
:::

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "shell": {
      "*": "ask",
      "git *": "allow",
      "git commit *": "deny",
      "git push *": "deny",
      "grep *": "allow"
    }
  },
  "agent": {
    "build": {
      "permission": {
        "shell": {
          "*": "ask",
          "git *": "allow",
          "git commit *": "ask",
          "git push *": "deny",
          "grep *": "allow"
        }
      }
    }
  }
}
```

You can also configure agent permissions in Markdown:

```markdown title="~/.config/opencode/agents/review.md"
---
description: Code review without edits
mode: subagent
permission:
  edit: deny
  shell: ask
  webfetch: deny
---

Only analyze code and suggest changes.
```

:::tip
Use pattern matching for commands with arguments. `"grep *"` allows `grep pattern file.txt`, while `"grep"` alone would block it. Commands like `git status` work for default behavior but require explicit permission (like `"git status *"`) when arguments are passed.
:::

---

### Packages Web Src Content Docs Plugins (`packages/web/src/content/docs/plugins.mdx`)

---
title: Plugins
description: Write your own plugins to extend OpenCode.
---

Plugins allow you to extend OpenCode by hooking into various events and customizing behavior. You can create plugins to add new features, integrate with external services, or modify OpenCode's default behavior.

For examples, check out the [plugins](/docs/ecosystem#plugins) created by the community.

---

## Use a plugin

There are two ways to load plugins.

---

### From local files

Place JavaScript or TypeScript files in the plugin directory.

- `.opencode/plugins/` - Project-level plugins
- `~/.config/opencode/plugins/` - Global plugins

Files in these directories are automatically loaded at startup.

---

### From npm

Specify npm packages in your config file.

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

Both regular and scoped npm packages are supported.

Browse available plugins in the [ecosystem](/docs/ecosystem#plugins).

---

### How plugins are installed

**npm plugins** are installed automatically using Bun at startup. Packages and their dependencies are cached in `~/.cache/opencode/node_modules/`.

**Local plugins** are loaded directly from the plugin directory. To use external packages, you must create a `package.json` within your config directory (see [Dependencies](#dependencies)), or publish the plugin to npm and [add it to your config](/docs/config#plugins).

---

### Load order

Plugins are loaded from all sources and all hooks run in sequence. The load order is:

1. Global config (`~/.config/opencode/opencode.json`)
2. Project config (`opencode.json`)
3. Global plugin directory (`~/.config/opencode/plugins/`)
4. Project plugin directory (`.opencode/plugins/`)

Duplicate npm packages with the same name and version are loaded once. However, a local plugin and an npm plugin with similar names are both loaded separately.

---

## Create a plugin

A plugin is a **JavaScript/TypeScript module** that exports one or more plugin
functions. Each function receives a context object and returns a hooks object.

---

### Dependencies

Local plugins and custom tools can use external npm packages. Add a `package.json` to your config directory with the dependencies you need.

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

OpenCode runs `bun install` at startup to install these. Your plugins and tools can then import them.

```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 === "shell") {
        output.args.command = escape(output.args.command)
      }
    },
  }
}
```

---

### Basic structure

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

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

The plugin function receives:

- `project`: The current project information.
- `directory`: The current working directory.
- `worktree`: The git worktree path.
- `client`: An opencode SDK client for interacting with the AI.
- `$`: Bun's [shell API](https://bun.com/docs/runtime/shell) for executing commands.

---

### TypeScript support

For TypeScript plugins, you can import types from the plugin package:

```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
  }
}
```

---

### Events

Plugins can subscribe to events as seen below in the Examples section. Here is a list of the different events available.

#### Command Events

- `command.executed`

#### File Events

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

#### Installation Events

- `installation.updated`

#### LSP Events

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

#### Message Events

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

#### Permission Events

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

#### Server Events

- `server.connected`

#### Session Events

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

#### Shell Events

- `shell.env`

#### Tool Events

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

#### TUI Events

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

---

## Examples

Here are some examples of plugins you can use to extend opencode.

---

### Send notifications

Send notifications when certain events occur:

```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"'`
      }
    },
  }
}
```

We are using `osascript` to run AppleScript on macOS. Here we are using it to send notifications.

:::note
If you’re using the OpenCode desktop app, it can send system notifications automatically when a response is ready or when a session errors.
:::

---

### .env protection

Prevent opencode from reading `.env` files:

```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 environment variables

Inject environment variables into all shell execution (AI tools and user terminals):

```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
    },
  }
}
```

---

### Custom tools

Plugins can also add custom tools to 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})`
        },
      }),
    },
  }
}
```

The `tool` helper creates a custom tool that opencode can call. It takes a Zod schema function and returns a tool definition with:

- `description`: What the tool does
- `args`: Zod schema for the tool's arguments
- `execute`: Function that runs when the tool is called

Your custom tools will be available to opencode alongside built-in tools.

:::note
If a plugin tool uses the same name as a built-in tool, the plugin tool takes precedence.
:::

---

### Logging

Use `client.app.log()` instead of `console.log` for structured logging:

```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" },
    },
  })
}
```

Levels: `debug`, `info`, `warn`, `error`. See [SDK documentation](https://opencode.ai/docs/sdk) for details.

---

### Compaction hooks

Customize the context included when a session is compacted:

```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
`)
    },
  }
}
```

The `experimental.session.compacting` hook fires before the LLM generates a continuation summary. Use it to inject domain-specific context that the default compaction prompt would miss.

You can also replace the compaction prompt entirely by setting `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.
`
    },
  }
}
```

When `output.prompt` is set, it completely replaces the default compaction prompt. The `output.context` array is ignored in this case.

---

### Packages Web Src Content Docs Policies (`packages/web/src/content/docs/policies.mdx`)

---
title: Policies
description: Control which configured resources OpenCode may use.
---

Policies control whether OpenCode may perform an action on a named resource. This feature is experimental and is configured with the `experimental.policies` array in `opencode.json`.

Policies are separate from [permissions](/docs/permissions). Permissions control what tools can do during a session, while policies control whether OpenCode may use a resource such as an LLM provider.

---

## Configuration

Each policy statement has three fields:

- `effect` - Either `"allow"` or `"deny"`.
- `action` - The operation being controlled.
- `resource` - The resource ID or wildcard pattern the statement applies to.

For example, deny use of the `openai` provider:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "experimental": {
    "policies": [
      {
        "effect": "deny",
        "action": "provider.use",
        "resource": "openai"
      }
    ]
  }
}
```

A provider denied by policy is not available for model selection or model use, even if it has credentials or is otherwise configured correctly.

---

## Available Policies

OpenCode currently supports one policy action:

| Action         | Resource                      | Description                           |
| -------------- | ----------------------------- | ------------------------------------- |
| `provider.use` | Provider ID, such as `openai` | Allow or deny use of an LLM provider. |

More policy actions may be added in the future.

---

## Matching

The `resource` field supports wildcard matching. Use `*` to match zero or more characters and `?` to match one character.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "experimental": {
    "policies": [
      {
        "effect": "deny",
        "action": "provider.use",
        "resource": "company-*"
      }
    ]
  }
}
```

This denies providers such as `company-us` and `company-eu`.

---

## Rule Order

When multiple statements match, the last matching statement wins. Put broad rules first, then more specific exceptions after them.

For example, allow only Anthropic:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "experimental": {
    "policies": [
      {
        "effect": "deny",
        "action": "provider.use",
        "resource": "*"
      },
      {
        "effect": "allow",
        "action": "provider.use",
        "resource": "anthropic"
      }
    ]
  }
}
```

If no policy matches a provider, provider use is allowed by default.

Policies may be set in both your global config and project config. If policies from both locations match the same provider, your global policy takes priority over the project policy. This prevents a repository from re-enabling a provider that you deny globally.

---

## Provider Lists

Use policies instead of the older `disabled_providers` and `enabled_providers` settings when controlling provider access.

To replace `disabled_providers`:

```json title="opencode.json"
{
  "experimental": {
    "policies": [
      { "effect": "deny", "action": "provider.use", "resource": "openai" },
      { "effect": "deny", "action": "provider.use", "resource": "google" }
    ]
  }
}
```

To replace `enabled_providers`, deny all providers first and allow the selected providers after it:

```json title="opencode.json"
{
  "experimental": {
    "policies": [
      { "effect": "deny", "action": "provider.use", "resource": "*" },
      { "effect": "allow", "action": "provider.use", "resource": "anthropic" },
      { "effect": "allow", "action": "provider.use", "resource": "openai" }
    ]
  }
}
```

---

### Packages Web Src Content Docs Providers (`packages/web/src/content/docs/providers.mdx`)

---
title: Providers
description: Using any LLM provider in OpenCode.
---

import config from "../../../config.mjs"
export const console = config.console

OpenCode uses the [AI SDK](https://ai-sdk.dev/) and [Models.dev](https://models.dev) to support **75+ LLM providers** and it supports running local models.

To add a provider you need to:

1. Add the API keys for the provider using the `/connect` command.
2. Configure the provider in your OpenCode config.

---

### Credentials

When you add a provider's API keys with the `/connect` command, they are stored
in `~/.local/share/opencode/auth.json`.

---

### Config

You can customize the providers through the `provider` section in your OpenCode
config.

---

#### Base URL

You can customize the base URL for any provider by setting the `baseURL` option. This is useful when using proxy services or custom endpoints.

```json title="opencode.json" {6}
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "anthropic": {
      "options": {
        "baseURL": "https://api.anthropic.com/v1"
      }
    }
  }
}
```

---

#### Hiding models

You can hide specific models from the `/models` picker for a provider using the `blacklist` option. This is useful when a provider exposes models you don't want to use or select.

```json title="opencode.json" {6}
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "anthropic": {
      "blacklist": ["claude-opus-4-20250514"]
    }
  }
}
```

The inverse `whitelist` option hides every model except the ones listed.

```json title="opencode.json" {6}
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "anthropic": {
      "whitelist": ["claude-sonnet-4-20250514"]
    }
  }
}
```

Both options take an array of model IDs — the same IDs shown in the `/models` picker.

- `blacklist` removes the listed models from the picker.
- `whitelist` keeps only the listed models and hides the rest.
- You can combine them: `whitelist` narrows the set, then `blacklist` removes entries from it.

---

## OpenCode Zen

OpenCode Zen is a list of models provided by the OpenCode team that have been
tested and verified to work well with OpenCode. [Learn more](https://opencode.ai/v2/docs/console/).

:::tip
If you are new, we recommend starting with OpenCode Zen.
:::

1. Run the `/connect` command in the TUI, select `OpenCode Zen`, and head to [opencode.ai/auth](https://opencode.ai/zen).

   ```txt
   /connect
   ```

2. Sign in, add your billing details, and copy your API key.

3. Paste your API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run `/models` in the TUI to see the list of models we recommend.

   ```txt
   /models
   ```

It works like any other provider in OpenCode and is completely optional to use.

---

## OpenCode Go

OpenCode Go is a low cost subscription plan that provides reliable access to popular open coding models provided by the OpenCode team that have been
tested and verified to work well with OpenCode.

1. Run the `/connect` command in the TUI, select `OpenCode Go`, and head to [opencode.ai/auth](https://opencode.ai/zen).

   ```txt
   /connect
   ```

2. Sign in, add your billing details, and copy your API key.

3. Paste your API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run `/models` in the TUI to see the list of models we recommend.

   ```txt
   /models
   ```

It works like any other provider in OpenCode and is completely optional to use.

---

## Directory

Let's look at some of the providers in detail. If you'd like to add a provider to the
list, feel free to open a PR.

:::note
Don't see a provider here? Submit a PR.
:::

---

### 302.AI

1. Head over to the [302.AI console](https://302.ai/), create an account, and generate an API key.

2. Run the `/connect` command and search for **302.AI**.

   ```txt
   /connect
   ```

3. Enter your 302.AI API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model.

   ```txt
   /models
   ```

---

### Amazon Bedrock

To use Amazon Bedrock with OpenCode:

1. Head over to the **Model catalog** in the Amazon Bedrock console and request
   access to the models you want.

   :::tip
   You need to have access to the model you want in Amazon Bedrock.
   :::

2. **Configure authentication** using one of the following methods:

   ***

   #### Environment Variables (Quick Start)

   Set one of these environment variables while running opencode:

   ```bash
   # Option 1: Using AWS access keys
   AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode

   # Option 2: Using named AWS profile
   AWS_PROFILE=my-profile opencode

   # Option 3: Using Bedrock bearer token
   AWS_BEARER_TOKEN_BEDROCK=XXX opencode
   ```

   Or add them to your bash profile:

   ```bash title="~/.bash_profile"
   export AWS_PROFILE=my-dev-profile
   export AWS_REGION=us-east-1
   ```

   ***

   #### Configuration File (Recommended)

   For project-specific or persistent configuration, use `opencode.json`:

   ```json title="opencode.json"
   {
     "$schema": "https://opencode.ai/config.json",
     "provider": {
       "amazon-bedrock": {
         "options": {
           "region": "us-east-1",
           "profile": "my-aws-profile"
         }
       }
     }
   }
   ```

   **Available options:**
   - `region` - AWS region (e.g., `us-east-1`, `eu-west-1`)
   - `profile` - AWS named profile from `~/.aws/credentials`
   - `endpoint` - Custom endpoint URL for VPC endpoints (alias for generic `baseURL` option)

   :::tip
   Configuration file options take precedence over environment variables.
   :::

   ***

   #### Advanced: VPC Endpoints

   If you're using VPC endpoints for Bedrock:

   ```json title="opencode.json"
   {
     "$schema": "https://opencode.ai/config.json",
     "provider": {
       "amazon-bedrock": {
         "options": {
           "region": "us-east-1",
           "profile": "production",
           "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com"
         }
       }
     }
   }
   ```

   :::note
   The `endpoint` option is an alias for the generic `baseURL` option, using AWS-specific terminology. If both `endpoint` and `baseURL` are specified, `endpoint` takes precedence.
   :::

   ***

   #### Authentication Methods
   - **`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`**: Create an IAM user and generate access keys in the AWS Console
   - **`AWS_PROFILE`**: Use named profiles from `~/.aws/credentials`. First configure with `aws configure --profile my-profile` or `aws sso login`
   - **`AWS_BEARER_TOKEN_BEDROCK`**: Generate long-term API keys from the Amazon Bedrock console
   - **`AWS_WEB_IDENTITY_TOKEN_FILE` / `AWS_ROLE_ARN`**: For EKS IRSA (IAM Roles for Service Accounts) or other Kubernetes environments with OIDC federation. These environment variables are automatically injected by Kubernetes when using service account annotations.

   ***

   #### Authentication Precedence

   Amazon Bedrock uses the following authentication priority:
   1. **Bearer Token** - `AWS_BEARER_TOKEN_BEDROCK` environment variable or token from `/connect` command
   2. **AWS Credential Chain** - Profile, access keys, shared credentials, IAM roles, Web Identity Tokens (EKS IRSA), instance metadata

   :::note
   When a bearer token is set (via `/connect` or `AWS_BEARER_TOKEN_BEDROCK`), it takes precedence over all AWS credential methods including configured profiles.
   :::

3. Run the `/models` command to select the model you want.

   ```txt
   /models
   ```

:::note
For custom inference profiles, use the model and provider name in the key and set the `id` property to the arn. This ensures correct caching.
:::

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "amazon-bedrock": {
      // ...
      "models": {
        "anthropic-claude-sonnet-4.5": {
          "id": "arn:aws:bedrock:us-east-1:xxx:application-inference-profile/yyy"
        }
      }
    }
  }
}
```

---

### Anthropic

1. Once you've signed up, run the `/connect` command and select Anthropic.

   ```txt
   /connect
   ```

2. Here you can select the **Claude Pro/Max** option and it'll open your browser
   and ask you to authenticate.

   ```txt
   ┌ Select auth method
   │
   │ Manually enter API Key
   └
   ```

3. Now all the Anthropic models should be available when you use the `/models` command.

   ```txt
   /models
   ```

:::info
There are plugins that allow you to use your Claude Pro/Max models with
OpenCode. Anthropic explicitly prohibits this.

Previous versions of OpenCode came bundled with these plugins but that is no
longer the case as of 1.3.0

Other companies support freedom of choice with developer tooling - you can use
the following subscriptions in OpenCode with zero setup:

- ChatGPT Plus
- Github Copilot
- Gitlab Duo
  :::

---

### Atomic Chat

You can configure opencode to use local models through [Atomic Chat](https://atomic.chat), a desktop application that runs local LLMs behind an OpenAI-compatible API server (default endpoint `http://127.0.0.1:1337/v1`).

```json title="opencode.json" "atomic-chat" {5, 6, 8, 10-14}
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "atomic-chat": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Atomic Chat (local)",
      "options": {
        "baseURL": "http://127.0.0.1:1337/v1"
      },
      "models": {
        "<your-model-id>": {
          "name": "<your-model-name>"
        }
      }
    }
  }
}
```

In this example:

- `atomic-chat` is the custom provider ID. This can be any string you want.
- `npm` specifies the package to use for this provider. Here, `@ai-sdk/openai-compatible` is used for any OpenAI-compatible API.
- `name` is the display name for the provider in the UI.
- `options.baseURL` is the endpoint for the local server. Change the host and port to match your Atomic Chat setup.
- `models` is a map of model IDs to their display names. Each ID must match the `id` returned by `GET /v1/models` — run `curl http://127.0.0.1:1337/v1/models` to list the ids currently loaded in Atomic Chat.

:::tip
If tool calls aren't working well, pick a loaded model with strong tool-calling support (for example, a Qwen-Coder or DeepSeek-Coder variant).
:::

---

### Azure OpenAI

:::note
If you encounter "I'm sorry, but I cannot assist with that request" errors, try changing the content filter from **DefaultV2** to **Default** in your Azure resource.
:::

1. Head over to the [Azure portal](https://portal.azure.com/) and create an **Azure OpenAI** resource. You'll need:
   - **Resource name**: This becomes part of your API endpoint (`https://RESOURCE_NAME.openai.azure.com/`)
   - **API key**: Either `KEY 1` or `KEY 2` from your resource

2. Go to [Azure AI Foundry](https://ai.azure.com/) and deploy a model.

   :::note
   The deployment name must match the model name for opencode to work properly.
   :::

3. Run the `/connect` command and search for **Azure**.

   ```txt
   /connect
   ```

4. Enter your API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

5. Set your resource name as an environment variable:

   ```bash
   AZURE_RESOURCE_NAME=XXX opencode
   ```

   Or add it to your bash profile:

   ```bash title="~/.bash_profile"
   export AZURE_RESOURCE_NAME=XXX
   ```

6. Run the `/models` command to select your deployed model.

   ```txt
   /models
   ```

#### Microsoft Entra ID (Azure CLI)

You can use your Azure CLI session instead of an API key. [Install the Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli), run `az login`, then run `/connect`, select **Azure**, and choose **Microsoft Entra ID (Azure CLI)**. Enter the Azure Resource name when prompted. Use `az login --tenant TENANT_ID` if the Resource belongs to a different tenant.

Find the Resource name by opening your Azure OpenAI or Foundry Resource in the [Azure portal](https://portal.azure.com/) or [Microsoft Foundry](https://ai.azure.com/). It is also the first part of the endpoint: `my-models` in `https://my-models.openai.azure.com/` or `https://my-models.services.ai.azure.com/`. If your identity can list Resources, you can also find their names and Resource groups with:

```bash
az cognitiveservices account list \
  --query "[].{name:name,resourceGroup:resourceGroup}" \
  --output table
```

OpenCode does not query Azure management APIs or discover deployments. Select a model whose catalog name matches your deployment, or configure its deployment name explicitly:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "azure": {
      "models": {
        "gpt-5-mini": {
          "id": "gpt-production"
        }
      }
    }
  }
}
```

Assign your identity the inference role required by the deployment: **Cognitive Services OpenAI User** for Azure OpenAI models or **Cognitive Services User** for other Foundry models. OpenCode refreshes access tokens through the Azure CLI, including versions earlier than 2.54.0, so you only need to sign in again when the CLI session expires.

---

### Azure Cognitive Services

1. Head over to the [Azure portal](https://portal.azure.com/) and create an **Azure OpenAI** resource. You'll need:
   - **Resource name**: This becomes part of your API endpoint (`https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/`)
   - **API key**: Either `KEY 1` or `KEY 2` from your resource

2. Go to [Azure AI Foundry](https://ai.azure.com/) and deploy a model.

   :::note
   The deployment name must match the model name for opencode to work properly.
   :::

3. Run the `/connect` command and search for **Azure Cognitive Services**.

   ```txt
   /connect
   ```

4. Enter your API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

5. Set your resource name as an environment variable:

   ```bash
   AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX opencode
   ```

   Or add it to your bash profile:

   ```bash title="~/.bash_profile"
   export AZURE_COGNITIVE_SERVICES_RESOURCE_NAME=XXX
   ```

6. Run the `/models` command to select your deployed model.

   ```txt
   /models
   ```

---

### Baseten

1. Head over to the [Baseten](https://app.baseten.co/), create an account, and generate an API key.

2. Run the `/connect` command and search for **Baseten**.

   ```txt
   /connect
   ```

3. Enter your Baseten API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model.

   ```txt
   /models
   ```

---

### Cerebras

1. Head over to the [Cerebras console](https://inference.cerebras.ai/), create an account, and generate an API key.

2. Run the `/connect` command and search for **Cerebras**.

   ```txt
   /connect
   ```

3. Enter your Cerebras API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model like _Qwen 3 Coder 480B_.

   ```txt
   /models
   ```

---

### Cloudflare AI Gateway

Cloudflare AI Gateway lets you access models from OpenAI, Anthropic, Workers AI, and more through a unified endpoint. With [Unified Billing](https://developers.cloudflare.com/ai-gateway/features/unified-billing/) you don't need separate API keys for each provider.

1. Head over to the [Cloudflare dashboard](https://dash.cloudflare.com/), navigate to **AI** > **AI Gateway**, and create a new gateway. Note your **Account ID** and **Gateway ID**.

2. Run the `/connect` command and search for **Cloudflare AI Gateway**.

   ```txt
   /connect
   ```

3. Enter your **Account ID** when prompted.

   ```txt
   ┌ Enter your Cloudflare Account ID
   │
   │
   └ enter
   ```

4. Enter your **Gateway ID** when prompted.

   ```txt
   ┌ Enter your Cloudflare AI Gateway ID
   │
   │
   └ enter
   ```

5. Enter your **Cloudflare API token**.

   ```txt
   ┌ Gateway API token
   │
   │
   └ enter
   ```

6. Run the `/models` command to select a model.

   ```txt
   /models
   ```

   You can also add models through your opencode config.

   ```json title="opencode.json"
   {
     "$schema": "https://opencode.ai/config.json",
     "provider": {
       "cloudflare-ai-gateway": {
         "models": {
           "openai/gpt-4o": {},
           "anthropic/claude-sonnet-4": {}
         }
       }
     }
   }
   ```

   Alternatively, you can set environment variables instead of using `/connect`.

   ```bash title="~/.bash_profile"
   export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id
   export CLOUDFLARE_GATEWAY_ID=your-gateway-id
   export CLOUDFLARE_API_TOKEN=your-api-token
   ```

---

### Cloudflare Workers AI

Cloudflare Workers AI lets you run AI models on Cloudflare's global network directly via REST API, with no separate provider accounts needed for supported models.

1. Head over to the [Cloudflare dashboard](https://dash.cloudflare.com/), navigate to **Workers AI**, and select **Use REST API** to get your **Account ID** and create an API token.

2. Run the `/connect` command and search for **Cloudflare Workers AI**.

   ```txt
   /connect
   ```

3. Enter your **Account ID** when prompted.

   ```txt
   ┌ Enter your Cloudflare Account ID
   │
   │
   └ enter
   ```

4. Enter your **Cloudflare API key**.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

5. Run the `/models` command to select a model.

   ```txt
   /models
   ```

   Alternatively, you can set environment variables instead of using `/connect`.

   ```bash title="~/.bash_profile"
   export CLOUDFLARE_ACCOUNT_ID=your-32-character-account-id
   export CLOUDFLARE_API_KEY=your-api-token
   ```

---

### Cortecs

1. Head over to the [Cortecs console](https://cortecs.ai/), create an account, and generate an API key.

2. Run the `/connect` command and search for **Cortecs**.

   ```txt
   /connect
   ```

3. Enter your Cortecs API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model like _Kimi K2 Instruct_.

   ```txt
   /models
   ```

---

### DeepSeek

1. Head over to the [DeepSeek console](https://platform.deepseek.com/), create an account, and click **Create new API key**.

2. Run the `/connect` command and search for **DeepSeek**.

   ```txt
   /connect
   ```

3. Enter your DeepSeek API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a DeepSeek model like _DeepSeek V4 Pro_.

   ```txt
   /models
   ```

---

### Deep Infra

1. Head over to the [Deep Infra dashboard](https://deepinfra.com/dash), create an account, and generate an API key.

2. Run the `/connect` command and search for **Deep Infra**.

   ```txt
   /connect
   ```

3. Enter your Deep Infra API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model.

   ```txt
   /models
   ```

---

### DigitalOcean

DigitalOcean's [Inference Engine](https://docs.digitalocean.com/products/inference/) provides access to open models like GPT-OSS, Llama, Qwen, and DeepSeek, plus custom [Inference Routers](https://docs.digitalocean.com/products/inference/how-to/use-inference-router/) that route each request to the cheapest, fastest, or best-fit model for a task.

OpenCode supports two authentication methods:

- **OAuth (Recommended)** — Sign in to your DigitalOcean account; OpenCode uses your DigitalOcean API token directly for inference and discovers your Inference Routers.
- **Model Access Key** — Paste an existing key from the DigitalOcean console.

#### OAuth (Recommended)

1. Run the `/connect` command and search for **DigitalOcean**.

   ```txt
   /connect
   ```

2. Select **Login with DigitalOcean**.

   ```txt
   ┌ Select auth method
   │
   │ Login with DigitalOcean
   │ Paste Model Access Key
   └
   ```

3. Your browser opens to authorize OpenCode. Sign in and approve.

   :::note
   OpenCode requests `genai:read` and `inference:query` OAuth scopes. Your DigitalOcean API token is used directly for inference — no separate Model Access Key is created.
   :::

   :::note
   Inference Routers only appear in the model picker after OAuth. Pasting a Model Access Key manually does not discover routers.
   :::

4. Run the `/models` command. Your Inference Routers appear as the format `router:` in the model selection.

   ```txt
   /models
   ```

5. To pick up newly created Inference Routers, re-run `/connect` and select **DigitalOcean** again.

#### Using a Model Access Key

If you'd rather paste a key directly:

1. Head over to the **Manage** page in the Inference section of the [DigitalOcean console](https://cloud.digitalocean.com/) and create a new key.

2. Run the `/connect` command and select **DigitalOcean**, then **Paste Model Access Key**.

   ```txt
   ┌ Enter your DigitalOcean Model Access Key
   │
   │
   └ enter
   ```

   :::note
   Inference Routers are not auto-discovered with this method. To surface them in the model picker, sign in via OAuth instead.
   :::

3. Run the `/models` command to select a model.

   ```txt
   /models
   ```

#### Environment Variable

Alternatively, set your Model Access Key as an environment variable.

```bash frame="none"
export DIGITALOCEAN_ACCESS_TOKEN=your-model-access-key
```

#### Inference Routers

Inference Routers let you define a routing policy across multiple models — picking the cheapest, fastest, or most appropriate model per request based on the task. After OAuth, OpenCode surfaces each router as `router:<router-name>` in the model picker.

Selecting a router model is a drop-in replacement for any other model — OpenCode forwards your request and DigitalOcean picks the underlying model based on your router's policy. Learn more about [Inference Routers](https://docs.digitalocean.com/products/inference/how-to/use-inference-router/)

---

### Eden AI

[Eden AI](https://www.edenai.co/) is an EU-based gateway that serves models from many vendors over a single OpenAI-compatible API, with a separate EU endpoint for teams that need inference to stay in the EU.

1. Head over to the [Eden AI platform](https://app.edenai.run/user/register) to create an account and generate an API key.

2. Run the `/connect` command and search for **Eden AI**.

   ```txt
   /connect
   ```

3. Enter your Eden AI API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model like _Mistral Large 3_ or _Claude Sonnet 5_.

   ```txt
   /models
   ```

   Eden AI model ids are themselves in `vendor/model` form, so a full reference has three segments, for example `edenai/anthropic/claude-sonnet-5`.

5. To keep requests on Eden AI's EU gateway, set its base URL.

   ```json title="opencode.json"
   {
     "$schema": "https://opencode.ai/config.json",
     "provider": {
       "edenai": {
         "options": {
           "baseURL": "https://api.eu.edenai.run/v3"
         }
       }
     }
   }
   ```

   The default is `https://api.edenai.run/v3`, so this swaps the global endpoint for the EU one. The EU endpoint serves the subset of the catalog that is available in the EU, so a model chosen in step 4 may not be reachable through it.

---

### FrogBot

1. Head over to the [FrogBot dashboard](https://app.frogbot.ai/signup), create an account, and generate an API key.

2. Run the `/connect` command and search for **FrogBot**.

   ```txt
   /connect
   ```

3. Enter your FrogBot API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model.

   ```txt
   /models
   ```

---

### Fireworks AI

1. Head over to the [Fireworks AI console](https://app.fireworks.ai/), create an account, and click **Create API Key**.

2. Run the `/connect` command and search for **Fireworks AI**.

   ```txt
   /connect
   ```

3. Enter your Fireworks AI API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model like _Kimi K2 Instruct_.

   ```txt
   /models
   ```

---

### GitLab Duo

:::caution[Experimental]
GitLab Duo support in OpenCode is experimental. Features, configuration, and
behavior may change in future releases.
:::

OpenCode integrates with the [GitLab Duo Agent Platform](https://docs.gitlab.com/user/duo_agent_platform/),
providing AI-powered agentic chat with native tool calling capabilities.

:::note[License requirements]
GitLab Duo Agent Platform requires a **Premium** or **Ultimate** GitLab
subscription. It is available on GitLab.com and GitLab Self-Managed.
See [GitLab Duo Agent Platform prerequisites](https://docs.gitlab.com/user/duo_agent_platform/#prerequisites)
for full requirements.
:::

1. Run the `/connect` command and select GitLab.

   ```txt
   /connect
   ```

2. Choose your authentication method:

   ```txt
   ┌ Select auth method
   │
   │ OAuth (Recommended)
   │ Personal Access Token
   └
   ```

   #### Using OAuth (Recommended)

   Select **OAuth** and your browser will open for authorization.

   #### Using Personal Access Token
   1. Go to [GitLab User Settings > Access Tokens](https://gitlab.com/-/user_settings/personal_access_tokens)
   2. Click **Add new token**
   3. Name: `OpenCode`, Scopes: `api`
   4. Copy the token (starts with `glpat-`)
   5. Enter it in the terminal

3. Run the `/models` command to see available models.

   ```txt
   /models
   ```

   Three Claude-based models are available:
   - **duo-chat-haiku-4-5** (Default) - Fast responses for quick tasks
   - **duo-chat-sonnet-4-5** - Balanced performance for most workflows
   - **duo-chat-opus-4-5** - Most capable for complex analysis

:::note
You can also specify 'GITLAB_TOKEN' environment variable if you don't want
to store token in opencode auth storage.
:::

##### Self-Hosted GitLab

:::note[compliance note]
OpenCode uses a small model for some AI tasks like generating the session title.
It is configured to use gpt-5-nano by default, hosted by Zen. To lock OpenCode
to only use your own GitLab-hosted instance, add the following to your
`opencode.json` file.

```json
{
  "$schema": "https://opencode.ai/config.json",
  "small_model": "gitlab/duo-chat-haiku-4-5"
}
```

:::

For self-hosted GitLab instances:

```bash
export GITLAB_INSTANCE_URL=https://gitlab.company.com
export GITLAB_TOKEN=glpat-...
```

If your instance runs a custom AI Gateway:

```bash
GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com
```

Or add to your bash profile:

```bash title="~/.bash_profile"
export GITLAB_INSTANCE_URL=https://gitlab.company.com
export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com
export GITLAB_TOKEN=glpat-...
```

:::note
Your GitLab administrator must:

1. [Turn on GitLab Duo](https://docs.gitlab.com/user/duo_agent_platform/turn_on_off/#turn-gitlab-duo-on-or-off)
   for the user, group, or instance
2. [Turn on the Agent Platform](https://docs.gitlab.com/user/duo_agent_platform/turn_on_off/#turn-gitlab-duo-agent-platform-on-or-off)
   (GitLab 18.8+) or [enable beta and experimental features](https://docs.gitlab.com/user/duo_agent_platform/turn_on_off/#turn-on-beta-and-experimental-features)
   (GitLab 18.7 and earlier)
3. For Self-Managed, [configure your instance](https://docs.gitlab.com/administration/gitlab_duo/configure/gitlab_self_managed/)
   :::

##### OAuth for Self-Hosted instances

OpenCode's bundled GitLab OAuth application only exists on gitlab.com. To use
OAuth with a self-hosted instance, create your own application (Settings →
Applications) with the callback URL `http://127.0.0.1:8080/callback`, the
`api` scope, and **Confidential** unchecked (PKCE requires a public client).

Then expose the application ID as an environment variable:

```bash
export GITLAB_OAUTH_CLIENT_ID=your_application_id_here
```

##### Configuration

Customize through `opencode.json`:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "gitlab": {
      "options": {
        "instanceUrl": "https://gitlab.com"
      }
    }
  }
}
```

##### GitLab Duo Agent Platform (DAP) Workflow Models

DAP workflow models provide an alternative execution path that routes tool calls
through GitLab's Duo Workflow Service (DWS) instead of the standard agentic chat.
When a `duo-workflow-*` model is selected, OpenCode will:

1. Discover available models from your GitLab namespace
2. Present a selection picker if multiple models are available
3. Cache the selected model to disk for fast subsequent startups
4. Route tool execution requests through OpenCode's permission-gated tool system

Available DAP workflow models follow the `duo-workflow-*` naming convention and
are dynamically discovered from your GitLab instance.

:::note
Workflow model discovery only runs for a login stored with `/connect` (OAuth or
a personal access token). A `GITLAB_TOKEN` environment variable on its own does
not trigger discovery.
:::

##### GitLab API Tools (Optional, but highly recommended)

To access GitLab tools (merge requests, issues, pipelines, CI/CD, etc.):

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["opencode-gitlab-plugin"]
}
```

This plugin provides comprehensive GitLab repository management capabilities including MR reviews, issue tracking, pipeline monitoring, and more.

---

### GitHub Copilot

To use your GitHub Copilot subscription with opencode:

:::note
Some models might need a [Pro+
subscription](https://github.com/features/copilot/plans) to use.
:::

1. Run the `/connect` command and search for GitHub Copilot.

   ```txt
   /connect
   ```

2. Navigate to [github.com/login/device](https://github.com/login/device) and enter the code.

   ```txt
   ┌ Login with GitHub Copilot
   │
   │ https://github.com/login/device
   │
   │ Enter code: 8F43-6FCF
   │
   └ Waiting for authorization...
   ```

3. Now run the `/models` command to select the model you want.

   ```txt
   /models
   ```

---

### GMI Cloud

To use GMI Cloud with OpenCode:

1. Head over to the [GMI Cloud console](https://console.gmicloud.ai/) to create an API key. You can also review the [API reference](https://docs.gmicloud.ai/inference-engine/api-reference/llm-api-reference) for the endpoint details.

2. Run the `/connect` command and search for **GMI Cloud**.

   ```txt
   /connect
   ```

3. Enter your GMI Cloud API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select the model you want.

   ```txt
   /models
   ```

---

### Google Vertex AI

To use Google Vertex AI with OpenCode:

1. Head over to the **Model Garden** in the Google Cloud Console and check the
   models available in your region.

   :::note
   You need to have a Google Cloud project with Vertex AI API enabled.
   :::

2. Set the required environment variables:
   - `GOOGLE_CLOUD_PROJECT`: Your Google Cloud project ID
   - `VERTEX_LOCATION` (optional): The region for Vertex AI (defaults to `global`)
   - Authentication (choose one):
     - `GOOGLE_APPLICATION_CREDENTIALS`: Path to your service account JSON key file
     - Authenticate using gcloud CLI: `gcloud auth application-default login`

   Set them while running opencode.

   ```bash
   GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode
   ```

   Or add them to your bash profile.

   ```bash title="~/.bash_profile"
   export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
   export GOOGLE_CLOUD_PROJECT=your-project-id
   export VERTEX_LOCATION=global
   ```

:::tip
The `global` region improves availability and reduces errors at no extra cost. Use regional endpoints (e.g., `us-central1`) for data residency requirements. [Learn more](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints)
:::

3. Run the `/models` command to select the model you want.

   ```txt
   /models
   ```

---

### Groq

1. Head over to the [Groq console](https://console.groq.com/), click **Create API Key**, and copy the key.

2. Run the `/connect` command and search for Groq.

   ```txt
   /connect
   ```

3. Enter the API key for the provider.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select the one you want.

   ```txt
   /models
   ```

---

### Hugging Face

[Hugging Face Inference Providers](https://huggingface.co/docs/inference-providers) provides access to open models supported by 17+ providers.

1. Head over to [Hugging Face settings](https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained) to create a token with permission to make calls to Inference Providers.

2. Run the `/connect` command and search for **Hugging Face**.

   ```txt
   /connect
   ```

3. Enter your Hugging Face token.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model like _Kimi-K2-Instruct_ or _GLM-4.6_.

   ```txt
   /models
   ```

---

### Helicone

[Helicone](https://helicone.ai) is an LLM observability platform that provides logging, monitoring, and analytics for your AI applications. The Helicone AI Gateway routes your requests to the appropriate provider automatically based on the model.

1. Head over to [Helicone](https://helicone.ai), create an account, and generate an API key from your dashboard.

2. Run the `/connect` command and search for **Helicone**.

   ```txt
   /connect
   ```

3. Enter your Helicone API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model.

   ```txt
   /models
   ```

For more providers and advanced features like caching and rate limiting, check the [Helicone documentation](https://docs.helicone.ai).

#### Optional Configs

In the event you see a feature or model from Helicone that isn't configured automatically through opencode, you can always configure it yourself.

Here's [Helicone's Model Directory](https://helicone.ai/models), you'll need this to grab the IDs of the models you want to add.

```jsonc title="~/.config/opencode/opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "helicone": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Helicone",
      "options": {
        "baseURL": "https://ai-gateway.helicone.ai",
      },
      "models": {
        "gpt-4o": {
          // Model ID (from Helicone's model directory page)
          "name": "GPT-4o", // Your own custom name for the model
        },
        "claude-sonnet-4-20250514": {
          "name": "Claude Sonnet 4",
        },
      },
    },
  },
}
```

#### Custom Headers

Helicone supports custom headers for features like caching, user tracking, and session management. Add them to your provider config using `options.headers`:

```jsonc title="~/.config/opencode/opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "helicone": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Helicone",
      "options": {
        "baseURL": "https://ai-gateway.helicone.ai",
        "headers": {
          "Helicone-Cache-Enabled": "true",
          "Helicone-User-Id": "opencode",
        },
      },
    },
  },
}
```

##### Session tracking

Helicone's [Sessions](https://docs.helicone.ai/features/sessions) feature lets you group related LLM requests together. Use the [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) plugin to automatically log each OpenCode conversation as a session in Helicone.

```bash
npm install opencode-helicone-session
```

Add it to your config.

```json title="opencode.json"
{
  "plugin": ["opencode-helicone-session"]
}
```

The plugin injects `Helicone-Session-Id` and `Helicone-Session-Name` headers into your requests. In Helicone's Sessions page, you'll see each OpenCode conversation listed as a separate session.

##### Common Helicone headers

| Header                     | Description                                                   |
| -------------------------- | ------------------------------------------------------------- |
| `Helicone-Cache-Enabled`   | Enable response caching (`true`/`false`)                      |
| `Helicone-User-Id`         | Track metrics by user                                         |
| `Helicone-Property-[Name]` | Add custom properties (e.g., `Helicone-Property-Environment`) |
| `Helicone-Prompt-Id`       | Associate requests with prompt versions                       |

See the [Helicone Header Directory](https://docs.helicone.ai/helicone-headers/header-directory) for all available headers.

---

### llama.cpp

You can configure opencode to use local models through [llama.cpp's](https://github.com/ggml-org/llama.cpp) llama-server utility

```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15}
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "llama.cpp": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "llama-server (local)",
      "options": {
        "baseURL": "http://127.0.0.1:8080/v1"
      },
      "models": {
        "qwen3-coder:a3b": {
          "name": "Qwen3-Coder: a3b-30b (local)",
          "limit": {
            "context": 128000,
            "output": 65536
          }
        }
      }
    }
  }
}
```

In this example:

- `llama.cpp` is the custom provider ID. This can be any string you want.
- `npm` specifies the package to use for this provider. Here, `@ai-sdk/openai-compatible` is used for any OpenAI-compatible API.
- `name` is the display name for the provider in the UI.
- `options.baseURL` is the endpoint for the local server.
- `models` is a map of model IDs to their configurations. The model name will be displayed in the model selection list.

---

### IO.NET

IO.NET offers 17 models optimized for various use cases:

1. Head over to the [IO.NET console](https://ai.io.net/), create an account, and generate an API key.

2. Run the `/connect` command and search for **IO.NET**.

   ```txt
   /connect
   ```

3. Enter your IO.NET API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model.

   ```txt
   /models
   ```

---

### LM Studio

You can configure opencode to use local models through LM Studio.

```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14}
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "lmstudio": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "LM Studio (local)",
      "options": {
        "baseURL": "http://127.0.0.1:1234/v1"
      },
      "models": {
        "google/gemma-3n-e4b": {
          "name": "Gemma 3n-e4b (local)"
        }
      }
    }
  }
}
```

In this example:

- `lmstudio` is the custom provider ID. This can be any string you want.
- `npm` specifies the package to use for this provider. Here, `@ai-sdk/openai-compatible` is used for any OpenAI-compatible API.
- `name` is the display name for the provider in the UI.
- `options.baseURL` is the endpoint for the local server.
- `models` is a map of model IDs to their configurations. The model name will be displayed in the model selection list.

---

### Moonshot AI

To use Kimi K2 from Moonshot AI:

1. Head over to the [Moonshot AI console](https://platform.moonshot.ai/console), create an account, and click **Create API key**.

2. Run the `/connect` command and search for **Moonshot AI**.

   ```txt
   /connect
   ```

3. Enter your Moonshot API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select _Kimi K2_.

   ```txt
   /models
   ```

---

### MiniMax

1. Head over to the [MiniMax API Console](https://platform.minimax.io/login), create an account, and generate an API key.

2. Run the `/connect` command and search for **MiniMax**.

   ```txt
   /connect
   ```

3. Enter your MiniMax API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model like _M2.1_.

   ```txt
   /models
   ```

---

### Modal

1. Create a [shared Endpoint](https://modal.com/endpoints) for the model you want to use.

2. Create a [proxy token](https://modal.com/docs/guide/endpoints#proxy-tokens), then join its ID and secret with a period:

   ```txt
   wk-<id>.ws-<secret>
   ```

3. Run the `/connect` command, search for **Modal**, and enter the combined proxy token.

   ```txt
   /connect
   ```

4. Run the `/models` command to select one of the endpoints in your Modal workspace.

   ```txt
   /models
   ```

---

### NVIDIA

NVIDIA provides access to Nemotron models and many other open models through [build.nvidia.com](https://build.nvidia.com) for free.

1. Head over to [build.nvidia.com](https://build.nvidia.com), create an account, and generate an API key.

2. Run the `/connect` command and search for **NVIDIA**.

   ```txt
   /connect
   ```

3. Enter your NVIDIA API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model like nemotron-3-super-120b-a12b.

   ```txt
   /models
   ```

#### On-Prem / NIM

You can also use NVIDIA models locally via [NVIDIA NIM](https://docs.nvidia.com/nim/) by setting a custom base URL.

```json title="opencode.json" {6}
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "nvidia": {
      "options": {
        "baseURL": "http://localhost:8000/v1"
      }
    }
  }
}
```

#### Environment Variable

Alternatively, set your API key as an environment variable.

```bash frame="none"
export NVIDIA_API_KEY=nvapi-your-key-here
```

---

### Nebius Token Factory

1. Head over to the [Nebius Token Factory console](https://tokenfactory.nebius.com/), create an account, and click **Add Key**.

2. Run the `/connect` command and search for **Nebius Token Factory**.

   ```txt
   /connect
   ```

3. Enter your Nebius Token Factory API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model like _Kimi K2 Instruct_.

   ```txt
   /models
   ```

---

### Ollama

You can configure opencode to use local models through Ollama.

:::tip
Ollama can automatically configure itself for OpenCode. See the [Ollama integration docs](https://docs.ollama.com/integrations/opencode) for details.
:::

```json title="opencode.json" "ollama" {5, 6, 8, 10-14}
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "ollama": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Ollama (local)",
      "options": {
        "baseURL": "http://localhost:11434/v1"
      },
      "models": {
        "llama2": {
          "name": "Llama 2"
        }
      }
    }
  }
}
```

In this example:

- `ollama` is the custom provider ID. This can be any string you want.
- `npm` specifies the package to use for this provider. Here, `@ai-sdk/openai-compatible` is used for any OpenAI-compatible API.
- `name` is the display name for the provider in the UI.
- `options.baseURL` is the endpoint for the local server.
- `models` is a map of model IDs to their configurations. The model name will be displayed in the model selection list.

:::tip
If tool calls aren't working, try increasing `num_ctx` in Ollama. Start around 16k - 32k.
:::

---

### Ollama Cloud

To use Ollama Cloud with OpenCode:

1. Head over to [https://ollama.com/](https://ollama.com/) and sign in or create an account.

2. Navigate to **Settings** > **Keys** and click **Add API Key** to generate a new API key.

3. Copy the API key for use in OpenCode.

4. Run the `/connect` command and search for **Ollama Cloud**.

   ```txt
   /connect
   ```

5. Enter your Ollama Cloud API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

6. **Important**: Before using cloud models in OpenCode, you must pull the model information locally:

   ```bash
   ollama pull gpt-oss:20b-cloud
   ```

7. Run the `/models` command to select your Ollama Cloud model.

   ```txt
   /models
   ```

---

### OpenAI

We recommend signing up for [ChatGPT Plus or Pro](https://chatgpt.com/pricing).

1. Once you've signed up, run the `/connect` command and select OpenAI.

   ```txt
   /connect
   ```

2. Here you can select the **ChatGPT Plus/Pro** option and it'll open your browser
   and ask you to authenticate.

   ```txt
   ┌ Select auth method
   │
   │ ChatGPT Plus/Pro
   │ Manually enter API Key
   └
   ```

3. Now all the OpenAI models should be available when you use the `/models` command.

   ```txt
   /models
   ```

##### Compute residency

For ChatGPT OAuth, OpenCode automatically applies a regional inference residency requirement when one is advertised by your workspace credentials. It forwards the compute residency value from the credential instead of maintaining a fixed list of regions. Data residency at rest does not imply regional inference.

##### Using API keys

If you already have an API key, you can select **Manually enter API Key** and paste it in your terminal.

---

### OpenCode Zen

OpenCode Zen is a list of tested and verified models provided by the OpenCode team. [Learn more](https://opencode.ai/v2/docs/console/).

1. Sign in to **<a href={console}>OpenCode Zen</a>** and click **Create API Key**.

2. Run the `/connect` command and search for **OpenCode Zen**.

   ```txt
   /connect
   ```

3. Enter your OpenCode API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model like _Qwen 3 Coder 480B_.

   ```txt
   /models
   ```

---

### OpenRouter

1. Head over to the [OpenRouter dashboard](https://openrouter.ai/settings/keys), click **Create API Key**, and copy the key.

2. Run the `/connect` command and search for OpenRouter.

   ```txt
   /connect
   ```

3. Enter the API key for the provider.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Many OpenRouter models are preloaded by default, run the `/models` command to select the one you want.

   ```txt
   /models
   ```

   You can also add additional models through your opencode config.

   ```json title="opencode.json" {6}
   {
     "$schema": "https://opencode.ai/config.json",
     "provider": {
       "openrouter": {
         "models": {
           "somecoolnewmodel": {}
         }
       }
     }
   }
   ```

5. You can also customize them through your opencode config. Here's an example of specifying a provider

   ```json title="opencode.json"
   {
     "$schema": "https://opencode.ai/config.json",
     "provider": {
       "openrouter": {
         "models": {
           "moonshotai/kimi-k2": {
             "options": {
               "provider": {
                 "order": ["baseten"],
                 "allow_fallbacks": false
               }
             }
           }
         }
       }
     }
   }
   ```

---

### LLM Gateway

1. Head over to the [LLM Gateway dashboard](https://llmgateway.io/dashboard), click **Create API Key**, and copy the key.

2. Run the `/connect` command and search for LLM Gateway.

   ```txt
   /connect
   ```

3. Enter the API key for the provider.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Many LLM Gateway models are preloaded by default, run the `/models` command to select the one you want.

   ```txt
   /models
   ```

   You can also add additional models through your opencode config.

   ```json title="opencode.json" {6}
   {
     "$schema": "https://opencode.ai/config.json",
     "provider": {
       "llmgateway": {
         "models": {
           "somecoolnewmodel": {}
         }
       }
     }
   }
   ```

5. You can also customize them through your opencode config. Here's an example of specifying a provider

   ```json title="opencode.json"
   {
     "$schema": "https://opencode.ai/config.json",
     "provider": {
       "llmgateway": {
         "models": {
           "glm-4.7": {
             "name": "GLM 4.7"
           },
           "gpt-5.2": {
             "name": "GPT-5.2"
           },
           "gemini-2.5-pro": {
             "name": "Gemini 2.5 Pro"
           },
           "claude-3-5-sonnet-20241022": {
             "name": "Claude 3.5 Sonnet"
           }
         }
       }
     }
   }
   ```

---

### Poolside

[Poolside](https://poolside.ai) provides access to its models through an OpenAI-compatible API.

1. Head over to [platform.poolside.ai](https://platform.poolside.ai), sign in, open the **API Keys** tab, and click **New key** to generate an API key.

2. Run the `/connect` command and search for **Poolside**.

   ```txt
   /connect
   ```

3. Enter your Poolside API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model.

   ```txt
   /models
   ```

#### Poolside deployment

If your organization runs a Poolside deployment, configure it as a custom OpenAI-compatible provider. Store the API key or token from your Poolside administrator in `~/.secrets/poolside-key`. Use a unique provider ID and add the model IDs available from your deployment.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "poolside-deployment": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Poolside deployment",
      "options": {
        "baseURL": "https://poolside.example.com/openai/v1",
        "apiKey": "{file:~/.secrets/poolside-key}"
      },
      "models": {
        "<served-model-id>": {
          "name": "Poolside deployment model",
          "reasoning": true,
          "interleaved": {
            "field": "reasoning_content"
          }
        }
      }
    }
  }
}
```

Replace `poolside.example.com` with your deployment's host and `<served-model-id>` with a model ID returned by its `/openai/v1/models` endpoint. Model availability and thinking behavior depend on the deployment's configuration.

:::tip
You can also install [Poolside Agent CLI](https://github.com/poolsideai/pool) to use Poolside agents directly from your terminal.
:::

---

### SAP AI Core

SAP AI Core provides access to 40+ models from OpenAI, Anthropic, Google, Amazon, Meta, Mistral, and AI21 through a unified platform.

1. Go to your [SAP BTP Cockpit](https://account.hana.ondemand.com/), navigate to your SAP AI Core service instance, and create a service key.

   :::tip
   The service key is a JSON object containing `clientid`, `clientsecret`, `url`, and `serviceurls.AI_API_URL`. You can find your AI Core instance under **Services** > **Instances and Subscriptions** in the BTP Cockpit.
   :::

2. Run the `/connect` command and search for **SAP AI Core**.

   ```txt
   /connect
   ```

3. Enter your service key JSON.

   ```txt
   ┌ Service key
   │
   │
   └ enter
   ```

   Or set the `AICORE_SERVICE_KEY` environment variable:

   ```bash
   AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' opencode
   ```

   Or add it to your bash profile:

   ```bash title="~/.bash_profile"
   export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}'
   ```

4. Optionally set deployment ID and resource group:

   ```bash
   AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode
   ```

   :::note
   These settings are optional and should be configured according to your SAP AI Core setup.
   :::

5. Run the `/models` command to select from 40+ available models.

   ```txt
   /models
   ```

---

### STACKIT

STACKIT AI Model Serving provides fully managed sovereign hosting environment for AI models, focusing on LLMs like Llama, Mistral, and Qwen, with maximum data sovereignty on European infrastructure.

1. Head over to [STACKIT Portal](https://portal.stackit.cloud), navigate to **AI Model Serving**, and create an auth token for your project.

   :::tip
   You need a STACKIT customer account, user account, and project before creating auth tokens.
   :::

2. Run the `/connect` command and search for **STACKIT**.

   ```txt
   /connect
   ```

3. Enter your STACKIT AI Model Serving auth token.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select from available models like _Qwen3-VL 235B_ or _Llama 3.3 70B_.

   ```txt
   /models
   ```

---

### OVHcloud AI Endpoints

1. Head over to the [OVHcloud panel](https://ovh.com/manager). Navigate to the `Public Cloud` section, `AI & Machine Learning` > `AI Endpoints` and in `API Keys` tab, click **Create a new API key**.

2. Run the `/connect` command and search for **OVHcloud AI Endpoints**.

   ```txt
   /connect
   ```

3. Enter your OVHcloud AI Endpoints API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model like _gpt-oss-120b_.

   ```txt
   /models
   ```

---

### Scaleway

To use [Scaleway Generative APIs](https://www.scaleway.com/en/docs/generative-apis/) with Opencode:

1. Head over to the [Scaleway Console IAM settings](https://console.scaleway.com/iam/api-keys) to generate a new API key.

2. Run the `/connect` command and search for **Scaleway**.

   ```txt
   /connect
   ```

3. Enter your Scaleway API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model like _devstral-2-123b-instruct-2512_ or _gpt-oss-120b_.

   ```txt
   /models
   ```

---

### SCX.ai

[SCX.ai](https://scx.ai) is an Australian sovereign AI platform serving open models over an OpenAI-compatible API, hosted on renewable-powered infrastructure in Australia.

1. Head over to the [SCX.ai platform](https://platform.scx.ai) to create an account and generate an API key.

2. Run the `/connect` command and search for **SCX.ai**.

   ```txt
   /connect
   ```

3. Enter your SCX.ai API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model like _MiniMax-M2.7_ or _GLM-5.2_.

   ```txt
   /models
   ```

---

### Snowflake Cortex

[Snowflake Cortex](https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-rest-api) gives you access to frontier models (Claude, OpenAI GPT-5, and more) via an OpenAI-compatible API. All inference runs within the Snowflake perimeter and is billed in Snowflake credits. For per-model rates, see the [Snowflake Service Consumption Table](https://www.snowflake.com/legal-files/CreditConsumptionTable.pdf).

Don't have a Snowflake account? [Sign up for a free trial](https://signup.snowflake.com/?utm_source=opencode&utm_medium=docs&utm_campaign=cortex-provider).

opencode's core workflow for coding, editing files, and running commands relies on tool calling. Only the Claude and OpenAI families within Snowflake Cortex support this. The provider is limited to those families to support the core workflow.

OpenCode supports two authentication methods:

- **Browser OAuth (Recommended)** — sign in with your IdP/SSO; no secrets to manage, tokens refresh automatically.
- **Manual bearer token** — paste a PAT or JWT from the Snowflake console.

#### Browser OAuth (Recommended)

1. Run the `/connect` command and search for **Snowflake Cortex**.

   ```txt
   /connect
   ```

2. Select **Login with Snowflake (External Browser)**.

   ```txt
   ┌ Select auth method
   │
   │ Login with Snowflake (External Browser)
   │ Paste PAT or bearer token manually
   └
   ```

3. Enter your [account identifier](https://docs.snowflake.com/en/user-guide/admin-account-identifier) when prompted, for example `myorg-myaccount` or `xy12345.us-east-1`.

   ```txt
   ┌ Snowflake Account Identifier
   │
   │
   └ enter
   ```

4. Optionally enter a Snowflake role to scope the session (e.g. `SYSADMIN`). Leave blank to use your default role.

5. Complete sign-in in the browser that opens. OpenCode captures the OAuth callback automatically and stores the token — no copy/paste needed.

6. Run the `/models` command to select a model.

   ```txt
   /models
   ```

:::note
Browser OAuth uses Snowflake's built-in `SNOWFLAKE$LOCAL_APPLICATION` security integration ([docs](https://docs.snowflake.com/en/user-guide/oauth-local-applications)), which is rolling out to all accounts. To check availability in your account:

```sql
SHOW SECURITY INTEGRATIONS LIKE 'SNOWFLAKE$LOCAL_APPLICATION';
```

If the result is empty, use the **Manual bearer token** method below while the integration rolls out to your account.
:::

#### Manual bearer token

If you prefer to paste a token directly, or if `SNOWFLAKE$LOCAL_APPLICATION` is not yet available in your account:

1. Generate a [Programmatic Access Token (PAT)](https://docs.snowflake.com/en/user-guide/programmatic-access-tokens) in your Snowflake account.

2. Run the `/connect` command, search for **Snowflake Cortex**, and select **Paste PAT or bearer token manually**.

3. Enter your [account identifier](https://docs.snowflake.com/en/user-guide/admin-account-identifier) when prompted.

4. Paste your PAT.

5. Run the `/models` command to select a model.

   ```txt
   /models
   ```

#### Environment variable

For CI or headless environments, set a PAT or JWT before starting opencode:

```bash
export SNOWFLAKE_ACCOUNT=myorg-myaccount
export SNOWFLAKE_CORTEX_TOKEN=your-pat-or-jwt
```

:::note
`SNOWFLAKE_CORTEX_TOKEN` accepts a PAT or JWT only — the browser OAuth flow is available via `/connect` only and cannot be configured through an environment variable. `SNOWFLAKE_CORTEX_PAT` is still supported for backward compatibility.
:::

The model catalog is provided automatically. A minimal `opencode.json` is all that's needed:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "model": "snowflake-cortex/claude-sonnet-4-6",
  "small_model": "snowflake-cortex/claude-haiku-4-5"
}
```

---

### Together AI

1. Head over to the [Together AI console](https://api.together.ai), create an account, and click **Add Key**.

2. Run the `/connect` command and search for **Together AI**.

   ```txt
   /connect
   ```

3. Enter your Together AI API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model like _Kimi K2 Instruct_.

   ```txt
   /models
   ```

---

### Venice AI

1. Head over to the [Venice AI console](https://venice.ai), create an account, and generate an API key.

2. Run the `/connect` command and search for **Venice AI**.

   ```txt
   /connect
   ```

3. Enter your Venice AI API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model like _Llama 3.3 70B_.

   ```txt
   /models
   ```

---

### Vercel AI Gateway

Vercel AI Gateway lets you access models from OpenAI, Anthropic, Google, xAI, and more through a unified endpoint. Models are offered at list price with no markup.

1. Head over to the [Vercel dashboard](https://vercel.com/), navigate to the **AI Gateway** tab, and click **API keys** to create a new API key.

2. Run the `/connect` command and search for **Vercel AI Gateway**.

   ```txt
   /connect
   ```

3. Enter your Vercel AI Gateway API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model.

   ```txt
   /models
   ```

You can also customize models through your opencode config. Here's an example of specifying provider routing order.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "vercel": {
      "models": {
        "anthropic/claude-sonnet-4": {
          "options": {
            "order": ["anthropic", "vertex"]
          }
        }
      }
    }
  }
}
```

Some useful routing options:

| Option              | Description                                          |
| ------------------- | ---------------------------------------------------- |
| `order`             | Provider sequence to try                             |
| `only`              | Restrict to specific providers                       |
| `zeroDataRetention` | Only use providers with zero data retention policies |

---

### xAI

Two ways to authenticate: a SuperGrok subscription via device-code OAuth or a pay-as-you-go API key from the xAI console.

#### Option A — SuperGrok subscription

1. Run the `/connect` command and search for **xAI**.

   ```txt
   /connect
   ```

2. Select **SuperGrok Subscription**. OpenCode opens xAI's verification link with the user code pre-populated when supported.

3. Approve the consent screen. If xAI asks for a code, enter the user code displayed by OpenCode. OpenCode polls xAI's token endpoint and stores the resulting OAuth tokens once you approve.

4. Run the `/models` command to select a Grok model.

   ```txt
   /models
   ```

OpenCode refreshes the OAuth access token automatically. Any Grok or X Premium plan that includes Grok API access works; you do not need a separate `XAI_API_KEY`.

#### Option B — API key

1. Head over to the [xAI console](https://console.x.ai/), create an account, and generate an API key.

2. Run the `/connect` command and search for **xAI**.

   ```txt
   /connect
   ```

3. Select **Manually enter API Key** and paste your xAI API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model like _Grok Beta_.

   ```txt
   /models
   ```

---

### Z.AI

1. Head over to the [Z.AI API console](https://z.ai/manage-apikey/apikey-list), create an account, and click **Create a new API key**.

2. Run the `/connect` command and search for **Z.AI**.

   ```txt
   /connect
   ```

   If you are subscribed to the **GLM Coding Plan**, select **Z.AI Coding Plan**.

3. Enter your Z.AI API key.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Run the `/models` command to select a model like _GLM-4.7_.

   ```txt
   /models
   ```

---

### ZenMux

1. Head over to the [ZenMux dashboard](https://zenmux.ai/settings/keys), click **Create API Key**, and copy the key.

2. Run the `/connect` command and search for ZenMux.

   ```txt
   /connect
   ```

3. Enter the API key for the provider.

   ```txt
   ┌ API key
   │
   │
   └ enter
   ```

4. Many ZenMux models are preloaded by default, run the `/models` command to select the one you want.

   ```txt
   /models
   ```

   You can also add additional models through your opencode config.

   ```json title="opencode.json" {6}
   {
     "$schema": "https://opencode.ai/config.json",
     "provider": {
       "zenmux": {
         "models": {
           "somecoolnewmodel": {}
         }
       }
     }
   }
   ```

---

## Custom provider

To add any **OpenAI-compatible** provider that's not listed in the `/connect` command:

:::tip
You can use any OpenAI-compatible provider with opencode. Most modern AI providers offer OpenAI-compatible APIs.
:::

1. Run the `/connect` command and scroll down to **Other**.

   ```bash
   $ /connect

   ┌  Add credential
   │
   ◆  Select provider
   │  ...
   │  ● Other
   └
   ```

2. Enter a unique ID for the provider.

   ```bash
   $ /connect

   ┌  Add credential
   │
   ◇  Enter provider id
   │  myprovider
   └
   ```

   :::note
   Choose a memorable ID, you'll use this in your config file.
   :::

3. Enter your API key for the provider.

   ```bash
   $ /connect

   ┌  Add credential
   │
   ▲  This only stores a credential for myprovider - you will need to configure it in opencode.json, check the docs for examples.
   │
   ◇  Enter your API key
   │  sk-...
   └
   ```

4. Create or update your `opencode.json` file in your project directory:

   ```json title="opencode.json" ""myprovider"" {5-15}
   {
     "$schema": "https://opencode.ai/config.json",
     "provider": {
       "myprovider": {
         "npm": "@ai-sdk/openai-compatible",
         "name": "My AI Provider Display Name",
         "options": {
           "baseURL": "https://api.myprovider.com/v1"
         },
         "models": {
           "my-model-name": {
             "name": "My Model Display Name"
           }
         }
       }
     }
   }
   ```

   Here are the configuration options:
   - **npm**: AI SDK package to use, `@ai-sdk/openai-compatible` for OpenAI-compatible providers (for `/v1/chat/completions`). If your provider/model uses `/v1/responses`, use `@ai-sdk/openai`.
   - **name**: Display name in UI.
   - **models**: Available models.
   - **options.baseURL**: API endpoint URL.
   - **options.apiKey**: Optionally set the API key, if not using auth.
   - **options.headers**: Optionally set custom headers.

   More on the advanced options in the example below.

5. Run the `/models` command and your custom provider and models will appear in the selection list.

---

##### Example

Here's an example setting the `apiKey`, `headers`, and model `limit` options.

```json title="opencode.json" {9,11,17-20}
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "myprovider": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "My AI Provider Display Name",
      "options": {
        "baseURL": "https://api.myprovider.com/v1",
        "apiKey": "{env:ANTHROPIC_API_KEY}",
        "headers": {
          "Authorization": "Bearer custom-token"
        }
      },
      "models": {
        "my-model-name": {
          "name": "My Model Display Name",
          "limit": {
            "context": 200000,
            "output": 65536
          }
        }
      }
    }
  }
}
```

Configuration details:

- **apiKey**: Set using `env` variable syntax, [learn more](/docs/config#env-vars).
- **headers**: Custom headers sent with each request.
- **limit.context**: Maximum input tokens the model accepts.
- **limit.output**: Maximum tokens the model can generate.

The `limit` fields allow OpenCode to understand how much context you have left. Standard providers pull these from models.dev automatically.

---

## Troubleshooting

If you are having trouble with configuring a provider, check the following:

1. **Check the auth setup**: Run `opencode auth list` to see if the credentials
   for the provider are added to your config.

   This doesn't apply to providers like Amazon Bedrock, that rely on environment variables for their auth.

2. For custom providers, check the opencode config and:
   - Make sure the provider ID used in the `/connect` command matches the ID in your opencode config.
   - The right npm package is used for the provider. For example, use `@ai-sdk/cerebras` for Cerebras. And for all other OpenAI-compatible providers, use `@ai-sdk/openai-compatible` (for `/v1/chat/completions`); if a model uses `/v1/responses`, use `@ai-sdk/openai`. For mixed setups under one provider, you can override per model via `provider.npm`.
   - Check correct API endpoint is used in the `options.baseURL` field.

---

### Packages Web Src Content Docs References (`packages/web/src/content/docs/references.mdx`)

---
title: References
description: Add local directories and Git repositories as project references.
---

References give OpenCode access to directories outside the current project. Use them to make documentation, shared libraries, examples, or another repository available while you work.

References are configured by alias in `opencode.json` or `opencode.jsonc`.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "references": {
    "docs": {
      "path": "../product-docs",
      "description": "Use for product behavior and documentation conventions",
    },
    "sdk": {
      "repository": "anomalyco/opencode-sdk-js",
      "branch": "main",
      "description": "Use for JavaScript SDK implementation details",
    },
  },
}
```

---

## Local directories

Use `path` to reference a local directory.

```jsonc title="opencode.jsonc"
{
  "references": {
    "docs": {
      "path": "../docs",
    },
  },
}
```

Paths can be:

- Relative to the config file that defines the reference
- Absolute, such as `/home/user/docs`
- Relative to your home directory, such as `~/docs`

You can also use a string shorthand:

```jsonc title="opencode.jsonc"
{
  "references": {
    "docs": "../docs",
  },
}
```

---

## Git repositories

Use `repository` to reference a Git repository. OpenCode materializes the repository in its local repository cache and makes the checked-out source available as a reference directory.

```jsonc title="opencode.jsonc"
{
  "references": {
    "effect": {
      "repository": "Effect-TS/effect",
      "branch": "main",
    },
  },
}
```

`repository` accepts Git URLs, host/path references, and GitHub `owner/repo` shorthand. The optional `branch` field selects a branch or ref. Without `branch`, OpenCode uses the repository's default branch.

You can use string shorthand when you do not need a branch, description, or other options:

```jsonc title="opencode.jsonc"
{
  "references": {
    "effect": "Effect-TS/effect",
  },
}
```

:::note
Git references are refreshed asynchronously. A newly configured repository may take a moment to finish cloning or updating.
:::

---

## Describe usage

Add `description` to explain when an agent should use a reference.

```jsonc title="opencode.jsonc"
{
  "references": {
    "design-system": {
      "path": "../design-system",
      "description": "Use when implementing UI components or design tokens",
    },
  },
}
```

OpenCode includes references with descriptions in agent context. Descriptions should be short and specific enough to distinguish references with similar content. References without descriptions remain available through autocomplete and direct use, but are not advertised to agents.

---

## Hide autocomplete entries

Set `hidden` to `true` to omit a reference from `@` autocomplete in the TUI.

```jsonc title="opencode.jsonc"
{
  "references": {
    "internal": {
      "path": "../internal",
      "description": "Use for internal implementation details",
      "hidden": true,
    },
  },
}
```

`hidden` only affects autocomplete. A hidden reference with a description remains included in agent context.

---

## Use references

Configured references appear in TUI `@` autocomplete. Type `@alias` to attach the reference root, or `@alias/` to search for files inside it.

```text
Compare this implementation with @sdk/src/client.ts
```

Agents also receive the resolved paths and descriptions of configured references that have descriptions in their system context, so they can inspect a reference when it is relevant without you attaching it manually.

OpenCode automatically allows reference directories through its external-directory permission boundary. Normal tool permissions still apply; for example, an agent that cannot edit files does not gain edit access because a directory is configured as a reference.

---

## Configure fields

| Field         | Local | Git | Description                                      |
| ------------- | ----- | --- | ------------------------------------------------ |
| `path`        | Yes   | No  | Local reference directory                        |
| `repository`  | No    | Yes | Git URL, host/path, or GitHub `owner/repo` value |
| `branch`      | No    | Yes | Optional Git branch or ref                       |
| `description` | Yes   | Yes | Guidance describing when to use the reference    |
| `hidden`      | Yes   | Yes | Hide the reference from TUI `@` autocomplete     |

Reference aliases cannot be empty or contain `/`, whitespace, backticks, or commas.

---

### Packages Web Src Content Docs Rules (`packages/web/src/content/docs/rules.mdx`)

---
title: Rules
description: Set custom instructions for opencode.
---

You can provide custom instructions to opencode by creating an `AGENTS.md` file. This is similar to Cursor's rules. It contains instructions that will be included in the LLM's context to customize its behavior for your specific project.

---

## Initialize

To create a new `AGENTS.md` file, you can run the `/init` command in opencode.

:::tip
You should commit your project's `AGENTS.md` file to Git.
:::

`/init` scans the important files in your repo, may ask a couple of targeted questions when the codebase cannot answer them, and then creates or updates `AGENTS.md` with concise project-specific guidance.

It focuses on the things future agent sessions are most likely to need:

- build, lint, and test commands
- command order and focused verification steps when they matter
- architecture and repo structure that are not obvious from filenames alone
- project-specific conventions, setup quirks, and operational gotchas
- references to existing instruction sources like Cursor or Copilot rules

If you already have an `AGENTS.md`, `/init` will improve it in place instead of blindly replacing it.

---

## Example

You can also just create this file manually. Here's an example of some things you can put into an `AGENTS.md` file.

```markdown title="AGENTS.md"
# SST v3 Monorepo Project

This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management.

## Project Structure

- `packages/` - Contains all workspace packages (functions, core, web, etc.)
- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts)
- `sst.config.ts` - Main SST configuration with dynamic imports

## Code Standards

- Use TypeScript with strict mode enabled
- Shared code goes in `packages/core/` with proper exports configuration
- Functions go in `packages/functions/`
- Infrastructure should be split into logical files in `infra/`

## Monorepo Conventions

- Import shared modules using workspace names: `@my-app/core/example`
```

We are adding project-specific instructions here and this will be shared across your team.

---

## Types

opencode also supports reading the `AGENTS.md` file from multiple locations. And this serves different purposes.

### Project

Place an `AGENTS.md` in your project root for project-specific rules. These only apply when you are working in this directory or its sub-directories.

### Global

You can also have global rules in a `~/.config/opencode/AGENTS.md` file. This gets applied across all opencode sessions.

Since this isn't committed to Git or shared with your team, we recommend using this to specify any personal rules that the LLM should follow.

### Claude Code Compatibility

For users migrating from Claude Code, OpenCode supports Claude Code's file conventions as fallbacks:

- **Project rules**: `CLAUDE.md` in your project directory (used if no `AGENTS.md` exists)
- **Global rules**: `~/.claude/CLAUDE.md` (used if no `~/.config/opencode/AGENTS.md` exists)
- **Skills**: `~/.claude/skills/` — see [Agent Skills](/docs/skills/) for details

To disable Claude Code compatibility, set one of these environment variables:

```bash
export OPENCODE_DISABLE_CLAUDE_CODE=1        # Disable all .claude support
export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md
export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills
```

---

## Precedence

When opencode starts, it looks for rule files in this order:

1. **Local files** by traversing up from the current directory (`AGENTS.md`, `CLAUDE.md`)
2. **Global file** at `~/.config/opencode/AGENTS.md`
3. **Claude Code file** at `~/.claude/CLAUDE.md` (unless disabled)

The first matching file wins in each category. For example, if you have both `AGENTS.md` and `CLAUDE.md`, only `AGENTS.md` is used. Similarly, `~/.config/opencode/AGENTS.md` takes precedence over `~/.claude/CLAUDE.md`.

---

## Custom Instructions

You can specify custom instruction files in your `opencode.json` or the global `~/.config/opencode/opencode.json`. This allows you and your team to reuse existing rules rather than having to duplicate them to AGENTS.md.

Example:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"]
}
```

You can also use remote URLs to load instructions from the web.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"]
}
```

Remote instructions are fetched with a 5 second timeout.

All instruction files are combined with your `AGENTS.md` files.

---

## Referencing External Files

While opencode doesn't automatically parse file references in `AGENTS.md`, you can achieve similar functionality in two ways:

### Using opencode.json

The recommended approach is to use the `instructions` field in `opencode.json`:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"]
}
```

### Manual Instructions in AGENTS.md

You can teach opencode to read external files by providing explicit instructions in your `AGENTS.md`. Here's a practical example:

```markdown title="AGENTS.md"
# TypeScript Project Rules

## External File Loading

CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand.

Instructions:

- Do NOT preemptively load all references - use lazy loading based on actual need
- When loaded, treat content as mandatory instructions that override defaults
- Follow references recursively when needed

## Development Guidelines

For TypeScript code style and best practices: @docs/typescript-guidelines.md
For React component architecture and hooks patterns: @docs/react-patterns.md
For REST API design and error handling: @docs/api-standards.md
For testing strategies and coverage requirements: @test/testing-guidelines.md

## General Guidelines

Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md.
```

This approach allows you to:

- Create modular, reusable rule files
- Share rules across projects via symlinks or git submodules
- Keep AGENTS.md concise while referencing detailed guidelines
- Ensure opencode loads files only when needed for the specific task

:::tip
For monorepos or projects with shared standards, using `opencode.json` with glob patterns (like `packages/*/AGENTS.md`) is more maintainable than manual instructions.
:::

---

### Packages Web Src Content Docs Sdk (`packages/web/src/content/docs/sdk.mdx`)

---
title: SDK
description: Type-safe JS client for opencode server.
---

import config from "../../../config.mjs"
export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts`

The opencode JS/TS SDK provides a type-safe client for interacting with the server.
Use it to build integrations and control opencode programmatically.

[Learn more](/docs/server) about how the server works. For examples, check out the [projects](/docs/ecosystem#projects) built by the community.

---

## Install

Install the SDK from npm:

```bash
npm install @opencode-ai/sdk
```

---

## Create client

Create an instance of opencode:

```javascript
import { createOpencode } from "@opencode-ai/sdk"

const { client } = await createOpencode()
```

This starts both a server and a client

#### Options

| Option     | Type          | Description                    | Default     |
| ---------- | ------------- | ------------------------------ | ----------- |
| `hostname` | `string`      | Server hostname                | `127.0.0.1` |
| `port`     | `number`      | Server port                    | `4096`      |
| `signal`   | `AbortSignal` | Abort signal for cancellation  | `undefined` |
| `timeout`  | `number`      | Timeout in ms for server start | `5000`      |
| `config`   | `Config`      | Configuration object           | `{}`        |

---

## Config

You can pass a configuration object to customize behavior. The instance still picks up your `opencode.json`, but you can override or add configuration inline:

```javascript
import { createOpencode } from "@opencode-ai/sdk"

const opencode = await createOpencode({
  hostname: "127.0.0.1",
  port: 4096,
  config: {
    model: "anthropic/claude-3-5-sonnet-20241022",
  },
})

console.log(`Server running at ${opencode.server.url}`)

opencode.server.close()
```

## Client only

If you already have a running instance of opencode, you can create a client instance to connect to it:

```javascript
import { createOpencodeClient } from "@opencode-ai/sdk"

const client = createOpencodeClient({
  baseUrl: "http://localhost:4096",
})
```

#### Options

| Option          | Type       | Description                      | Default                 |
| --------------- | ---------- | -------------------------------- | ----------------------- |
| `baseUrl`       | `string`   | URL of the server                | `http://localhost:4096` |
| `fetch`         | `function` | Custom fetch implementation      | `globalThis.fetch`      |
| `parseAs`       | `string`   | Response parsing method          | `auto`                  |
| `responseStyle` | `string`   | Return style: `data` or `fields` | `fields`                |
| `throwOnError`  | `boolean`  | Throw errors instead of return   | `false`                 |

---

## Types

The SDK includes TypeScript definitions for all API types. Import them directly:

```typescript
import type { Session, Message, Part } from "@opencode-ai/sdk"
```

All types are generated from the server's OpenAPI specification and available in the <a href={typesUrl}>types file</a>.

---

## Errors

The SDK can throw errors that you can catch and handle:

```typescript
try {
  await client.session.get({ path: { id: "invalid-id" } })
} catch (error) {
  console.error("Failed to get session:", (error as Error).message)
}
```

---

## Structured Output

You can request structured JSON output from the model by specifying an `format` with a JSON schema. The model will use a `StructuredOutput` tool to return validated JSON matching your schema.

### Basic Usage

```typescript
const result = await client.session.prompt({
  path: { id: sessionId },
  body: {
    parts: [{ type: "text", text: "Research Anthropic and provide company info" }],
    format: {
      type: "json_schema",
      schema: {
        type: "object",
        properties: {
          company: { type: "string", description: "Company name" },
          founded: { type: "number", description: "Year founded" },
          products: {
            type: "array",
            items: { type: "string" },
            description: "Main products",
          },
        },
        required: ["company", "founded"],
      },
    },
  },
})

// Access the structured output
console.log(result.data.info.structured_output)
// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] }
```

### Output Format Types

| Type          | Description                                            |
| ------------- | ------------------------------------------------------ |
| `text`        | Default. Standard text response (no structured output) |
| `json_schema` | Returns validated JSON matching the provided schema    |

### JSON Schema Format

When using `type: 'json_schema'`, provide:

| Field        | Type            | Description                                                |
| ------------ | --------------- | ---------------------------------------------------------- |
| `type`       | `'json_schema'` | Required. Specifies JSON schema mode                       |
| `schema`     | `object`        | Required. JSON Schema object defining the output structure |
| `retryCount` | `number`        | Optional. Number of validation retries (default: 2)        |

### Error Handling

If the model fails to produce valid structured output after all retries, the response will include a `StructuredOutputError`:

```typescript
if (result.data.info.error?.name === "StructuredOutputError") {
  console.error("Failed to produce structured output:", result.data.info.error.message)
  console.error("Attempts:", result.data.info.error.retries)
}
```

### Best Practices

1. **Provide clear descriptions** in your schema properties to help the model understand what data to extract
2. **Use `required`** to specify which fields must be present
3. **Keep schemas focused** - complex nested schemas may be harder for the model to fill correctly
4. **Set appropriate `retryCount`** - increase for complex schemas, decrease for simple ones

---

## APIs

The SDK exposes all server APIs through a type-safe client.

---

### Global

| Method            | Description                     | Response                             |
| ----------------- | ------------------------------- | ------------------------------------ |
| `global.health()` | Check server health and version | `{ healthy: true, version: string }` |

---

#### Examples

```javascript
const health = await client.global.health()
console.log(health.data.version)
```

---

### App

| Method         | Description               | Response                                    |
| -------------- | ------------------------- | ------------------------------------------- |
| `app.log()`    | Write a log entry         | `boolean`                                   |
| `app.agents()` | List all available agents | <a href={typesUrl}><code>Agent[]</code></a> |

---

#### Examples

```javascript
// Write a log entry
await client.app.log({
  body: {
    service: "my-app",
    level: "info",
    message: "Operation completed",
  },
})

// List available agents
const agents = await client.app.agents()
```

---

### Project

| Method              | Description         | Response                                      |
| ------------------- | ------------------- | --------------------------------------------- |
| `project.list()`    | List all projects   | <a href={typesUrl}><code>Project[]</code></a> |

---

#### Examples

```javascript
// List all projects
const projects = await client.project.list()

```

---

### Path

| Method       | Description      | Response                                 |
| ------------ | ---------------- | ---------------------------------------- |
| `path.get()` | Get current path | <a href={typesUrl}><code>Path</code></a> |

---

#### Examples

```javascript
// Get current path information
const pathInfo = await client.path.get()
```

---

### Config

| Method               | Description                       | Response                                                                                              |
| -------------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `config.get()`       | Get config info                   | <a href={typesUrl}><code>Config</code></a>                                                            |
| `config.providers()` | List providers and default models | `{ providers: `<a href={typesUrl}><code>Provider[]</code></a>`, default: { [key: string]: string } }` |

---

#### Examples

```javascript
const config = await client.config.get()

const { providers, default: defaults } = await client.config.providers()
```

---

### Sessions

| Method                                                     | Description                        | Notes                                                                                                                                                                                                                    |
| ---------------------------------------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `session.list()`                                           | List sessions                      | Returns <a href={typesUrl}><code>Session[]</code></a>                                                                                                                                                                    |
| `session.get({ path })`                                    | Get session                        | Returns <a href={typesUrl}><code>Session</code></a>                                                                                                                                                                      |
| `session.children({ path })`                               | List child sessions                | Returns <a href={typesUrl}><code>Session[]</code></a>                                                                                                                                                                    |
| `session.create({ body })`                                 | Create session                     | Returns <a href={typesUrl}><code>Session</code></a>                                                                                                                                                                      |
| `session.delete({ path })`                                 | Delete session                     | Returns `boolean`                                                                                                                                                                                                        |
| `session.update({ path, body })`                           | Update session properties          | Returns <a href={typesUrl}><code>Session</code></a>                                                                                                                                                                      |
| `session.init({ path, body })`                             | Analyze app and create `AGENTS.md` | Returns `boolean`                                                                                                                                                                                                        |
| `session.abort({ path })`                                  | Abort a running session            | Returns `boolean`                                                                                                                                                                                                        |
| `session.share({ path })`                                  | Share session                      | Returns <a href={typesUrl}><code>Session</code></a>                                                                                                                                                                      |
| `session.unshare({ path })`                                | Unshare session                    | Returns <a href={typesUrl}><code>Session</code></a>                                                                                                                                                                      |
| `session.summarize({ path, body })`                        | Summarize session                  | Returns `boolean`                                                                                                                                                                                                        |
| `session.messages({ path })`                               | List messages in a session         | Returns `{ info: `<a href={typesUrl}><code>Message</code></a>`, parts: `<a href={typesUrl}><code>Part[]</code></a>`}[]`                                                                                                  |
| `session.message({ path })`                                | Get message details                | Returns `{ info: `<a href={typesUrl}><code>Message</code></a>`, parts: `<a href={typesUrl}><code>Part[]</code></a>`}`                                                                                                    |
| `session.prompt({ path, body })`                           | Send prompt message                | `body.noReply: true` returns UserMessage (context only). Default returns <a href={typesUrl}><code>AssistantMessage</code></a> with AI response. Supports `body.outputFormat` for [structured output](#structured-output) |
| `session.command({ path, body })`                          | Send command to session            | Returns `{ info: `<a href={typesUrl}><code>AssistantMessage</code></a>`, parts: `<a href={typesUrl}><code>Part[]</code></a>`}`                                                                                           |
| `session.shell({ path, body })`                            | Run a shell command                | Returns <a href={typesUrl}><code>AssistantMessage</code></a>                                                                                                                                                             |
| `session.revert({ path, body })`                           | Revert a message                   | Returns <a href={typesUrl}><code>Session</code></a>                                                                                                                                                                      |
| `session.unrevert({ path })`                               | Restore reverted messages          | Returns <a href={typesUrl}><code>Session</code></a>                                                                                                                                                                      |
| `postSessionByIdPermissionsByPermissionId({ path, body })` | Respond to a permission request    | Returns `boolean`                                                                                                                                                                                                        |

---

#### Examples

```javascript
// Create and manage sessions
const session = await client.session.create({
  body: { title: "My session" },
})

const sessions = await client.session.list()

// Send a prompt message
const result = await client.session.prompt({
  path: { id: session.id },
  body: {
    model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" },
    parts: [{ type: "text", text: "Hello!" }],
  },
})

// Inject context without triggering AI response (useful for plugins)
await client.session.prompt({
  path: { id: session.id },
  body: {
    noReply: true,
    parts: [{ type: "text", text: "You are a helpful assistant." }],
  },
})
```

---

### Files

| Method                    | Description                        | Response                                                                                    |
| ------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------- |
| `find.text({ query })`    | Search for text in files           | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` |
| `find.files({ query })`   | Find files and directories by name | `string[]` (paths)                                                                          |
| `find.symbols({ query })` | Find workspace symbols             | <a href={typesUrl}><code>Symbol[]</code></a>                                                |
| `file.read({ query })`    | Read a file                        | `{ type: "raw" \| "patch", content: string }`                                               |
| `file.status({ query? })` | Get status for tracked files       | <a href={typesUrl}><code>File[]</code></a>                                                  |

`find.files` supports a few optional query fields:

- `type`: `"file"` or `"directory"`
- `directory`: override the project root for the search
- `limit`: max results (1–200)

---

#### Examples

```javascript
// Search and read files
const textResults = await client.find.text({
  query: { pattern: "function.*opencode" },
})

const files = await client.find.files({
  query: { query: "*.ts", type: "file" },
})

const directories = await client.find.files({
  query: { query: "packages", type: "directory", limit: 20 },
})

const content = await client.file.read({
  query: { path: "src/index.ts" },
})
```

---

### TUI

| Method                         | Description               | Response  |
| ------------------------------ | ------------------------- | --------- |
| `tui.appendPrompt({ body })`   | Append text to the prompt | `boolean` |
| `tui.openHelp()`               | Open the help dialog      | `boolean` |
| `tui.openSessions()`           | Open the session selector | `boolean` |
| `tui.openThemes()`             | Open the theme selector   | `boolean` |
| `tui.openModels()`             | Open the model selector   | `boolean` |
| `tui.submitPrompt()`           | Submit the current prompt | `boolean` |
| `tui.clearPrompt()`            | Clear the prompt          | `boolean` |
| `tui.executeCommand({ body })` | Execute a command         | `boolean` |
| `tui.showToast({ body })`      | Show toast notification   | `boolean` |

---

#### Examples

```javascript
// Control TUI interface
await client.tui.appendPrompt({
  body: { text: "Add this to prompt" },
})

await client.tui.showToast({
  body: { message: "Task completed", variant: "success" },
})
```

---

### Auth

| Method              | Description                    | Response  |
| ------------------- | ------------------------------ | --------- |
| `auth.set({ ... })` | Set authentication credentials | `boolean` |

---

#### Examples

```javascript
await client.auth.set({
  path: { id: "anthropic" },
  body: { type: "api", key: "your-api-key" },
})
```

---

### Events

| Method              | Description               | Response                  |
| ------------------- | ------------------------- | ------------------------- |
| `event.subscribe()` | Server-sent events stream | Server-sent events stream |

---

#### Examples

```javascript
// Listen to real-time events
const events = await client.event.subscribe()
for await (const event of events.stream) {
  console.log("Event:", event.type, event.properties)
}
```

---

### Packages Web Src Content Docs Server (`packages/web/src/content/docs/server.mdx`)

---
title: Server
description: Interact with opencode server over HTTP.
---

import config from "../../../config.mjs"
export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts`

The `opencode serve` command runs a headless HTTP server that exposes an OpenAPI endpoint that an opencode client can use.

---

### Usage

```bash
opencode serve [--port <number>] [--hostname <string>] [--cors <origin>]
```

#### Options

| Flag            | Description                         | Default          |
| --------------- | ----------------------------------- | ---------------- |
| `--port`        | Port to listen on                   | `4096`           |
| `--hostname`    | Hostname to listen on               | `127.0.0.1`      |
| `--mdns`        | Enable mDNS discovery               | `false`          |
| `--mdns-domain` | Custom domain name for mDNS service | `opencode.local` |
| `--cors`        | Additional browser origins to allow | `[]`             |

`--cors` can be passed multiple times:

```bash
opencode serve --cors http://localhost:5173 --cors https://app.example.com
```

---

### Authentication

Set `OPENCODE_SERVER_PASSWORD` to protect the server with HTTP basic auth. The username defaults to `opencode`, or set `OPENCODE_SERVER_USERNAME` to override it. This applies to both `opencode serve` and `opencode web`.

```bash
OPENCODE_SERVER_PASSWORD=your-password opencode serve
```

---

### How it works

When you run `opencode` it starts a TUI and a server. Where the TUI is the
client that talks to the server. The server exposes an OpenAPI 3.1 spec
endpoint. This endpoint is also used to generate an [SDK](/docs/sdk).

:::tip
Use the opencode server to interact with opencode programmatically.
:::

This architecture lets opencode support multiple clients and allows you to interact with opencode programmatically.

You can run `opencode serve` to start a standalone server. If you have the
opencode TUI running, `opencode serve` will start a new server.

---

#### Connect to an existing server

When you start the TUI it randomly assigns a port and hostname. You can instead pass in the `--hostname` and `--port` [flags](/docs/cli). Then use this to connect to its server.

The [`/tui`](#tui) endpoint can be used to drive the TUI through the server. For example, you can prefill or run a prompt. This setup is used by the OpenCode [IDE](/docs/ide) plugins.

---

## Spec

The server publishes an OpenAPI 3.1 spec that can be viewed at:

```
http://<hostname>:<port>/doc
```

For example, `http://localhost:4096/doc`. Use the spec to generate clients or inspect request and response types. Or view it in a Swagger explorer.

---

## APIs

The opencode server exposes the following APIs.

---

### Global

| Method | Path             | Description                    | Response                             |
| ------ | ---------------- | ------------------------------ | ------------------------------------ |
| `GET`  | `/global/health` | Get server health and version  | `{ healthy: true, version: string }` |
| `GET`  | `/global/event`  | Get global events (SSE stream) | Event stream                         |

---

### Project

| Method | Path               | Description             | Response                                      |
| ------ | ------------------ | ----------------------- | --------------------------------------------- |
| `GET`  | `/project`         | List all projects       | <a href={typesUrl}><code>Project[]</code></a> |
| `GET`  | `/project/current` | Get the current project | <a href={typesUrl}><code>Project</code></a>   |

---

### Path & VCS

| Method | Path    | Description                          | Response                                    |
| ------ | ------- | ------------------------------------ | ------------------------------------------- |
| `GET`  | `/path` | Get the current path                 | <a href={typesUrl}><code>Path</code></a>    |
| `GET`  | `/vcs`  | Get VCS info for the current project | <a href={typesUrl}><code>VcsInfo</code></a> |

---

### Instance

| Method | Path                | Description                  | Response  |
| ------ | ------------------- | ---------------------------- | --------- |
| `POST` | `/instance/dispose` | Dispose the current instance | `boolean` |

---

### Config

| Method  | Path                | Description                       | Response                                                                                 |
| ------- | ------------------- | --------------------------------- | ---------------------------------------------------------------------------------------- |
| `GET`   | `/config`           | Get config info                   | <a href={typesUrl}><code>Config</code></a>                                               |
| `PATCH` | `/config`           | Update config                     | <a href={typesUrl}><code>Config</code></a>                                               |
| `GET`   | `/config/providers` | List providers and default models | `{ providers: `<a href={typesUrl}>Provider[]</a>`, default: { [key: string]: string } }` |

---

### Provider

| Method | Path                             | Description                          | Response                                                                            |
| ------ | -------------------------------- | ------------------------------------ | ----------------------------------------------------------------------------------- |
| `GET`  | `/provider`                      | List all providers                   | `{ all: `<a href={typesUrl}>Provider[]</a>`, default: {...}, connected: string[] }` |
| `GET`  | `/provider/auth`                 | Get provider authentication methods  | `{ [providerID: string]: `<a href={typesUrl}>ProviderAuthMethod[]</a>` }`           |
| `POST` | `/provider/{id}/oauth/authorize` | Authorize a provider using OAuth     | <a href={typesUrl}><code>ProviderAuthAuthorization</code></a>                       |
| `POST` | `/provider/{id}/oauth/callback`  | Handle OAuth callback for a provider | `boolean`                                                                           |

---

### Sessions

| Method   | Path                                     | Description                           | Notes                                                                              |
| -------- | ---------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------- |
| `GET`    | `/session`                               | List all sessions                     | Returns <a href={typesUrl}><code>Session[]</code></a>                              |
| `POST`   | `/session`                               | Create a new session                  | body: `{ parentID?, title? }`, returns <a href={typesUrl}><code>Session</code></a> |
| `GET`    | `/session/status`                        | Get session status for all sessions   | Returns `{ [sessionID: string]: `<a href={typesUrl}>SessionStatus</a>` }`          |
| `GET`    | `/session/:id`                           | Get session details                   | Returns <a href={typesUrl}><code>Session</code></a>                                |
| `DELETE` | `/session/:id`                           | Delete a session and all its data     | Returns `boolean`                                                                  |
| `PATCH`  | `/session/:id`                           | Update session properties             | body: `{ title? }`, returns <a href={typesUrl}><code>Session</code></a>            |
| `GET`    | `/session/:id/children`                  | Get a session's child sessions        | Returns <a href={typesUrl}><code>Session[]</code></a>                              |
| `POST`   | `/session/:id/init`                      | Analyze app and create `AGENTS.md`    | body: `{ messageID, providerID, modelID }`, returns `boolean`                      |
| `POST`   | `/session/:id/fork`                      | Fork an existing session at a message | body: `{ messageID? }`, returns <a href={typesUrl}><code>Session</code></a>        |
| `POST`   | `/session/:id/abort`                     | Abort a running session               | Returns `boolean`                                                                  |
| `GET`    | `/session/:id/diff`                      | Get the diff for this session         | query: `messageID?`, returns <a href={typesUrl}><code>FileDiff[]</code></a>        |
| `POST`   | `/session/:id/summarize`                 | Summarize the session                 | body: `{ providerID, modelID }`, returns `boolean`                                 |
| `POST`   | `/session/:id/revert`                    | Revert a message                      | body: `{ messageID, partID? }`, returns `boolean`                                  |
| `POST`   | `/session/:id/unrevert`                  | Restore all reverted messages         | Returns `boolean`                                                                  |
| `POST`   | `/session/:id/permissions/:permissionID` | Respond to a permission request       | body: `{ response, remember? }`, returns `boolean`                                 |

---

### Messages

| Method | Path                              | Description                             | Notes                                                                                                                                                                 |
| ------ | --------------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET`  | `/session/:id/message`            | List messages in a session              | query: `limit?`, returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}[]`                                                        |
| `POST` | `/session/:id/message`            | Send a message and wait for response    | body: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}` |
| `GET`  | `/session/:id/message/:messageID` | Get message details                     | Returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}`                                                                           |
| `POST` | `/session/:id/prompt_async`       | Send a message asynchronously (no wait) | body: same as `/session/:id/message`, returns `204 No Content`                                                                                                        |
| `POST` | `/session/:id/command`            | Execute a slash command                 | body: `{ messageID?, agent?, model?, command, arguments }`, returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}`               |
| `POST` | `/session/:id/shell`              | Run a shell command                     | body: `{ agent, model?, command }`, returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}`                                       |

---

### Commands

| Method | Path       | Description       | Response                                      |
| ------ | ---------- | ----------------- | --------------------------------------------- |
| `GET`  | `/command` | List all commands | <a href={typesUrl}><code>Command[]</code></a> |

---

### Files

| Method | Path                     | Description                        | Response                                                                                    |
| ------ | ------------------------ | ---------------------------------- | ------------------------------------------------------------------------------------------- |
| `GET`  | `/find?pattern=<pat>`    | Search for text in files           | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` |
| `GET`  | `/find/file?query=<q>`   | Find files and directories by name | `string[]` (paths)                                                                          |
| `GET`  | `/find/symbol?query=<q>` | Find workspace symbols             | <a href={typesUrl}><code>Symbol[]</code></a>                                                |
| `GET`  | `/file?path=<path>`      | List files and directories         | <a href={typesUrl}><code>FileNode[]</code></a>                                              |
| `GET`  | `/file/content?path=<p>` | Read a file                        | <a href={typesUrl}><code>FileContent</code></a>                                             |
| `GET`  | `/file/status`           | Get status for tracked files       | <a href={typesUrl}><code>File[]</code></a>                                                  |

#### `/find/file` query parameters

- `query` (required) — search string (fuzzy match)
- `type` (optional) — limit results to `"file"` or `"directory"`
- `directory` (optional) — override the project root for the search
- `limit` (optional) — max results (1–200)
- `dirs` (optional) — legacy flag (`"false"` returns only files)

---

### Tools (Experimental)

| Method | Path                                        | Description                              | Response                                     |
| ------ | ------------------------------------------- | ---------------------------------------- | -------------------------------------------- |
| `GET`  | `/experimental/tool/ids`                    | List all tool IDs                        | <a href={typesUrl}><code>ToolIDs</code></a>  |
| `GET`  | `/experimental/tool?provider=<p>&model=<m>` | List tools with JSON schemas for a model | <a href={typesUrl}><code>ToolList</code></a> |

---

### LSP, Formatters & MCP

| Method | Path         | Description                | Response                                                 |
| ------ | ------------ | -------------------------- | -------------------------------------------------------- |
| `GET`  | `/lsp`       | Get LSP server status      | <a href={typesUrl}><code>LSPStatus[]</code></a>          |
| `GET`  | `/formatter` | Get formatter status       | <a href={typesUrl}><code>FormatterStatus[]</code></a>    |
| `GET`  | `/mcp`       | Get MCP server status      | `{ [name: string]: `<a href={typesUrl}>MCPStatus</a>` }` |
| `POST` | `/mcp`       | Add MCP server dynamically | body: `{ name, config }`, returns MCP status object      |

---

### Agents

| Method | Path     | Description               | Response                                    |
| ------ | -------- | ------------------------- | ------------------------------------------- |
| `GET`  | `/agent` | List all available agents | <a href={typesUrl}><code>Agent[]</code></a> |

---

### Logging

| Method | Path   | Description                                                  | Response  |
| ------ | ------ | ------------------------------------------------------------ | --------- |
| `POST` | `/log` | Write log entry. Body: `{ service, level, message, extra? }` | `boolean` |

---

### TUI

| Method | Path                    | Description                                 | Response               |
| ------ | ----------------------- | ------------------------------------------- | ---------------------- |
| `POST` | `/tui/append-prompt`    | Append text to the prompt                   | `boolean`              |
| `POST` | `/tui/open-help`        | Open the help dialog                        | `boolean`              |
| `POST` | `/tui/open-sessions`    | Open the session selector                   | `boolean`              |
| `POST` | `/tui/open-themes`      | Open the theme selector                     | `boolean`              |
| `POST` | `/tui/open-models`      | Open the model selector                     | `boolean`              |
| `POST` | `/tui/submit-prompt`    | Submit the current prompt                   | `boolean`              |
| `POST` | `/tui/clear-prompt`     | Clear the prompt                            | `boolean`              |
| `POST` | `/tui/execute-command`  | Execute a command (`{ command }`)           | `boolean`              |
| `POST` | `/tui/show-toast`       | Show toast (`{ title?, message, variant }`) | `boolean`              |
| `GET`  | `/tui/control/next`     | Wait for the next control request           | Control request object |
| `POST` | `/tui/control/response` | Respond to a control request (`{ body }`)   | `boolean`              |

---

### Auth

| Method | Path        | Description                                                     | Response  |
| ------ | ----------- | --------------------------------------------------------------- | --------- |
| `PUT`  | `/auth/:id` | Set authentication credentials. Body must match provider schema | `boolean` |

---

### Events

| Method | Path     | Description                                                                   | Response                  |
| ------ | -------- | ----------------------------------------------------------------------------- | ------------------------- |
| `GET`  | `/event` | Server-sent events stream. First event is `server.connected`, then bus events | Server-sent events stream |

---

### Docs

| Method | Path   | Description               | Response                    |
| ------ | ------ | ------------------------- | --------------------------- |
| `GET`  | `/doc` | OpenAPI 3.1 specification | HTML page with OpenAPI spec |

---

### Packages Web Src Content Docs Skills (`packages/web/src/content/docs/skills.mdx`)

---
title: "Agent Skills"
description: "Define reusable behavior via SKILL.md definitions"
---

Agent skills let OpenCode discover reusable instructions from your repo or home directory.
Skills are loaded on-demand via the native `skill` tool—agents see available skills and can load the full content when needed.

---

## Place files

Create one folder per skill name and put a `SKILL.md` inside it.
OpenCode searches these locations:

- Project config: `.opencode/skills/<name>/SKILL.md`
- Global config: `~/.config/opencode/skills/<name>/SKILL.md`
- Project Claude-compatible: `.claude/skills/<name>/SKILL.md`
- Global Claude-compatible: `~/.claude/skills/<name>/SKILL.md`
- Project agent-compatible: `.agents/skills/<name>/SKILL.md`
- Global agent-compatible: `~/.agents/skills/<name>/SKILL.md`

---

## Understand discovery

For project-local paths, OpenCode walks up from your current working directory until it reaches the git worktree.
It loads any matching `skills/*/SKILL.md` in `.opencode/` and any matching `.claude/skills/*/SKILL.md` or `.agents/skills/*/SKILL.md` along the way.

Global definitions are also loaded from `~/.config/opencode/skills/*/SKILL.md`, `~/.claude/skills/*/SKILL.md`, and `~/.agents/skills/*/SKILL.md`.

---

## Write frontmatter

Each `SKILL.md` must start with YAML frontmatter.
Use these Agent Skills fields:

- `name` (required)
- `description` (required)
- `license` (optional)
- `compatibility` (optional)
- `metadata` (optional, string-to-string map)

Put OpenCode-specific behavior in `metadata` instead of adding custom top-level fields.

OpenCode recognizes these optional `metadata` keys:

- `opencode/slash`: set to `"true"` to expose the skill as a `/name` command in the TUI
- `opencode/autoinvoke`: set to `"false"` to keep the skill out of model-facing auto-selection guidance

The Agent Skills spec defines `metadata` values as strings, so quoted values are the portable form.
OpenCode also accepts YAML booleans like `opencode/slash: true` and `opencode/autoinvoke: false`.

---

## Validate names

`name` must:

- Be 1–64 characters
- Be lowercase alphanumeric with single hyphen separators
- Not start or end with `-`
- Not contain consecutive `--`
- Match the directory name that contains `SKILL.md`

Equivalent regex:

```text
^[a-z0-9]+(-[a-z0-9]+)*$
```

---

## Follow length rules

`description` must be 1-1024 characters.
Keep it specific enough for the agent to choose correctly.

---

## Use an example

Create `.opencode/skills/git-release/SKILL.md` like this:

```markdown
---
name: git-release
description: Create consistent releases and changelogs
license: MIT
compatibility: opencode
metadata:
  audience: maintainers
  workflow: github
  opencode/slash: "true"
  opencode/autoinvoke: "false"
---

## What I do

- Draft release notes from merged PRs
- Propose a version bump
- Provide a copy-pasteable `gh release create` command

## When to use me

Use this when you are preparing a tagged release.
Ask clarifying questions if the target versioning scheme is unclear.
```

---

## Recognize tool description

OpenCode lists available skills in the `skill` tool description.
Each entry includes the skill name and description:

```xml
<available_skills>
  <skill>
    <name>git-release</name>
    <description>Create consistent releases and changelogs</description>
  </skill>
</available_skills>
```

The agent loads a skill by calling the tool:

```
skill({ name: "git-release" })
```

Skills with `metadata["opencode/autoinvoke"]` set to `"false"` are not included in `<available_skills>`.
They can still be selected manually and loaded by exact name.

---

## Configure permissions

Control which skills agents can access using pattern-based permissions in `opencode.json`:

```json
{
  "permission": {
    "skill": {
      "*": "allow",
      "pr-review": "allow",
      "internal-*": "deny",
      "experimental-*": "ask"
    }
  }
}
```

| Permission | Behavior                                  |
| ---------- | ----------------------------------------- |
| `allow`    | Skill loads immediately                   |
| `deny`     | Skill hidden from agent, access rejected  |
| `ask`      | User prompted for approval before loading |

Patterns support wildcards: `internal-*` matches `internal-docs`, `internal-tools`, etc.

---

## Override per agent

Give specific agents different permissions than the global defaults.

**For custom agents** (in agent frontmatter):

```yaml
---
permission:
  skill:
    "documents-*": "allow"
---
```

**For built-in agents** (in `opencode.json`):

```json
{
  "agent": {
    "plan": {
      "permission": {
        "skill": {
          "internal-*": "allow"
        }
      }
    }
  }
}
```

---

## Disable the skill tool

Completely disable skills for agents that shouldn't use them:

**For custom agents**:

```yaml
---
tools:
  skill: false
---
```

**For built-in agents**:

```json
{
  "agent": {
    "plan": {
      "tools": {
        "skill": false
      }
    }
  }
}
```

When disabled, the `<available_skills>` section is omitted entirely.

---

## Troubleshoot loading

If a skill does not show up:

1. Verify `SKILL.md` is spelled in all caps
2. Check that frontmatter includes `name` and `description`
3. Ensure skill names are unique across all locations
4. Check permissions—skills with `deny` are hidden from agents
5. Check `metadata["opencode/autoinvoke"]`—skills set to `"false"` are hidden from model-facing guidance

---

### Packages Web Src Content Docs Themes (`packages/web/src/content/docs/themes.mdx`)

---
title: Themes
description: Select a built-in theme or define your own.
---

With OpenCode you can select from one of several built-in themes, use a theme that adapts to your terminal theme, or define your own custom theme.

By default, OpenCode uses our own `opencode` theme.

---

## Terminal requirements

For themes to display correctly with their full color palette, your terminal must support **truecolor** (24-bit color). Most modern terminals support this by default, but you may need to enable it:

- **Check support**: Run `echo $COLORTERM` - it should output `truecolor` or `24bit`
- **Enable truecolor**: Set the environment variable `COLORTERM=truecolor` in your shell profile
- **Terminal compatibility**: Ensure your terminal emulator supports 24-bit color (most modern terminals like iTerm2, Alacritty, Kitty, Windows Terminal, and recent versions of GNOME Terminal do)

Without truecolor support, themes may appear with reduced color accuracy or fall back to the nearest 256-color approximation.

---

## Built-in themes

OpenCode comes with several built-in themes.

| Name                   | Description                                                                  |
| ---------------------- | ---------------------------------------------------------------------------- |
| `system`               | Adapts to your terminal’s background color                                   |
| `tokyonight`           | Based on the [Tokyonight](https://github.com/folke/tokyonight.nvim) theme    |
| `everforest`           | Based on the [Everforest](https://github.com/sainnhe/everforest) theme       |
| `ayu`                  | Based on the [Ayu](https://github.com/ayu-theme) dark theme                  |
| `catppuccin`           | Based on the [Catppuccin](https://github.com/catppuccin) theme               |
| `catppuccin-macchiato` | Based on the [Catppuccin](https://github.com/catppuccin) theme               |
| `gruvbox`              | Based on the [Gruvbox](https://github.com/morhetz/gruvbox) theme             |
| `kanagawa`             | Based on the [Kanagawa](https://github.com/rebelot/kanagawa.nvim) theme      |
| `nord`                 | Based on the [Nord](https://github.com/nordtheme/nord) theme                 |
| `matrix`               | Hacker-style green on black theme                                            |
| `one-dark`             | Based on the [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) Dark theme |

And more, we are constantly adding new themes.

---

## System theme

The `system` theme is designed to automatically adapt to your terminal's color scheme. Unlike traditional themes that use fixed colors, the _system_ theme:

- **Generates gray scale**: Creates a custom gray scale based on your terminal's background color, ensuring optimal contrast.
- **Uses ANSI colors**: Leverages standard ANSI colors (0-15) for syntax highlighting and UI elements, which respect your terminal's color palette.
- **Preserves terminal defaults**: Uses `none` for text and background colors to maintain your terminal's native appearance.

The system theme is for users who:

- Want OpenCode to match their terminal's appearance
- Use custom terminal color schemes
- Prefer a consistent look across all terminal applications

---

## Using a theme

You can select a theme by bringing up the theme select with the `/theme` command. Or you can specify it in `tui.json`.

```json title="tui.json" {3}
{
  "$schema": "https://opencode.ai/tui.json",
  "theme": "tokyonight"
}
```

---

## Custom themes

OpenCode supports a flexible JSON-based theme system that allows users to create and customize themes easily.

---

### Hierarchy

Themes are loaded from multiple directories in the following order where later directories override earlier ones:

1. **Built-in themes** - These are embedded in the binary
2. **User config directory** - Defined in `~/.config/opencode/themes/*.json` or `$XDG_CONFIG_HOME/opencode/themes/*.json`
3. **Project root directory** - Defined in the `<project-root>/.opencode/themes/*.json`
4. **Current working directory** - Defined in `./.opencode/themes/*.json`

If multiple directories contain a theme with the same name, the theme from the directory with higher priority will be used.

---

### Creating a theme

To create a custom theme, create a JSON file in one of the theme directories.

For user-wide themes:

```bash no-frame
mkdir -p ~/.config/opencode/themes
vim ~/.config/opencode/themes/my-theme.json
```

And for project-specific themes.

```bash no-frame
mkdir -p .opencode/themes
vim .opencode/themes/my-theme.json
```

---

### JSON format

Themes use a flexible JSON format with support for:

- **Hex colors**: `"#ffffff"`
- **ANSI colors**: `3` (0-255)
- **Color references**: `"primary"` or custom definitions
- **Dark/light variants**: `{"dark": "#000", "light": "#fff"}`
- **No color**: `"none"` - Uses the terminal's default color or transparent

---

### Color definitions

The `defs` section is optional and it allows you to define reusable colors that can be referenced in the theme.

---

### Terminal defaults

The special value `"none"` can be used for any color to inherit the terminal's default color. This is particularly useful for creating themes that blend seamlessly with your terminal's color scheme:

- `"text": "none"` - Uses terminal's default foreground color
- `"background": "none"` - Uses terminal's default background color

---

### Example

Here's an example of a custom theme:

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Packages Web Src Content Docs Tools (`packages/web/src/content/docs/tools.mdx`)

---
title: Tools
description: Manage the tools an LLM can use.
---

Tools allow the LLM to perform actions in your codebase. OpenCode comes with a set of built-in tools, but you can extend it with [custom tools](/docs/custom-tools) or [MCP servers](/docs/mcp-servers).

By default, all tools are **enabled** and don't need permission to run. You can control tool behavior through [permissions](/docs/permissions).

---

## Configure

Use the `permission` field to control tool behavior. You can allow, deny, or require approval for each tool.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "edit": "deny",
    "shell": "ask",
    "webfetch": "allow"
  }
}
```

You can also use wildcards to control multiple tools at once. For example, to require approval for all tools from an MCP server:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "mymcp_*": "ask"
  }
}
```

[Learn more](/docs/permissions) about configuring permissions.

---

## Built-in

Here are all the built-in tools available in OpenCode.

---

### shell

Execute shell commands in your project environment.

```json title="opencode.json" {4}
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "shell": "allow"
  }
}
```

This tool allows the LLM to run terminal commands like `npm install`, `git status`, or any other shell command.

---

### edit

Modify existing files using exact string replacements.

```json title="opencode.json" {4}
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "edit": "allow"
  }
}
```

This tool performs precise edits to files by replacing exact text matches. It's the primary way the LLM modifies code.

---

### write

Create new files or overwrite existing ones.

```json title="opencode.json" {4}
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "edit": "allow"
  }
}
```

Use this to allow the LLM to create new files. It will overwrite existing files if they already exist.

:::note
The `write` tool is controlled by the `edit` permission, which covers all file modifications (`edit`, `write`, `apply_patch`).
:::

---

### read

Read file contents from your codebase.

```json title="opencode.json" {4}
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "read": "allow"
  }
}
```

This tool reads files and returns their contents. It supports reading specific line ranges for large files.

---

### grep

Search file contents using regular expressions.

```json title="opencode.json" {4}
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "grep": "allow"
  }
}
```

Fast content search across your codebase. Supports full regex syntax and file pattern filtering.

---

### glob

Find files by pattern matching.

```json title="opencode.json" {4}
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "glob": "allow"
  }
}
```

Search for files using glob patterns like `**/*.js` or `src/**/*.ts`. Returns matching file paths sorted by modification time.

---

### lsp (experimental)

Interact with your configured LSP servers to get code intelligence features like definitions, references, hover info, and call hierarchy.

:::note
This tool is only available when `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (or `OPENCODE_EXPERIMENTAL=true`).
:::

```json title="opencode.json" {4}
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "lsp": "allow"
  }
}
```

Supported operations include `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls`, and `outgoingCalls`.

To configure which LSP servers are available for your project, see [LSP Servers](/docs/lsp).

---

### apply_patch

Apply patches to files.

```json title="opencode.json" {4}
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "edit": "allow"
  }
}
```

This tool applies patch files to your codebase. Useful for applying diffs and patches from various sources.

When handling `tool.execute.before` or `tool.execute.after` hooks, check `input.tool === "apply_patch"` (not `"patch"`).

`apply_patch` uses `output.args.patchText` instead of `output.args.filePath`. Paths are embedded in marker lines within `patchText` and are relative to the project root (for example: `*** Add File: src/new-file.ts`, `*** Update File: src/existing.ts`, `*** Move to: src/renamed.ts`, `*** Delete File: src/obsolete.ts`).

:::note
The `apply_patch` tool is controlled by the `edit` permission, which covers all file modifications (`edit`, `write`, `apply_patch`).
:::

---

### skill

Load a [skill](/docs/skills) (a `SKILL.md` file) and return its content in the conversation.

```json title="opencode.json" {4}
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "skill": "allow"
  }
}
```

---

### webfetch

Fetch web content.

```json title="opencode.json" {4}
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "webfetch": "allow"
  }
}
```

Allows the LLM to fetch and read web pages. Useful for looking up documentation or researching online resources.

---

### websearch

Search the web for information.

:::note
This tool is only available when using the OpenCode or OpenCode Go provider, or when either the `OPENCODE_ENABLE_EXA` or `OPENCODE_ENABLE_PARALLEL` environment variable is set to any truthy value (e.g., `true` or `1`).

To enable when launching OpenCode:

```bash
OPENCODE_ENABLE_EXA=1 opencode
# or
OPENCODE_ENABLE_PARALLEL=1 opencode
```

:::

```json title="opencode.json" {4}
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "websearch": "allow"
  }
}
```

Performs web searches using Exa or Parallel to find relevant information online. Useful for researching topics, finding current events, or gathering information beyond the training data cutoff.

No API key is required — the tool connects directly to the backend's hosted MCP service without authentication.

:::tip
Use `websearch` when you need to find information (discovery), and `webfetch` when you need to retrieve content from a specific URL (retrieval).
:::

---

### question

Ask the user questions during execution.

```json title="opencode.json" {4}
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "question": "allow"
  }
}
```

This tool allows the LLM to ask the user questions during a task. It's useful for:

- Gathering user preferences or requirements
- Clarifying ambiguous instructions
- Getting decisions on implementation choices
- Offering choices about what direction to take

Each question includes a header, the question text, and a list of options. Users can select from the provided options or type a custom answer. When there are multiple questions, users can navigate between them before submitting all answers.

---

## Custom tools

Custom tools let you define your own functions that the LLM can call. These are defined in your config file and can execute arbitrary code.

[Learn more](/docs/custom-tools) about creating custom tools.

---

## MCP servers

MCP (Model Context Protocol) servers allow you to integrate external tools and services. This includes database access, API integrations, and third-party services.

[Learn more](/docs/mcp-servers) about configuring MCP servers.

---

## Internals

Internally, tools like `grep` and `glob` use [ripgrep](https://github.com/BurntSushi/ripgrep) under the hood. By default, ripgrep respects `.gitignore` patterns, which means files and directories listed in your `.gitignore` will be excluded from searches and listings.

---

### Ignore patterns

To include files that would normally be ignored, create a `.ignore` file in your project root. This file can explicitly allow certain paths.

```text title=".ignore"
!node_modules/
!dist/
!build/
```

For example, this `.ignore` file allows ripgrep to search within `node_modules/`, `dist/`, and `build/` directories even if they're listed in `.gitignore`.

---

### Packages Web Src Content Docs Troubleshooting (`packages/web/src/content/docs/troubleshooting.mdx`)

---
title: Troubleshooting
description: Common issues and how to resolve them.
---

To debug issues with OpenCode, start by checking the logs and local data it stores on disk.

---

## Logs

Log files are written to:

- **macOS/Linux**: `~/.local/share/opencode/log/`
- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.local\share\opencode\log`

Log files are named with timestamps (e.g., `2025-01-09T123456.log`) and the most recent 10 log files are kept.

You can set the log level with the `--log-level` command-line option to get more detailed debug information. For example, `opencode --log-level DEBUG`.

---

## Storage

opencode stores session data and other application data on disk at:

- **macOS/Linux**: `~/.local/share/opencode/`
- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.local\share\opencode`

This directory contains:

- `auth.json` - Authentication data like API keys, OAuth tokens
- `log/` - Application logs
- `project/` - Project-specific data like session and message data
  - If the project is within a Git repo, it is stored in `./<project-slug>/storage/`
  - If it is not a Git repo, it is stored in `./global/storage/`

---

## Uninstall

To uninstall the OpenCode CLI and remove its related files, run:

```bash
opencode uninstall
```

The command shows what will be removed and asks for confirmation. See the [CLI reference](/docs/cli#uninstall) for options to keep your configuration or application data.

To remove OpenCode Desktop, uninstall the application through your operating system's app management tools.

---

## Desktop app

OpenCode Desktop runs a local OpenCode server (the `opencode-cli` sidecar) in the background. Most issues are caused by a misbehaving plugin, a corrupted cache, or a bad server setting.

### Quick checks

- Fully quit and relaunch the app.
- If the app shows an error screen, click **Restart** and copy the error details.
- macOS only: `OpenCode` menu -> **Reload Webview** (helps if the UI is blank/frozen).

---

### Disable plugins

If the desktop app is crashing on launch, hanging, or behaving strangely, start by disabling plugins.

#### Check the global config

Open your global config file and look for a `plugin` key.

- **macOS/Linux**: `~/.config/opencode/opencode.jsonc` (or `~/.config/opencode/opencode.json`)
- **macOS/Linux** (older installs): `~/.local/share/opencode/opencode.jsonc`
- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.config\opencode\opencode.jsonc`

If you have plugins configured, temporarily disable them by removing the key or setting it to an empty array:

```jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "plugin": [],
}
```

#### Check plugin directories

OpenCode can also load local plugins from disk. Temporarily move these out of the way (or rename the folder) and restart the desktop app:

- **Global plugins**
  - **macOS/Linux**: `~/.config/opencode/plugins/`
  - **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.config\opencode\plugins`
- **Project plugins** (only if you use per-project config)
  - `<your-project>/.opencode/plugins/`

If the app starts working again, re-enable plugins one at a time to find which one is causing the issue.

---

### Clear the cache

If disabling plugins doesn't help (or a plugin install is stuck), clear the cache so OpenCode can rebuild it.

1. Quit OpenCode Desktop completely.
2. Delete the cache directory:

- **macOS**: Finder -> `Cmd+Shift+G` -> paste `~/.cache/opencode`
- **Linux**: delete `~/.cache/opencode` (or run `rm -rf ~/.cache/opencode`)
- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.cache\opencode`

3. Restart OpenCode Desktop.

---

### Fix server connection issues

OpenCode Desktop can either start its own local server (default) or connect to a server URL you configured.

If you see a **"Connection Failed"** dialog (or the app never gets past the splash screen), check for a custom server URL.

#### Clear the desktop default server URL

From the Home screen, click the server name (with the status dot) to open the Server picker. In the **Default server** section, click **Clear**.

#### Remove `server.port` / `server.hostname` from your config

If your `opencode.json(c)` contains a `server` section, temporarily remove it and restart the desktop app.

#### Check environment variables

If you have `OPENCODE_PORT` set in your environment, the desktop app will try to use that port for the local server.

- Unset `OPENCODE_PORT` (or pick a free port) and restart.

---

### Linux: Wayland / X11 issues

On Linux, some Wayland setups can cause blank windows or compositor errors.

- If you're on Wayland and the app is blank/crashing, try launching with `OC_ALLOW_WAYLAND=1`.
- If that makes things worse, remove it and try launching under an X11 session instead.

---

### Windows: WebView2 runtime

On Windows, OpenCode Desktop requires the Microsoft Edge **WebView2 Runtime**. If the app opens to a blank window or won't start, install/update WebView2 and try again.

---

### Windows: General performance issues

If you're experiencing slow performance, file access issues, or terminal problems on Windows, try using [WSL (Windows Subsystem for Linux)](/docs/windows-wsl). WSL provides a Linux environment that works more seamlessly with OpenCode's features.

---

### Notifications not showing

OpenCode Desktop only shows system notifications when:

- notifications are enabled for OpenCode in your OS settings, and
- the app window is not focused.

---

### Reset desktop app storage (last resort)

If the app won't start and you can't clear settings from inside the UI, reset the desktop app's saved state.

1. Quit OpenCode Desktop.
2. Find and delete these files (they live in the OpenCode Desktop app data directory):

- `opencode.settings.dat` (desktop default server URL)
- `opencode.global.dat` and `opencode.workspace.*.dat` (UI state like recent servers/projects)

To find the directory quickly:

- **macOS**: Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (then search for the filenames above)
- **Linux**: search under `~/.local/share` for the filenames above
- **Windows**: Press `WIN+R` -> `%APPDATA%` (then search for the filenames above)

---

## Getting help

If you're experiencing issues with OpenCode:

1. **Report issues on GitHub**

   The best way to report bugs or request features is through our GitHub repository:

   [**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues)

   Before creating a new issue, search existing issues to see if your problem has already been reported.

2. **Join our Discord**

   For real-time help and community discussion, join our Discord server:

   [**opencode.ai/discord**](https://opencode.ai/discord)

---

## Common issues

Here are some common issues and how to resolve them.

---

### OpenCode won't start

1. Check the logs for error messages
2. Try running with `--print-logs` to see output in the terminal
3. Ensure you have the latest version with `opencode upgrade`

---

### Authentication issues

1. Try re-authenticating with the `/connect` command in the TUI
2. Check that your API keys are valid
3. Ensure your network allows connections to the provider's API

---

### Model not available

1. Check that you've authenticated with the provider
2. Verify the model name in your config is correct
3. Some models may require specific access or subscriptions

If you encounter `ProviderModelNotFoundError` you are most likely incorrectly
referencing a model somewhere.
Models should be referenced like so: `<providerId>/<modelId>`

Examples:

- `openai/gpt-4.1`
- `openrouter/google/gemini-2.5-flash`
- `opencode/kimi-k2`

To figure out what models you have access to, run `opencode models`

---

### ProviderInitError

If you encounter a ProviderInitError, you likely have an invalid or corrupted configuration.

To resolve this:

1. First, verify your provider is set up correctly by following the [providers guide](/docs/providers)
2. If the issue persists, try clearing your stored configuration:

   ```bash
   rm -rf ~/.local/share/opencode
   ```

   On Windows, press `WIN+R` and delete: `%USERPROFILE%\.local\share\opencode`

3. Re-authenticate with your provider using the `/connect` command in the TUI.

---

### AI_APICallError and provider package issues

If you encounter API call errors, this may be due to outdated provider packages. opencode dynamically installs provider packages (OpenAI, Anthropic, Google, etc.) as needed and caches them locally.

To resolve provider package issues:

1. Clear the provider package cache:

   ```bash
   rm -rf ~/.cache/opencode
   ```

   On Windows, press `WIN+R` and delete: `%USERPROFILE%\.cache\opencode`

2. Restart opencode to reinstall the latest provider packages

This will force opencode to download the most recent versions of provider packages, which often resolves compatibility issues with model parameters and API changes.

---

### Copy/paste not working on Linux

Linux users need to have one of the following clipboard utilities installed for copy/paste functionality to work:

**For X11 systems:**

```bash
apt install -y xclip
# or
apt install -y xsel
```

**For Wayland systems:**

```bash
apt install -y wl-clipboard
```

**For headless environments:**

```bash
apt install -y xvfb
# and run:
Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
export DISPLAY=:99.0
```

opencode will detect if you're using Wayland and prefer `wl-clipboard`, otherwise it will try to find clipboard tools in order of: `xclip` and `xsel`.

---

### Packages Web Src Content Docs Tui (`packages/web/src/content/docs/tui.mdx`)

---
title: TUI
description: Using the OpenCode terminal user interface.
---

import { Tabs, TabItem } from "@astrojs/starlight/components"

OpenCode provides an interactive terminal interface or TUI for working on your projects with an LLM.

Running OpenCode starts the TUI for the current directory.

```bash
opencode
```

Or you can start it for a specific working directory.

```bash
opencode /path/to/project
```

Once you're in the TUI, you can prompt it with a message.

```text
Give me a quick summary of the codebase.
```

---

## File references

You can reference files in your messages using `@`. This does a fuzzy file search in the current working directory.

:::tip
You can also use `@` to reference files in your messages.
:::

```text "@packages/functions/src/api/index.ts"
How is auth handled in @packages/functions/src/api/index.ts?
```

The content of the file is added to the conversation automatically.

Configured [references](/docs/references) also appear in `@` autocomplete. Type `@alias` to add the reference root as context, or type `@alias/` to autocomplete files inside that reference.

```text "@docs/README.md"
Compare our setup with @docs/README.md
```

---

## Shell commands

Start a message with `!` to run a shell command.

```bash frame="none"
!ls -la
```

The output of the command is added to the conversation as a tool result.

---

## Commands

When using the OpenCode TUI, you can type `/` followed by a command name to quickly execute actions. For example:

```bash frame="none"
/help
```

Most commands also have keyboard shortcuts using `ctrl+x` as the default leader key. [Learn more](/docs/keybinds).

Here are all available slash commands:

---

### connect

Add a provider to OpenCode. Allows you to select from available providers and add their API keys.

```bash frame="none"
/connect
```

---

### compact

Compact the current session. _Alias_: `/summarize`

```bash frame="none"
/compact
```

**Keybind:** `ctrl+x c`

---

### details

Toggle tool execution details.

```bash frame="none"
/details
```

---

### editor

Open external editor for composing messages. Uses the editor set in your `EDITOR` environment variable. [Learn more](#editor-setup).

```bash frame="none"
/editor
```

**Keybind:** `ctrl+x e`

---

### exit

Exit OpenCode. _Aliases_: `/quit`, `/q`

```bash frame="none"
/exit
```

**Keybind:** `ctrl+x q`

---

### export

Export current conversation to Markdown and open in your default editor. Uses the editor set in your `EDITOR` environment variable. [Learn more](#editor-setup).

```bash frame="none"
/export
```

**Keybind:** `ctrl+x x`

---

### help

Show the help dialog.

```bash frame="none"
/help
```

---

### init

Guided setup for creating or updating `AGENTS.md`. [Learn more](/docs/rules).

```bash frame="none"
/init
```

---

### models

List available models.

```bash frame="none"
/models
```

**Keybind:** `ctrl+x m`

---

### new

Start a new session. _Alias_: `/clear`

```bash frame="none"
/new
```

**Keybind:** `ctrl+x n`

---

### redo

Redo a previously undone message. Only available after using `/undo`.

:::tip
Any file changes will also be restored.
:::

Internally, this uses Git to manage the file changes. So your project **needs to
be a Git repository**.

```bash frame="none"
/redo
```

**Keybind:** `ctrl+x r`

---

### sessions

List and switch between sessions. _Aliases_: `/resume`, `/continue`

```bash frame="none"
/sessions
```

**Keybind:** `ctrl+x l`

---

### themes

List available themes.

```bash frame="none"
/themes
```

**Keybind:** `ctrl+x t`

---

### thinking

Toggle the visibility of thinking/reasoning blocks in the conversation. When enabled, you can see the model's reasoning process for models that support extended thinking.

:::note
This command only controls whether thinking blocks are **displayed** - it does not enable or disable the model's reasoning capabilities. To toggle actual reasoning capabilities, use `ctrl+t` to cycle through model variants.
:::

```bash frame="none"
/thinking
```

---

### undo

Undo last message in the conversation. Removes the most recent user message, all subsequent responses, and any file changes.

:::tip
Any file changes made will also be reverted.
:::

Internally, this uses Git to manage the file changes. So your project **needs to
be a Git repository**.

```bash frame="none"
/undo
```

**Keybind:** `ctrl+x u`

---

## Editor setup

Both the `/editor` and `/export` commands use the editor specified in your `EDITOR` environment variable.

<Tabs>
  <TabItem label="Linux/macOS">
    ```bash
    # Example for nano or vim
    export EDITOR=nano
    export EDITOR=vim

    # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc.
    # include --wait
    export EDITOR="code --wait"
    ```

    To make it permanent, add this to your shell profile;
    `~/.bashrc`, `~/.zshrc`, etc.

  </TabItem>

  <TabItem label="Windows (CMD)">
    ```bash
    set EDITOR=notepad

    # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc.
    # include --wait
    set EDITOR=code --wait
    ```

    To make it permanent, use **System Properties** > **Environment
    Variables**.

  </TabItem>

  <TabItem label="Windows (PowerShell)">
    ```powershell
    $env:EDITOR = "notepad"

    # For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc.
    # include --wait
    $env:EDITOR = "code --wait"
    ```

    To make it permanent, add this to your PowerShell profile.

  </TabItem>
</Tabs>

Popular editor options include:

- `code` - Visual Studio Code
- `cursor` - Cursor
- `windsurf` - Windsurf
- `nvim` - Neovim editor
- `vim` - Vim editor
- `nano` - Nano editor
- `notepad` - Windows Notepad
- `subl` - Sublime Text

:::note
Some editors like VS Code need to be started with the `--wait` flag.
:::

Some editors need command-line arguments to run in blocking mode. The `--wait` flag makes the editor process block until closed.

---

## Configure

You can customize TUI behavior through `tui.json` (or `tui.jsonc`).

```json title="tui.json"
{
  "$schema": "https://opencode.ai/tui.json",
  "theme": "opencode",
  "leader_timeout": 2000,
  "keybinds": {
    "leader": "ctrl+x",
    "command_list": "ctrl+p"
  },
  "scroll_speed": 3,
  "scroll_acceleration": {
    "enabled": false
  },
  "diff_style": "auto",
  "cursor": {
    "style": "block",
    "blinking": true
  },
  "mouse": true,
  "attention": {
    "enabled": true,
    "notifications": true,
    "sound": true,
    "volume": 0.4,
    "sound_pack": "opencode.default",
    "sounds": {
      "error": "./sounds/error.mp3"
    }
  }
}
```

This is separate from `opencode.json`, which configures server/runtime behavior.

`keybinds` is merged with built-in defaults, so you only need to configure the shortcuts you want to change.

### Options

- `theme` - Sets your UI theme. [Learn more](/docs/themes).
- `keybinds` - Customizes keyboard shortcuts. [Learn more](/docs/keybinds).
- `leader_timeout` - Controls how long OpenCode waits after the leader key. Defaults to `2000`.
- `scroll_acceleration.enabled` - Enable macOS-style scroll acceleration for smooth, natural scrolling. When enabled, scroll speed increases with rapid scrolling gestures and stays precise for slower movements. **This setting takes precedence over `scroll_speed` and overrides it when enabled.**
- `scroll_speed` - Controls how fast the TUI scrolls when using scroll commands (minimum: `0.001`, supports decimal values). Defaults to `3`. **Note: This is ignored if `scroll_acceleration.enabled` is set to `true`.**
- `diff_style` - Controls diff rendering. `"auto"` adapts to terminal width, `"stacked"` always shows a single-column layout.
- `cursor` - Controls the terminal cursor in TUI input fields. `style` defaults to `"block"`, can be `"underline"`, `"line"`, or `"default"`; `blinking` defaults to `true`. When `style` is `"default"`, the terminal default cursor is restored, so `blinking` has no effect.
- `mouse` - Enable or disable mouse capture in the TUI (default: `true`). When disabled, the terminal's native mouse selection/scrolling behavior is preserved.
- `attention` - Configures TUI desktop notifications and sounds. Disabled by default.

Use `OPENCODE_TUI_CONFIG` to load a custom TUI config path.

### Attention

The TUI can request attention for questions, permissions, session errors, and completed sessions. Enable it with `attention.enabled`; built-in events play sounds when triggered, and non-subagent events request desktop notifications only when the terminal is blurred.

- `enabled` - Enable all attention notifications and sounds. Defaults to `false`.
- `notifications` - Allow terminal-mediated desktop notifications when attention is enabled. Defaults to `true`.
- `sound` - Allow attention sounds when attention is enabled. Defaults to `true`.
- `volume` - Default sound volume from `0` to `1`. Defaults to `0.4`.
- `sound_pack` - Sound pack ID to use. Defaults to `opencode.default`.
- `sounds` - Override sound files for `default`, `question`, `permission`, `error`, `done`, or `subagent_done`. Paths can be absolute, `file://` URLs, or relative to `tui.json`.

---

## Customization

You can customize various aspects of the TUI view using the command palette (`ctrl+p`). These settings persist across restarts.

---

#### Username display

Toggle whether your username appears in chat messages. Access this through:

- Command palette: Search for "username" or "hide username"
- The setting persists automatically and will be remembered across TUI sessions

---

### Packages Web Src Content Docs Web (`packages/web/src/content/docs/web.mdx`)

---
title: Web
description: Using OpenCode in your browser.
---

OpenCode can run as a web application in your browser, providing the same powerful AI coding experience without needing a terminal.



## Getting Started

Start the web interface by running:

```bash
opencode web
```

This starts a local server on `127.0.0.1` with a random available port and automatically opens OpenCode in your default browser.

:::caution
If `OPENCODE_SERVER_PASSWORD` is not set, the server will be unsecured. This is fine for local use but should be set for network access.
:::

:::tip[Windows Users]
For the best experience, run `opencode web` from [WSL](/docs/windows-wsl) rather than PowerShell. This ensures proper file system access and terminal integration.
:::

---

## Configuration

You can configure the web server using command line flags or in your [config file](/docs/config).

### Port

By default, OpenCode picks an available port. You can specify a port:

```bash
opencode web --port 4096
```

### Hostname

By default, the server binds to `127.0.0.1` (localhost only). To make OpenCode accessible on your network:

```bash
opencode web --hostname 0.0.0.0
```

When using `0.0.0.0`, OpenCode will display both local and network addresses:

```
  Local access:       http://localhost:4096
  Network access:     http://192.168.1.100:4096
```

### mDNS Discovery

Enable mDNS to make your server discoverable on the local network:

```bash
opencode web --mdns
```

This automatically sets the hostname to `0.0.0.0` and advertises the server as `opencode.local`.

You can customize the mDNS domain name to run multiple instances on the same network:

```bash
opencode web --mdns --mdns-domain myproject.local
```

### CORS

To allow additional domains for CORS (useful for custom frontends):

```bash
opencode web --cors https://example.com
```

### Authentication

To protect access, set a password using the `OPENCODE_SERVER_PASSWORD` environment variable:

```bash
OPENCODE_SERVER_PASSWORD=secret opencode web
```

The username defaults to `opencode` but can be changed with `OPENCODE_SERVER_USERNAME`.

---

## Using the Web Interface

Once started, the web interface provides access to your OpenCode sessions.

### Sessions

View and manage your sessions from the homepage. You can see active sessions and start new ones.



### Server Status

Click "See Servers" to view connected servers and their status.



---

## Attaching a Terminal

You can attach a terminal TUI to a running web server:

```bash
# Start the web server
opencode web --port 4096

# In another terminal, attach the TUI
opencode attach http://localhost:4096
```

This allows you to use both the web interface and terminal simultaneously, sharing the same sessions and state.

---

## Config File

You can also configure server settings in your `opencode.json` config file:

```json
{
  "server": {
    "port": 4096,
    "hostname": "0.0.0.0",
    "mdns": true,
    "cors": ["https://example.com"]
  }
}
```

Command line flags take precedence over config file settings.

---

### Packages Web Src Content Docs Windows Wsl (`packages/web/src/content/docs/windows-wsl.mdx`)

---
title: Windows (WSL)
description: Run OpenCode on Windows using WSL for the best experience.
---

import { Steps } from "@astrojs/starlight/components"

While OpenCode can run directly on Windows, we recommend using [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install) for the best experience. WSL provides a Linux environment that works seamlessly with OpenCode's features.

:::tip[Why WSL?]
WSL offers better file system performance, full terminal support, and compatibility with development tools that OpenCode relies on.
:::

---

## Setup

<Steps>

1. **Install WSL**

   If you haven't already, [install WSL](https://learn.microsoft.com/en-us/windows/wsl/install) using the official Microsoft guide.

2. **Install OpenCode in WSL**

   Once WSL is set up, open your WSL terminal and install OpenCode using one of the [installation methods](/docs/).

   ```bash
   curl -fsSL https://opencode.ai/install | bash
   ```

3. **Use OpenCode from WSL**

   Navigate to your project directory (access Windows files via `/mnt/c/`, `/mnt/d/`, etc.) and run OpenCode.

   ```bash
   cd /mnt/c/Users/YourName/project
   opencode
   ```

</Steps>

---

## Desktop App + WSL Server

If you prefer using the OpenCode Desktop app but want to run the server in WSL:

1. **Start the server in WSL** with `--hostname 0.0.0.0` to allow external connections:

   ```bash
   opencode serve --hostname 0.0.0.0 --port 4096
   ```

2. **Connect the Desktop app** to `http://localhost:4096`

:::note
If `localhost` does not work in your setup, connect using the WSL IP address instead (from WSL: `hostname -I`) and use `http://<wsl-ip>:4096`.
:::

:::caution
When using `--hostname 0.0.0.0`, set `OPENCODE_SERVER_PASSWORD` to secure the server.
:::

```bash
OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0
```

---

## Web Client + WSL

For the best web experience on Windows:

1. **Run `opencode web` in the WSL terminal** rather than PowerShell:

   ```bash
   opencode web --hostname 0.0.0.0
   ```

2. **Access from your Windows browser** at `http://localhost:<port>` (OpenCode prints the URL)

Running `opencode web` from WSL ensures proper file system access and terminal integration while still being accessible from your Windows browser.

---

## Accessing Windows Files

WSL can access all your Windows files through the `/mnt/` directory:

- `C:` drive → `/mnt/c/`
- `D:` drive → `/mnt/d/`
- And so on...

Example:

```bash
cd /mnt/c/Users/YourName/Documents/project
opencode
```

:::tip
For the smoothest experience, consider cloning/copying your repo into the WSL filesystem (for example under `~/code/`) and running OpenCode there.
:::

---

## Tips

- Keep OpenCode running in WSL for projects stored on Windows drives - file access is seamless
- Use VS Code's [WSL extension](https://code.visualstudio.com/docs/remote/wsl) alongside OpenCode for an integrated development workflow
- Your OpenCode config and sessions are stored within the WSL environment at `~/.local/share/opencode/`

---

### Services Www Src Docs Content Agents (`services/www/src/docs/content/agents.mdx`)

---
title: "Agents"
---

Create a Markdown file to add a reusable agent. This example adds a read-only reviewer that the main agent can launch for code reviews:

```md title=".opencode/agents/reviewer.md"
---
description: Reviews changes for correctness and regressions
mode: subagent
model: anthropic/claude-sonnet-4-5#high
permissions:
  - action: edit
    resource: "*"
    effect: deny
  - action: shell
    resource: "*"
    effect: deny
---

Review the current changes. List findings in severity order with file and line references.
```

Ask your primary agent to use it:

```text
Use the reviewer subagent to review my current changes.
```

An agent combines a system prompt, model preference, permissions, and display details into a named assistant profile.

## Locations

Save Markdown agents globally for all projects or inside a project:

```text
~/.config/opencode/agents/<name>.md
.opencode/agents/<name>.md
```

OpenCode discovers project `.opencode` directories from the current directory up to the project root. A nested path becomes part of the agent ID:

```text
.opencode/agents/team/reviewer.md  →  team/reviewer
```

## Formats

### Markdown

Frontmatter accepts the same fields as an `agents` configuration entry. The Markdown body becomes the agent's `system` prompt:

```md title=".opencode/agents/explainer.md"
---
description: Explains code without changing it
mode: subagent
---

Explain the relevant code with short examples. Do not edit files.
```

V1 frontmatter fields are deprecated. See [Agent files](/migrate-v1#agent-files) for how files that still use them are read.

### JSONC

Define agents under `agents` in any [OpenCode configuration file](/config):

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "agents": {
    "reviewer": {
      "description": "Reviews current changes",
      "mode": "subagent",
      "system": "Report findings in severity order.",
      "permissions": [
        { "action": "edit", "resource": "*", "effect": "deny" },
      ],
    },
  },
}
```

## Selection

Set the primary agent used when a session has not selected one:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "default_agent": "writer",
  "agents": {
    "writer": { "mode": "primary" },
  },
}
```

The selected default must exist, be visible, and support primary use. Otherwise OpenCode uses `build`, then the first visible primary-capable agent. Changing this setting does not replace the agent stored on an existing session.

## Modes

Set `mode` according to where the agent should run:

```jsonc
{
  "agents": {
    "reviewer": { "mode": "subagent" },
  },
}
```

| Mode | Behavior |
| --- | --- |
| `primary` | Runs as the main agent for a session. This is the default for a new custom agent. |
| `subagent` | Runs only in a child session through the `subagent` tool. |
| `all` | Runs either as a primary agent or a subagent. |

Subagents run with fresh context in foreground or background child sessions. The parent agent's `subagent` permissions control which agents it may launch; the child uses its own configured permissions.

```jsonc
{
  "agents": {
    "orchestrator": {
      "permissions": [
        { "action": "subagent", "resource": "*", "effect": "deny" },
        { "action": "subagent", "resource": "reviewer", "effect": "allow" },
      ],
    },
  },
}
```

## Builtins

OpenCode includes these visible agents:

| Agent | Mode | Purpose |
| --- | --- | --- |
| **Build** (`build`) | `primary` | Default coding agent. Tools and access outside the workspace are allowed by default; sensitive environment-file reads ask for approval. |
| **Plan** (`plan`) | `primary` | Explores and plans without editing normal project files. It may write OpenCode plan files when asked, and shell commands remain permission-controlled. |
| **General** (`general`) | `subagent` | Handles research and multi-step work with broad tool access, but cannot launch more subagents. |
| **Explore** (`explore`) | `subagent` | Searches and reads code or web sources without editing files. |

Override a built-in by using the same ID:

```jsonc
{
  "agents": {
    "build": {
      "permissions": [
        { "action": "shell", "resource": "git push *", "effect": "ask" },
      ],
    },
  },
}
```

Hidden `compaction`, `title`, and `summary` agents perform maintenance and cannot be selected directly. V2 has no built-in `scout` agent.

## Merging

Agent definitions merge in configuration order. Later scalar values replace earlier values, request maps merge by key, and permission rules append:

```jsonc
{
  "permissions": [
    { "action": "shell", "resource": "*", "effect": "ask" },
  ],
  "agents": {
    "build": {
      "permissions": [
        { "action": "shell", "resource": "git status", "effect": "allow" },
      ],
    },
  },
}
```

Global `permissions` apply before agent-specific rules, so later agent rules can refine them.

## Options

### Description

`description` explains the agent's purpose. Add it to subagents because OpenCode shows it to the model choosing which agent to launch:

```yaml
description: Reviews database migrations for safety
```

### Mode

`mode` accepts `primary`, `subagent`, or `all`. When omitted on a new custom agent, it defaults to `primary`:

```yaml
mode: all
```

### Model

`model` uses `provider/model` with an optional `#variant`:

```yaml
model: anthropic/claude-sonnet-4-5#high
```

JSON configuration also accepts the expanded form:

```jsonc
{
  "agents": {
    "reviewer": {
      "model": {
        "providerID": "anthropic",
        "model": "claude-sonnet-4-5",
        "variant": "high",
      },
    },
  },
}
```

- A subagent uses its configured model, or inherits the parent session's model when none is configured.
- A session stores its selected model separately. Selecting a primary agent by ID does not change that model.

### System

`system` sets the agent's system prompt. A non-empty value replaces the provider's base prompt for that agent:

```jsonc
{
  "agents": {
    "reviewer": { "system": "Review only. Do not modify files." },
  },
}
```

Project instructions, skills, references, and other instruction sources are still added. In a Markdown agent, put this text in the document body instead of a `system` frontmatter field.

### Permissions

`permissions` is an ordered list of matching rules:

```jsonc
{
  "agents": {
    "reviewer": {
      "permissions": [
        { "action": "*", "resource": "*", "effect": "deny" },
        { "action": "read", "resource": "src/**", "effect": "allow" },
      ],
    },
  },
}
```

| Field | Meaning |
| --- | --- |
| `action` | Tool or permission action. Wildcards are supported. |
| `resource` | Path, command, agent ID, or other value matched by the action. Wildcards are supported. |
| `effect` | `allow`, `ask`, or `deny`. |

The last matching rule wins, so put broad rules before exceptions. Common actions include:

| Action | Covers |
| --- | --- |
| `shell` | Shell commands |
| `edit` | Edit, write, and patch tools |
| `subagent` | Child agents |
| `read`, `glob`, `grep` | Local discovery tools |
| `webfetch`, `websearch` | Web tools |
| `skill` | Skill loading |

For `read`, `edit`, and `external_directory` resources, OpenCode expands `~` and `$HOME`:

```jsonc
{ "action": "read", "resource": "~/notes/**", "effect": "allow" }
```

Shell resources remain raw command text and do not expand those values.

### Steps

`steps` sets a positive maximum number of model steps:

```yaml
steps: 8
```

On the final step, OpenCode removes tools and asks the model to summarize in text. New user input resets the allowance.

### Hidden

`hidden` removes an agent from normal listings, interactive discovery, and the subagent catalog:

```yaml
hidden: true
```

This controls visibility, not security. Use permissions to restrict behavior.

### Color

`color` sets the agent's UI color using a six-digit hex value:

```yaml
color: "#ff6b6b"
```

### Disabled

`disabled` removes a built-in or custom agent at that point in configuration loading:

```jsonc
{
  "agents": {
    "plan": { "disabled": true },
  },
}
```

### Request

`request` accepts per-agent header and JSON body overlays:

```jsonc
{
  "agents": {
    "reviewer": {
      "request": {
        "headers": { "x-agent": "reviewer" },
        "body": { "temperature": 0.1 },
      },
    },
  },
}
```

<Callout type="warning">
  The V2 session runner preserves these values but does not yet send them with model requests. Configure active request
  settings on the provider, model, or model variant instead.
</Callout>

Do not use legacy top-level fields such as `temperature`, `top_p`, `prompt`, `permission`, `tools`, `disable`, or `maxSteps` in new V2 agent configuration.

---

### Services Www Src Docs Content Attachments (`services/www/src/docs/content/attachments.mdx`)

---
title: "Attachments"
---

## Attach

Attach a local file, then ask OpenCode to use it in your prompt. In the desktop
or web client, choose **Attach file**, paste a file, or drag it into the prompt.

```text
Summarize the attached README.md and list the required setup steps.
```

Desktop file-picker selections can total up to 20 MiB. Other interfaces may
apply lower client-side limits.

<Callout type="warning">
  Choose a model with image input before attaching an image. OpenCode can pass supported images to the provider, but the
  provider and model still enforce their own formats, dimensions, file counts, and sizes. A text-only model may reject the
  request.
</Callout>

## Syntax

V2 prompt and command inputs describe an attachment with a `uri` and optional
`name` and `description`:

```json
{
  "uri": "file:///home/me/project/src/server.ts",
  "name": "server.ts",
  "description": "HTTP server entrypoint"
}
```

Use an absolute `file:` URL for a file or directory that is available to the
server. For text files, positive `start` and `end` parameters select one-based
lines.

```text
file:///home/me/project/src/server.ts?start=20&end=60
```

Use a `data:` URL to send content inline:

```json
{
  "uri": "data:text/plain;base64,SGVsbG8sIE9wZW5Db2RlIQ==",
  "name": "greeting.txt"
}
```

HTTP and HTTPS attachment URLs are not supported. See the generated
[API reference](/api) for programmatic prompt submission.

## Formats

Current V2 sessions make these attachment types visible to the model:

| Input                   | Model receives                                                 | Example            |
| ----------------------- | -------------------------------------------------------------- | ------------------ |
| UTF-8 text file         | Filename and decoded text                                      | `README.md`        |
| Directory               | Non-recursive listing of immediate files and directories       | `file:///home/me/` |
| PNG, JPEG, GIF, or WebP | Image media                                                    | `diagram.png`      |

SVG is treated as text. PDF, AVIF, BMP, audio, video, and other binary prompt
attachments are not included in the model request. Convert an unsupported
binary to text or a supported image first; for example, export a PDF page as
`page-1.png` before attaching it.

OpenCode reads each attachment before admitting the prompt. It rejects invalid
URLs, unreadable paths, paths other than files or directories, and decoded
attachments over 20 MiB. Media type is detected from the bytes, so changing a
filename or `data:` URL media type does not make an unsupported binary visible.

## Images

Configure image normalization in `opencode.json` or `opencode.jsonc`:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "media": {
    "image": {
      "auto_resize": true,
      "max_width": 2000,
      "max_height": 2000,
      "max_base64_bytes": 5242880,
    },
  },
}
```

All fields are optional:

| Field              | Default   | Behavior                                                                  |
| ------------------ | --------- | ------------------------------------------------------------------------- |
| `auto_resize`      | `true`    | Resize an image over a configured limit; when `false`, reject the image.  |
| `max_width`        | `2000`    | Maximum width in pixels; must be a positive integer.                      |
| `max_height`       | `2000`    | Maximum height in pixels; must be a positive integer.                     |
| `max_base64_bytes` | `5242880` | Maximum bytes in the Base64-encoded image; must be a positive integer.    |

For example, this rejects rather than resizes an image wider than 1200 pixels:

```jsonc title="opencode.jsonc"
{
  "media": {
    "image": {
      "auto_resize": false,
      "max_width": 1200,
    },
  },
}
```

These settings apply both to supported images attached to prompts and to images
returned by the built-in `read` tool.

## Processing

The `read` tool recognizes PNG, JPEG, GIF, and WebP by their contents and reads
up to 20 MiB of source image data. It checks width, height, and Base64 length
against the configured image limits.

With `auto_resize: true`, OpenCode preserves the aspect ratio and scales down
to the dimension limits. It then tries progressively smaller PNG and JPEG
encodings until the Base64 limit is met, so the output media type can change.

```text
Input:  4000 × 2000 WebP
Limits: 2000 × 2000
Output: 2000 × 1000 PNG or JPEG
```

If no encoding fits, processing fails. With `auto_resize: false`, an image that
exceeds any limit fails without modification; an image that cannot be decoded
also fails.

```text
Input:  2400 × 1600 JPEG
Limit:  max_width = 2000, auto_resize = false
Result: Image processing fails
```

If the image resizer is unavailable, OpenCode passes the original image through
unchanged. Image settings are therefore processing limits, not an upload or
security boundary.

## Limits

| Limit                         | Value or behavior                                             | Example                                      |
| ----------------------------- | ------------------------------------------------------------- | -------------------------------------------- |
| Direct attachment             | 20 MiB decoded per item; clients may impose lower limits      | Two 12 MiB files pass the per-item limit     |
| Desktop picker selection      | 20 MiB total                                                  | Two 12 MiB files exceed the selection limit  |
| `max_base64_bytes`            | Encoded Base64 only, excluding the complete `data:` URL       | `SGVsbG8=` counts as 8 bytes                 |
| Provider image limits         | Apply after OpenCode processing                               | A provider may reject an accepted image      |
| Text attachment model support | Does not require a multimodal model                           | `notes.txt` is inserted as prompt text       |
| `read` text limits            | Uses separate paging and truncation limits                    | Read a large log in pages                    |

A client accepting a file does not guarantee that its contents reach the
model. The attachment must use a model-visible format and satisfy both OpenCode
and provider limits.

---

### Services Www Src Docs Content Commands (`services/www/src/docs/content/commands.mdx`)

---
title: "Commands"
---

Create `.opencode/commands/review.md` to turn a prompt into `/review`:

```md title=".opencode/commands/review.md"
Review $ARGUMENTS for bugs and missing tests.
```

Run it from the TUI with a target:

```text
/review src/auth.ts
```

OpenCode submits `Review src/auth.ts for bugs and missing tests.` as a user prompt.

## Markdown

Put global commands in `~/.config/opencode/commands/` and project commands in `.opencode/commands/`.

```text
~/.config/opencode/commands/review.md
.opencode/commands/review.md
```

Only `.md` files are discovered. Nested paths become command names with `/` separators:

```md title=".opencode/commands/team/review.md"
Review $ARGUMENTS using the team's checklist.
```

Run the nested command as `/team/review src/auth.ts`. The legacy singular directories `command/` are also discovered,
but use `commands/` for new files.

Add YAML frontmatter when the command needs metadata. The trimmed Markdown body is always the prompt template.

```md title=".opencode/commands/review.md"
---
description: Review code for correctness
agent: plan
model: anthropic/claude-sonnet-4-5#high
---

Review $ARGUMENTS. Report bugs first.
```

## JSON

Define commands under `commands` in any OpenCode JSON or JSONC [configuration file](/config). Each command requires a
`template`.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "commands": {
    "review": {
      "description": "Review code for correctness",
      "template": "Review $ARGUMENTS. Report bugs first.",
    },
  },
}
```

## Fields

Markdown frontmatter and JSON entries accept the same fields, except that Markdown gets `template` from the file body.

| Field | Required | Behavior |
| --- | --- | --- |
| `template` | JSON only | Prompt template. |
| `description` | No | Text shown in command lists and discovery. |
| `agent` | No | Agent selected when the command runs. |
| `model` | No | Model override in `provider/model` or `provider/model#variant` format. |
| `subagent` | No | `true` runs in a background child session; `false` forces the current session. |
| `subtask` | No | Deprecated alias for `subagent`. |

For example, this JSON command sets every current optional field:

```jsonc title="opencode.jsonc"
{
  "commands": {
    "audit": {
      "template": "Audit $ARGUMENTS.",
      "description": "Audit a package",
      "agent": "general",
      "model": "anthropic/claude-sonnet-4-5#high",
      "subagent": true,
    },
  },
}
```

Do not put `template` in Markdown frontmatter; the body supplies it.

## Arguments

Use `$ARGUMENTS` for the complete argument string exactly as entered.

```md title=".opencode/commands/component.md"
Create a typed React component named $ARGUMENTS.
```

For `/component Account Settings`, the placeholder becomes `Account Settings`.

## Positions

Use `$1`, `$2`, and higher numbers for parsed positional arguments. Single or double quotes group words and are removed.

```md title=".opencode/commands/check.md"
Check $1. Focus on $2.
```

For `/check src/auth.ts "error handling"`, `$1` becomes `src/auth.ts` and `$2` becomes `error handling`.

The highest-numbered placeholder consumes its argument and everything after it. Missing positions become empty strings.

```md title=".opencode/commands/compare.md"
Compare $1 with $2.
```

For `/compare api stable branch`, OpenCode submits `Compare api with stable branch.`

## Fallback

When a template has no `$ARGUMENTS` or positional placeholder, OpenCode appends non-empty arguments after a blank line.

```md title=".opencode/commands/explain.md"
Explain this code clearly.
```

For `/explain src/cache.ts`, the prompt becomes:

```text
Explain this code clearly.

src/cache.ts
```

## Shell

Wrap a shell command in `!` followed by backticks to insert its output before the prompt is submitted.

```md title=".opencode/commands/review-diff.md"
Review this diff:

!`git diff --stat && git diff`
```

OpenCode runs each block with the configured shell in the active project location and inserts its combined output.
Argument placeholders are expanded first:

```md title=".opencode/commands/history.md"
Summarize these commits:

!`git log --oneline -$1`
```

For `/history 5`, the shell receives `git log --oneline -5`. Do not place untrusted arguments inside shell blocks.

<Callout type="warning">
  Shell blocks run when OpenCode evaluates the command, outside the agent's tool permission flow. Only use commands from
  sources you trust.
</Callout>

## Attachments

Stored templates do not expand `@path`; it remains ordinary prompt text.

```md title=".opencode/commands/readme.md"
Review @README.md.
```

To attach a file, add it through the composer when invoking the command. OpenCode preserves those composer attachments
when it submits the expanded prompt.

## Execution

Commands expand arguments and shell blocks before submitting a durable user prompt. They run in the current session by
default.

```md title=".opencode/commands/plan.md"
---
agent: plan
---

Plan $ARGUMENTS.
```

Running `/plan migration` switches the current session to `plan` before submitting the prompt.

Model selection follows these rules:

1. A command `model` overrides every other model.
2. Otherwise, the selected command agent's configured model overrides the model active at invocation.
3. Otherwise, the current session model remains active.

For example, this command selects both its agent and an explicit model:

```md title=".opencode/commands/design.md"
---
agent: plan
model: openai/gpt-5#high
---

Design $ARGUMENTS.
```

## Background

Set `subagent: true` to run a command in a background child session.

```md title=".opencode/commands/audit.md"
---
description: Audit changes
agent: general
subagent: true
---

Audit $ARGUMENTS for bugs and missing tests.
```

The parent stays available and keeps its agent and model. OpenCode sends the child's result or failure back to the parent
when the child finishes.

| Value | Behavior |
| --- | --- |
| `true` | Always use a child, even when the selected agent has `mode: primary`. |
| `false` | Always use the current session, even when the selected agent has `mode: subagent`. |
| Omitted | Use a child only when the selected agent has `mode: subagent`. |

The child uses the command model, then the selected agent's model, then the parent's model. Legacy `subtask` remains
accepted; if both fields are present, `subagent` wins.

```yaml
subagent: false
subtask: true
```

This example runs in the current session because `subagent` takes precedence.

## Loading

Markdown and JSON commands share one registry. Later sources replace earlier commands with the same name.

```text
~/.config/opencode/commands/review.md   # Lower priority
.opencode/commands/review.md           # Replaces the global command
```

Project sources take precedence over global sources, and nearer project sources take precedence over ancestor sources.
A custom definition can also replace an earlier built-in command. OpenCode reloads command files and configuration changes
automatically.

```md title=".opencode/commands/review.md"
Review only the staged changes: !`git diff --cached`
```

Saving this file updates `/review` without restarting OpenCode.

---

### Services Www Src Docs Content Compaction (`services/www/src/docs/content/compaction.mdx`)

---
title: "Compaction"
---

Compaction makes room in a long session by replacing older conversation with a
summary, so the session can keep going past the model's context limit.

## How it works

When a session approaches the model's context limit, OpenCode summarizes the
entire current conversation. It also keeps the most recent conversation, about
15,000 tokens by default, beside the summary so exact recent details remain
available.

```text
before   [ system prompt ][ older conversation ............ ][ recent 15k ][ pending work ]
request  [ system prompt ][ older conversation ............ ][ recent 15k ][ summary instructions ]
after    [ system prompt ][ summary of older + recent ][ recent 15k ][ pending work ]
```

Sending the full conversation lets the summary request reuse the normal request's
prompt cache when the provider supports it. Later compactions update the existing
summary using the conversation since that checkpoint.

## Start

Automatic compaction is on by default:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "compaction": {
    "auto": true,
    "keep": { "tokens": 15000 },
  },
}
```

Compaction is lossy. Increase `keep.tokens` when exact recent details matter,
or request compaction yourself before the automatic one.

## Manual

Request compaction at any time, even for a short history:

```sh
opencode api post /api/session/ses_example/compact --data '{}'
```

The `api` command discovers and authenticates with the background service. Its
response confirms the request was accepted; it does not wait for the summary.
Follow `session.compaction.*` events to learn when it finishes. See the
[API reference](/api) for the full operation.

| Rule | Behavior |
| --- | --- |
| Timing | Runs at the next safe point, before prompts that are still waiting. |
| Repeats | Requests made while one is pending merge into it. |
| Automation | Works when `compaction.auto` is `false`. |

Pass an `id` to make an exact retry idempotent. Reusing that ID for a different
request returns a conflict.

```sh
opencode api post /api/session/ses_example/compact --data '{"id":"msg_compact_once"}'
```

## Settings

Add `compaction` to any [OpenCode configuration file](/config):

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "compaction": {
    "auto": false,
    "keep": { "tokens": 24000 },
    "buffer": 16000,
  },
}
```

| Field | Default | Behavior |
| --- | ---: | --- |
| `auto` | `true` | Compact automatically near the context limit, and recover once when a provider rejects a request as too long. Manual compaction always works. |
| `keep.tokens` | `15000` | Approximate recent conversation kept beside the summary. Larger values preserve more detail but leave less room for new work. |
| `buffer` | 15% of the limit, at least 16k | Tokens to keep free below the model's limit. Larger values start automatic compaction earlier. |

`keep.tokens` and `buffer` accept non-negative integers.

## Providers

By default OpenCode writes the summary itself, using the session's model. Some
providers can compact the conversation on their side instead. Enable it per
provider or model with `settings.compaction`:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "openai": {
      "settings": { "compaction": { "type": "native" } },
      "models": {
        "gpt-4.1": { "settings": { "compaction": { "type": "summary" } } },
      },
    },
  },
}
```

A model setting overrides the provider setting. `native` uses the provider's
compaction; `summary` uses OpenCode's own.

With native compaction, OpenCode sends the conversation to the provider's
compaction endpoint. The provider returns an opaque, encrypted item that stands
in for the older conversation. Your recent messages and attachments, up to
`keep.tokens`, are kept alongside it:

```text
before   [ older conversation ........................ ][ recent user messages ]
after    [ encrypted checkpoint + recent user messages ]
```

| Topic | Behavior |
| --- | --- |
| Support | OpenAI Responses models. Support varies by deployment and model. |
| Threshold | Same `auto` and `buffer` settings as summary compaction. Manual requests work too. |
| Portability | An encrypted checkpoint only works with the same provider and model. If you switch models, the session continues from the original conversation instead. |
| Too long | If the provider rejects a compaction as too long, OpenCode retries it with a smaller request. It does not switch to a summary. |

## Summaries

The summary is structured so another agent could pick the work up from it:

```md
## Objective
Finish the authentication migration.

## Next Move
- Update the callback handler.
- Verify the login flow.
```

It covers the objective and requirements, decisions, completed and active work,
blockers and next moves, and relevant files. In the recent conversation kept
beside it, long tool output is shortened and attachment data is replaced by a
short description.

After compaction, the current versions of your instruction files become the
session's baseline; see [Instructions](/instructions).

## Limits

| Limit | Result |
| --- | --- |
| Model | Compaction uses the session's model. There is no separate compaction model. |
| History | Compaction needs older conversation to replace. It cannot create room when a request is mostly fixed instructions and tool schemas. |
| Size | If the conversation to compact is itself too long, OpenCode sends a shortened text version and may leave out the oldest exchanges. |
| Recovery | A request rejected as too long is compacted and retried once. A second rejection is returned as an error. |
| Storage | Earlier messages remain stored even when they are no longer sent to the model. |

For example, compaction cannot help here:

```text
128k context = 120k fixed instructions and tools + 8k conversation
```

## Migration

V1 used tail-turn and pruning behavior. V2 uses summaries and
`compaction.keep.tokens`:

```jsonc
{
  "compaction": {
    "keep": { "tokens": 15000 }
  }
}
```

The settings and behavior on this page apply to V2.

---

### Services Www Src Docs Content Config (`services/www/src/docs/content/config.mdx`)

---
title: "Config"
---

Create `opencode.jsonc` in your project to configure OpenCode. Add the schema for editor validation, then set only the options you need.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "model": "anthropic/claude-sonnet-4-5",
}
```

You can also ask OpenCode to update this file for you.

## Format

OpenCode supports JSON and JSONC. Use JSONC when you want comments or trailing commas.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  // Use this model by default.
  "model": "anthropic/claude-sonnet-4-5",
}
```

## Locations

Put managed, machine-wide settings in the system configuration directory:

| Platform | Directory                               |
| -------- | --------------------------------------- |
| macOS    | `/Library/Application Support/opencode` |
| Linux    | `/etc/opencode`                         |
| Windows  | `%ProgramData%\opencode`                |

The system directory works like the global directory. Besides
`opencode.json(c)`, it loads `agents/`, `commands/`, `skills/`, and `plugins/`
for every user on the machine:

```text
/etc/opencode/
├── opencode.json
├── agents/review.md
├── commands/release.md
└── skills/deploy/SKILL.md
```

On macOS, OpenCode also reads managed preferences that MDM tools deploy for the
`ai.opencode.managed` domain. A user-specific profile replaces the
machine-wide one:

```text
/Library/Managed Preferences/<user>/ai.opencode.managed.plist
/Library/Managed Preferences/ai.opencode.managed.plist
```

Managed settings have the highest precedence, so users and projects cannot
override the values they set, and managed preferences override the system
directory. Settings alone cannot stop users from adding providers, MCP servers,
agents, or plugins; use [policies](/policies#precedence) in managed
configuration to enforce restrictions.

Put user settings for every project in the global configuration:

```text
~/.config/opencode/opencode.json(c)
```

Put project settings in either of these files:

```text
/home/user/projects/my-app/opencode.json(c)
/home/user/projects/my-app/.opencode/opencode.json(c)
```

OpenCode searches from the current directory to the filesystem root. It first
merges direct `opencode.json(c)` files from the farthest directory to the
closest, then merges files inside `.opencode` directories in the same order.
This means every discovered `.opencode` config overrides every direct config.
Use one form throughout a directory tree unless you need that behavior.

For example, start OpenCode from `/home/user/projects/acme/packages/web`:

```text
/etc/opencode/opencode.json
~/.config/opencode/opencode.json

/home/user/projects/acme/
├── opencode.json
└── packages/
    └── web/
        ├── opencode.json
        └── src/
```

OpenCode applies these files from lowest to highest precedence:

1. `~/.config/opencode/opencode.json`
2. `/home/user/projects/acme/opencode.json`
3. `/home/user/projects/acme/packages/web/opencode.json`
4. `/etc/opencode/opencode.json`

The package config overrides matching settings from the repository config,
which overrides the global config. The system config overrides all of them.
Settings that do not conflict are preserved. [Policies](/policies#precedence)
from global and project files evaluate in the reverse order, and system
policies outrank all of them.

## Schema

The complete OpenCode configuration schema is available at
[opencode.ai/config.json](https://opencode.ai/config.json).

Add the `$schema` field to your configuration file to enable validation and
autocomplete in editors that support JSON Schema:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json"
}
```

Use the schema as the source of truth for available fields, accepted values,
and nested configuration shapes.

### Shell

Set the shell used by the terminal and shell tools.

```jsonc
{
  "shell": "/bin/zsh",
}
```

### Model

Set the default model in `provider/model` format. The root default currently
does not retain a `#variant`; agent and command model references can select one.

```jsonc
{
  "model": "anthropic/claude-sonnet-4-5",
}
```

See the [models guide](/models) for model selection and local models.

### Agent

Choose the primary agent used when a session does not select one explicitly.

```jsonc
{
  "default_agent": "build",
}
```

See the [agents guide](/agents) for built-in and custom
agents.

### Updates

Control update checks from the global config. Set `update` to `"disable"` to
skip them, `"notify"` to show available updates before installing them, or
`"auto"` to install updates automatically. When omitted, `update` defaults to `"notify"`.

Automatic installation does not restart a running server. Restart it manually to activate the installed update.
Project-level values are ignored.

```jsonc
{
  "update": "notify",
}
```

### Username

Set a username. OpenCode accepts this field but does not display it in
conversations.

```jsonc
{
  "username": "alice",
}
```

### Permissions

Define ordered rules that allow, deny, or ask before an agent uses a tool on a
matching resource.

```jsonc
{
  "permissions": [
    {
      "action": "shell",
      "resource": "git push *",
      "effect": "ask",
    },
  ],
}
```

See the [permissions guide](/permissions) for rule matching and available actions.

### Policies

Allow or deny use of a provider, hard-deny a permission check, or block an MCP
server, skill, or plugin, with ordered statements that broader configuration can
override.

```jsonc
{
  "policies": [
    { "action": "provider.use", "resource": "*", "effect": "deny" },
    { "action": "provider.use", "resource": "anthropic", "effect": "allow" },
    { "action": "tool.use", "resource": "shell:git push *", "effect": "deny" },
  ],
}
```

See the [policies guide](/policies) for matching, precedence across configuration
files, and Console-managed policy.

### Agents

Override built-in agents or define specialized agents with their own model,
instructions, mode, and permissions.

```jsonc
{
  "agents": {
    "reviewer": {
      "description": "Review changes without editing files",
      "mode": "subagent",
      "system": "Focus on correctness, security, and missing tests.",
      "permissions": [{ "action": "edit", "resource": "*", "effect": "deny" }],
    },
  },
}
```

See the [agents guide](/agents) for all agent options and file-based agents.

### Snapshots

Enable or disable filesystem snapshots used by undo and revert behavior.

```jsonc
{
  "snapshots": false,
}
```

See the [snapshots guide](/snapshots) for undo and redo behavior.

### Watcher

Ignore files and directories that should not trigger filesystem updates.

```jsonc
{
  "watcher": {
    "ignore": ["dist/**", "coverage/**"],
  },
}
```

### Formatter

Format files after the `write`, `edit`, or `patch` tools change them. Set
`formatter` to `true` to enable available built-in formatters.

```jsonc
{
  "formatter": true,
}
```

See the [formatters guide](/formatters) for built-ins and custom formatters.

### Media

Control how oversized images loaded by the `read` tool are resized or rejected
before they are sent to a model.

```jsonc
{
  "media": {
    "image": {
      "auto_resize": true,
      "max_width": 2000,
      "max_height": 2000,
      "max_base64_bytes": 5242880,
    },
  },
}
```

See the [attachments guide](/attachments) for image processing and limits.

### Output

Set the maximum number of lines and bytes retained from a tool result.

```jsonc
{
  "tool_output": {
    "max_lines": 2000,
    "max_bytes": 51200,
  },
}
```

### Search

Choose how OpenCode searches the web. Use `"random"` to select an available
provider automatically.

```jsonc
{
  "websearch": {
    "provider": "random",
  },
}
```

See the [websearch guide](/websearch) for providers, credentials, selection,
rate limits, and disabling search.

### MCP

Configure local and remote Model Context Protocol servers. Global
`mcp.timeout` values apply to servers defined in configuration files; each
server's `timeout` overrides them.

```jsonc
{
  "mcp": {
    "servers": {
      "playwright": {
        "type": "local",
        "command": ["bunx", "@playwright/mcp"],
      },
    },
  },
}
```

See the [MCP guide](/mcp-servers) for remote servers, OAuth, environment variables, and timeouts.

### Compaction

Control automatic context compaction and how much recent context it preserves.

```jsonc
{
  "compaction": {
    "auto": true,
    "keep": {
      "tokens": 15000,
    },
    "buffer": 20000,
  },
}
```

Local summaries remain the default. Opt into native provider compaction for both
automatic and manual requests with a provider or model policy:

```jsonc
{
  "providers": {
    "openai": {
      "settings": { "compaction": { "type": "native" } },
      "models": {
        "gpt-4.1": { "settings": { "compaction": { "type": "summary" } } },
      },
    },
  },
}
```

A model setting overrides the provider setting. Automatic compaction uses the
selected model's usable input budget. Provider checkpoints keep recent user messages within the same
`compaction.keep.tokens` budget that local summaries use for their retained tail.
Top-level `compaction.auto: false` disables new automatic compaction without
discarding installed checkpoints. See the [compaction guide](/compaction) for
budgeting and overflow recovery.

### Warming

Keep recently active model sessions warm with periodic transient requests.
Warming is disabled by default; set it to `true` to use the four-minute idle
interval and 30-minute active window.

```jsonc
{
  "warming": {
    "prompt": "Do not perform any work. Reply with exactly: OK",
    "interval": "4 minutes",
    "duration": "30 minutes",
  },
}
```

See the [warming guide](/warming) for request behavior, customization,
and cost considerations.

### Skills

Add directories or URLs that OpenCode should search for agent skills.

```jsonc
{
  "skills": ["./team-skills", "https://example.com/.well-known/skills/"],
}
```

See the [skills guide](/skills) for skill structure and automatic discovery under `.opencode/skills/`.

### Commands

Define reusable slash commands as named prompt templates.

```jsonc
{
  "commands": {
    "review": {
      "description": "Review the current changes",
      "template": "Review the current diff for correctness and missing tests.",
    },
  },
}
```

See the [commands guide](/commands) for arguments, models, agents, and file-based commands.

### Instructions

Declare additional instruction files, globs, or HTTP(S) URLs. OpenCode loads
them alongside discovered `AGENTS.md` files.

```jsonc
{
  "instructions": ["CONTRIBUTING.md", "docs/guidelines/*.md"],
}
```

See the [instructions guide](/instructions) for project instructions and `AGENTS.md`.

### References

Make local directories or Git repositories available as named supporting
context.

```jsonc
{
  "references": {
    "docs": {
      "path": "../product-docs",
      "description": "Product behavior and terminology",
    },
    "effect": {
      "repository": "Effect-TS/effect",
      "branch": "main",
    },
  },
}
```

See the [references guide](/references) for shorthand, visibility, and path resolution.

### Worktrees

Set the parent directory for new local worktrees. OpenCode appends the requested or generated worktree name.

```jsonc
{
  "worktree": {
    "directory": "../worktrees",
  },
}
```

Relative paths resolve against the project's saved canonical checkout. This applies to global and project
configuration alike; absolute paths are used as-is, and `~/` resolves
against the user's home directory.

For example, this global configuration places new worktrees under each project's own `.lane/trees/` directory:

```jsonc
{
  "worktree": {
    "directory": ".lane/trees",
  },
}
```

Without this setting, creation uses the server's data directory under `worktree/<first-six-project-ID-characters>`.
Worktree creation and refresh load configuration from the project's saved canonical checkout, including when other
clones share its project ID. Changing it does not move existing worktrees.

Git is the built-in default. A [plugin](/build/plugins#worktrees) that registers a strategy automatically becomes the
default in that plugin runtime. Project operations use the canonical checkout's runtime. Strategy-specific options
belong to that plugin, not the `worktree` config object.

### Plugins

Load plugins from packages or local plugin directories. Use the object form when a plugin
accepts options.

```jsonc
{
  "plugins": [
    "opencode-example-plugin",
    {
      "package": "./plugins/local",
      "options": {
        "enabled": true,
      },
    },
  ],
}
```

See the [plugins guide](/plugins) for plugin loading and configuration.

### Providers

Configure providers and add or override their models, request settings,
headers, and model variants.

```jsonc
{
  "providers": {
    "openai": {
      "models": {
        "gpt-5.2-custom": {
          "modelID": "gpt-5.2",
          "name": "GPT-5.2 Custom",
          "limit": {
            "context": 200000,
            "output": 32000,
          },
        },
      },
    },
  },
}
```

Provider `settings.transport: "websocket"` selects its session WebSocket.

See the [providers guide](/providers) for credentials, custom endpoints, provider packages, the WebSocket transport, and model configuration.

## Variables

You can use variable substitution in your config files to reference environment variables and file contents. Place references inside JSON strings.

### Env vars

Use `{env:VARIABLE_NAME}` to substitute environment variables:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "model": "{env:OPENCODE_MODEL}",
  "providers": {
    "anthropic": {
      "settings": {
        "apiKey": "{env:ANTHROPIC_API_KEY}",
      },
    },
  },
}
```

If the environment variable is not set, it will be replaced with an empty string.

### Files

Use `{file:path/to/file}` to substitute the contents of a file:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "openai": {
      "settings": {
        "apiKey": "{file:~/.secrets/openai-key}",
      },
    },
  },
}
```

File paths can be:

- Relative to the config file directory
- Absolute, or starting with `~/` for your home directory

If the file does not exist, it will be replaced with an empty string.

These are useful for:

- Keeping sensitive data like API keys in separate files.
- Sharing common configuration snippets across multiple config files.

## Experimental

<Callout type="warning">
  Experimental settings may change, break, or be removed in any release without notice. Don't rely on them for stable
  workflows.
</Callout>

All experimental settings live under the `experimental` key:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "experimental": {
    "todo": true,
    "subagent_depth": 2,
    "portable_shell_scanner": true,
    "location_idle_timeout": "4 hours",
  },
}
```

### Todos

Set `todo` to `true` to give agents a `todowrite` tool for tracking multi-step work. Defaults to `false`.

### Subagent depth

`subagent_depth` sets how deeply subagents can start their own subagents. Defaults to `1`, so a subagent cannot
start another subagent.

### Portable shell scanner

Set `portable_shell_scanner` to `true` to replace the default tree-sitter shell scanner used by permission checks.
Defaults to `false`. See [Permissions](/permissions#scanner) for how it behaves.

### Location idle timeout

`location_idle_timeout` controls how long a project location can go without session activity before OpenCode unloads
its services. It takes a duration such as `"2 hours"` and defaults to `"60 minutes"`. Running sessions and background
jobs keep a location loaded. Set it to `false` to never unload idle locations. Project config can override the global
value.

```jsonc
{
  "experimental": {
    "location_idle_timeout": false,
  },
}
```

### Deprecated policies

`experimental.policies` is deprecated. Use top-level [`policies`](/policies) instead. The old key still works and
merges into `policies`.

---

### Services Www Src Docs Content Formatters (`services/www/src/docs/content/formatters.mdx`)

---
title: "Formatters"
---

OpenCode can format files after its `write`, `edit`, or `patch` tools change
them. Formatters are disabled by default, so enable them in your configuration:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": true,
}
```

## Enable

Set `formatter` to `true` to enable every built-in formatter. OpenCode runs a
built-in only when its executable and any project-specific requirements are
available.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": true,
}
```

An object also enables the built-ins and lets you override them or add custom
formatters. An empty object preserves inherited formatter settings, while `true`
resets them to the built-ins.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": {},
}
```

## Builtins

OpenCode includes these formatter definitions. Most require the named command
to be available; definitions with extra detection rules list them below.

| Formatter | Extensions | Requirement |
| --- | --- | --- |
| `gofmt` | `.go` | `gofmt` command |
| `mix` | `.ex`, `.exs`, `.eex`, `.heex`, `.leex`, `.neex`, `.sface` | `mix` command |
| `oxfmt` | `.js`, `.jsx`, `.mjs`, `.cjs`, `.ts`, `.tsx`, `.mts`, `.cts` | `oxfmt` dependency in `package.json` |
| `prettier` | `.js`, `.jsx`, `.mjs`, `.cjs`, `.ts`, `.tsx`, `.mts`, `.cts`, `.html`, `.htm`, `.css`, `.scss`, `.sass`, `.less`, `.vue`, `.svelte`, `.json`, `.jsonc`, `.yaml`, `.yml`, `.toml`, `.xml`, `.md`, `.mdx`, `.graphql`, `.gql` | `prettier` dependency in `package.json` |
| `biome` | Same extensions as `prettier` above | `biome.json` or `biome.jsonc` and an installed `@biomejs/biome` binary |
| `zig` | `.zig`, `.zon` | `zig` command |
| `clang-format` | `.c`, `.cc`, `.cpp`, `.cxx`, `.c++`, `.h`, `.hh`, `.hpp`, `.hxx`, `.h++`, `.ino`, `.C`, `.H` | `clang-format` command and `.clang-format` |
| `ktlint` | `.kt`, `.kts` | `ktlint` command |
| `ruff` | `.py`, `.pyi` | `ruff` command and a Ruff config or dependency declaration |
| `air` | `.R` | `air` command that identifies itself as the R formatter |
| `uv` | `.py`, `.pyi` | `uv` command with `uv format` support |
| `rubocop` | `.rb`, `.rake`, `.gemspec`, `.ru` | `rubocop` command |
| `standardrb` | `.rb`, `.rake`, `.gemspec`, `.ru` | `standardrb` command |
| `htmlbeautifier` | `.erb` | `htmlbeautifier` command |
| `dart` | `.dart` | `dart` command |
| `ocamlformat` | `.ml`, `.mli` | `ocamlformat` command and `.ocamlformat` |
| `terraform` | `.tf`, `.tfvars` | `terraform` command |
| `latexindent` | `.tex` | `latexindent` command |
| `gleam` | `.gleam` | `gleam` command |
| `shfmt` | `.sh`, `.bash` | `shfmt` command |
| `nixfmt` | `.nix` | `nixfmt` command |
| `rustfmt` | `.rs` | `rustfmt` command |
| `pint` | `.php` | `laravel/pint` in `composer.json` |
| `ormolu` | `.hs` | `ormolu` command |
| `cljfmt` | `.clj`, `.cljs`, `.cljc`, `.edn` | `cljfmt` command |
| `dfmt` | `.d` | `dfmt` command |

For example, enabling built-ins lets OpenCode discover and run a project-local
Prettier dependency for matching files:

```jsonc title="opencode.jsonc"
{
  "formatter": true,
}
```

## Customize

Add a named entry to change a built-in or define a custom formatter. A custom
formatter needs both `command` and `extensions` to run.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": {
    "prettier": {
      "environment": {
        "NODE_ENV": "development",
      },
      "extensions": [".js", ".ts"],
    },
    "deno-markdown": {
      "command": ["deno", "fmt", "$FILE"],
      "extensions": [".md"],
    },
  },
}
```

| Field | Type | Behavior |
| --- | --- | --- |
| `disabled` | `boolean` | Removes the named formatter when `true`. |
| `command` | `string[]` | Replaces the built-in command or defines a custom command. |
| `environment` | `Record<string, string>` | Adds environment variables while preserving the parent environment. |
| `extensions` | `string[]` | Replaces the built-in extension list or defines the custom list. Include the leading dot. |

All fields are optional. A built-in entry inherits omitted values, while a new
entry without a command or extensions cannot run.

```jsonc title="opencode.jsonc"
{
  "formatter": {
    "prettier": {
      "extensions": [".md", ".mdx"],
    },
  },
}
```

## Commands

`command` is an argument array, not a shell command string. OpenCode replaces
`$FILE` with the file's absolute path and runs the command from the active
project directory.

```jsonc title="opencode.jsonc"
{
  "formatter": {
    "custom": {
      "command": ["custom-fmt", "--write", "$FILE"],
      "extensions": [".custom"],
    },
  },
}
```

## Matching

OpenCode compares the file's final extension with `extensions`. Matching is
case-sensitive, and compound entries such as `.part.md` do not match
`notes.part.md` because its final extension is `.md`.

```jsonc title="opencode.jsonc"
{
  "formatter": {
    "markdown": {
      "command": ["deno", "fmt", "$FILE"],
      "extensions": [".md"],
    },
  },
}
```

When several formatters match, OpenCode tries them in registered order and
stops after the first successful command. Built-ins retain their built-in
order; custom entries follow in object order. If one exits unsuccessfully,
OpenCode logs the failure and tries the next match.

```jsonc title="opencode.jsonc"
{
  "formatter": {
    "preferred": {
      "command": ["preferred-fmt", "$FILE"],
      "extensions": [".foo"],
    },
    "fallback": {
      "command": ["fallback-fmt", "$FILE"],
      "extensions": [".foo"],
    },
  },
}
```

## Disable

Formatting is disabled when no config file sets `formatter`. To disable
formatting that a lower-priority file enabled, set it to `false`.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": false,
}
```

To disable one built-in while leaving the others enabled, mark its named entry
as disabled.

```jsonc title="opencode.jsonc"
{
  "formatter": {
    "prettier": {
      "disabled": true,
    },
  },
}
```

---

### Services Www Src Docs Content Instructions (`services/www/src/docs/content/instructions.mdx`)

---
title: "Instructions"
---

Add an `AGENTS.md` file to give OpenCode persistent project guidance. Use it for build commands, architecture notes, code conventions, and verification requirements.

```md title="AGENTS.md"
# Project instructions

- Run `bun typecheck` after changing TypeScript.
- Keep database queries in `src/database`.
- Do not edit generated files directly.
```

Commit project instruction files so everyone working in the repository receives the same guidance.

## Scope

Place `AGENTS.md` in the directory where its guidance should apply. OpenCode loads the global file followed by every `AGENTS.md` from the current workspace directory toward the home directory. For workspaces outside the home directory, it stops at the project root.

```text
~/.config/opencode/AGENTS.md
~/code/my-project/AGENTS.md
~/code/my-project/packages/AGENTS.md
~/code/my-project/packages/web/AGENTS.md  ← current workspace
```

In this example, all four files are loaded. They are combined in this order:

```text
~/.config/opencode/AGENTS.md
packages/web/AGENTS.md
packages/AGENTS.md
AGENTS.md
```

Keep guidance that applies everywhere in the global file. Put repository-wide guidance at the project root and more specific guidance closer to the code it covers. OpenCode combines the files and does not resolve conflicts between them.

If the workspace is outside the project root, only the global file is loaded. Set `OPENCODE_DISABLE_PROJECT_CONFIG=1` to skip project `AGENTS.md` discovery without disabling the global file.

<Callout type="note">
  OpenCode V2 recognizes `AGENTS.md` only. It does not use `CLAUDE.md` as a fallback.
</Callout>

## Discovery

Instruction files below the workspace are discovered as the agent explores the project. Reading a file or listing a directory loads any `AGENTS.md` files between that target and the workspace.

```text
my-project/                         ← current workspace
├── AGENTS.md                       loaded initially
└── packages/
    └── web/
        ├── AGENTS.md               loaded when this area is read
        └── src/
            └── app.ts              read target
```

Nested files are loaded nearest-first and deduplicated while their instruction entry remains in model-visible history. Reading the same area again does not normally inject them again. If compaction or a revert removes that entry, a later read can load the file again.

Edits to a nested file are not detected automatically after it loads. Start a new session when updated text must apply immediately.

## Ordering

The selected agent or provider system prompt is sent first. OpenCode then assembles initial instructions in this order:

```text
1. Agent or provider system prompt
2. Code Mode tool guidance, when enabled
3. MCP server, reference, and skill guidance
4. Global and project AGENTS.md files, then configured instructions
5. Built-in date and environment context
6. Session-specific instruction entries supplied through the API
```

These sources are combined rather than used as overrides. Nested `AGENTS.md` files discovered later are added to session history in discovery order.

## Updates

Edit a global or upward-discovered `AGENTS.md` while a session is running to update its guidance.

```bash
$ printf '\n- Run the integration suite before committing.\n' >> AGENTS.md
```

Before the next model request, OpenCode detects the change and adds an instruction update before delivering pending input:

```text
AGENTS.md changes
→ instruction update
→ next prompt
```

- Removing every ambient `AGENTS.md` tells the session that the previous ambient instructions no longer apply.
- A temporary read failure preserves the last known instructions instead of treating them as deleted.
- Moving a session retains its instruction state, so guidance at the destination is introduced as an update.
- Committing a session revert clears its instruction state and reloads instructions before the next prompt.

Instruction values remain privileged. Clients can see which sources changed, but not their contents.

## Configuration

Use the `instructions` array to add files, glob patterns, or HTTP(S) URLs alongside discovered `AGENTS.md` files:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "instructions": [
    "CONTRIBUTING.md",
    "docs/guidelines/*.md",
    "~/rules/opencode.md",
    "https://example.com/instructions.md",
  ],
}
```

Configured instructions load after `AGENTS.md` files, in the order they are listed. Entries from every config document are combined.

| Entry                   | Resolution                                                           |
| ----------------------- | -------------------------------------------------------------------- |
| Relative path or glob   | Searched in each directory from the workspace up to the project root |
| `~/` path               | Resolved from your home directory                                    |
| Absolute path           | Used as written; the file name may be a glob                         |
| `http://` or `https://` | Fetched when config loads, with a five-second timeout                |

- Local files update like `AGENTS.md` when they change. New files matching a glob load on the next config change.
- Missing files are skipped. A URL that cannot be fetched is skipped, or keeps its last fetched content.
- With `OPENCODE_DISABLE_PROJECT_CONFIG=1`, or when the workspace is outside the project, relative entries resolve against the global config directory.

See [Config](/config) for configuration locations and precedence.

---

### Services Www Src Docs Content Mcp Servers (`services/www/src/docs/content/mcp-servers.mdx`)

---
title: "MCP servers"
---

OpenCode connects to [Model Context Protocol](https://modelcontextprotocol.io/) servers and exposes capabilities such as tools, prompts, resources, and instructions. MCP tools consume model context, so add only the servers you need.

## Setup

Add a remote server from the project that should use it, then check its connection:

```sh
opencode mcp add context7 --url https://mcp.context7.com/mcp
opencode mcp list
```

The command writes the server to the project [configuration](/config). Add `--global` to make it available in every project:

```sh
opencode mcp add context7 --global --url https://mcp.context7.com/mcp
```

Remote servers use OAuth by default. If the list shows `needs authentication`, open OpenCode, run `/mcps`, select the server, and sign in. A connected server is ready for an agent to use:

```text
✓ context7  connected
```

## Config

To configure a server by hand, give it a unique name under `mcp.servers`. V2 does not place server names directly under `mcp`.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "servers": {
      "my-server": {
        "type": "local",
        "command": ["npx", "-y", "example-mcp-server"],
      },
    },
  },
}
```

Servers connect automatically. Use `disabled`, not an `enabled` field, to keep one configured without connecting it:

```jsonc
{
  "mcp": {
    "servers": {
      "my-server": {
        "type": "local",
        "command": ["npx", "-y", "example-mcp-server"],
        "disabled": true,
      },
    },
  },
}
```

A higher-precedence project config replaces the entire server object with the same name. Use different names for separate connections or accounts; otherwise repeat every required field in the override:

```jsonc title="opencode.jsonc"
{
  "mcp": {
    "servers": {
      "my-server": {
        "type": "remote",
        "url": "https://mcp.example.com/mcp",
      },
    },
  },
}
```

## Local

A local server is a command that OpenCode starts over the MCP stdio transport. Add one with a command after `--`:

```sh
opencode mcp add everything -- npx -y @modelcontextprotocol/server-everything
```

Pass environment variables with repeated `--env` flags:

```sh
opencode mcp add everything --env LOG_LEVEL=info -- npx -y @modelcontextprotocol/server-everything
```

Use configuration for other process options such as a working directory:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "servers": {
      "everything": {
        "type": "local",
        "command": ["npx", "-y", "@modelcontextprotocol/server-everything"],
        "cwd": ".",
        "environment": {
          "LOG_LEVEL": "info",
          "MCP_API_KEY": "{env:MCP_API_KEY}",
        },
      },
    },
  },
}
```

| Field | Required | Description |
| --- | --- | --- |
| `type` | Yes | Must be `"local"`. |
| `command` | Yes | Executable followed by its arguments. |
| `cwd` | No | Process directory. Relative paths resolve from the workspace, which is also the default. |
| `environment` | No | String variables added to OpenCode's inherited process environment. |
| `disabled` | No | Prevents connection when `true`. Defaults to `false`. |
| `codemode` | No | Set to `false` to expose tools directly instead of through Code Mode. Defaults to `true`. |
| `timeout` | No | Per-server timeout overrides. |
| `protocol` | No | `legacy` (default), `auto`, or `2026-07-28`. See [Protocol version](#protocol-version). |

Use `{env:NAME}` for environment substitution. Shell expressions such as `$NAME` are not expanded in JSON strings:

```jsonc
{
  "environment": {
    "MCP_API_KEY": "{env:MCP_API_KEY}",
  },
}
```

## Remote

A remote server uses the MCP Streamable HTTP transport and requires an absolute URL:

```sh
opencode mcp add context7 --url https://mcp.context7.com/mcp
```

Pass request headers with repeated `--header` flags. Quote `{env:NAME}` references so the shell writes them literally:

```sh
opencode mcp add context7 --url https://mcp.context7.com/mcp --header 'CONTEXT7_API_KEY={env:CONTEXT7_API_KEY}'
```

Use configuration for other options. Store secrets in environment variables rather than in the file:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "servers": {
      "context7": {
        "type": "remote",
        "url": "https://mcp.context7.com/mcp",
        "oauth": false,
        "headers": {
          "CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}",
        },
      },
    },
  },
}
```

| Field | Required | Description |
| --- | --- | --- |
| `type` | Yes | Must be `"remote"`. |
| `url` | Yes | Absolute Streamable HTTP endpoint. |
| `headers` | No | String HTTP headers sent to the endpoint. |
| `oauth` | No | OAuth settings, or `false` to disable OAuth. |
| `disabled` | No | Prevents connection when `true`. Defaults to `false`. |
| `codemode` | No | Set to `false` to expose tools directly instead of through Code Mode. Defaults to `true`. |
| `timeout` | No | Per-server timeout overrides. |
| `protocol` | No | `legacy` (default), `auto`, or `2026-07-28`. See [Protocol version](#protocol-version). |

Use `oauth: false` only when the server exclusively uses an API key or another header credential:

```jsonc
{
  "type": "remote",
  "url": "https://mcp.example.com/mcp",
  "oauth": false,
  "headers": { "Authorization": "Bearer {env:MCP_API_KEY}" },
}
```

## OAuth

OAuth is enabled for remote servers unless `oauth` is `false`. OpenCode discovers the authorization server, signs in with PKCE, and refreshes tokens. Credentials are stored outside project configuration.

Most servers need only the URL:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "servers": {
      "sentry": {
        "type": "remote",
        "url": "https://mcp.sentry.dev/mcp",
      },
    },
  },
}
```

If the server needs authentication, run `/mcps`, select it, and complete authorization in the browser. The CLI can start the same flow:

```sh
opencode mcp auth sentry
```

### Client registration

OpenCode identifies itself to the authorization server with the first method that applies:

| Method | Used when |
| --- | --- |
| Pre-registered client | `oauth.client_id` is configured. |
| [Client ID Metadata Document](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#client-id-metadata-documents) (CIMD) | The authorization server supports CIMD and public clients, and `oauth.redirect_uri` is not set. |
| [Dynamic client registration](https://datatracker.ietf.org/doc/html/rfc7591) (DCR) | Neither of the above applies. OpenCode registers a client and reuses it on later sign-ins. |

An authorization server opts into CIMD through its metadata:

```json
{
  "issuer": "https://auth.example.com",
  "client_id_metadata_document_supported": true,
  "token_endpoint_auth_methods_supported": ["none"]
}
```

With CIMD, OpenCode sends its metadata document URL as the `client_id` and skips registration:

```text
https://opencode.ai/oauth/opencode/client.json
```

The document allows the loopback redirects `http://127.0.0.1/callback` and `http://localhost/callback` without a port. Authorization servers accept any loopback port for these redirects, as [RFC 8252](https://datatracker.ietf.org/doc/html/rfc8252#section-7.3) requires, so `callback_port` works with CIMD. A custom `redirect_uri` does not, so OpenCode falls back to DCR.

If the authorization server supports neither CIMD nor DCR, configure a pre-registered client.

### Pre-registered clients

When a provider gives you client credentials, use V2's snake_case OAuth fields:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "servers": {
      "company-tools": {
        "type": "remote",
        "url": "https://mcp.example.com/mcp",
        "oauth": {
          "client_id": "{env:MCP_CLIENT_ID}",
          "client_secret": "{env:MCP_CLIENT_SECRET}",
          "scope": "tools:read tools:execute",
          "callback_port": 19876,
          "redirect_uri": "http://127.0.0.1:19876/callback",
        },
      },
    },
  },
}
```

| Field | Description |
| --- | --- |
| `client_id` | Pre-registered client ID. Takes priority over CIMD and DCR. |
| `client_secret` | Secret for a confidential client, sent in the token request body. Omit it for public clients. |
| `scope` | Space-delimited scopes to request. Defaults to the scope the server names when it rejects an unauthenticated request. |
| `callback_port` | Local callback port from `1` through `65535`. Defaults to the `redirect_uri` port, then an available ephemeral port. |
| `redirect_uri` | Pre-registered loopback URI whose path and port reach the local callback listener. Setting it disables CIMD. |
| `auth_server_metadata_url` | URL of the authorization server's OAuth or OpenID Connect metadata document. Set it when the MCP server does not publish protected resource metadata that names its authorization server. |

Remove stored OAuth credentials when you need to sign in again or switch accounts:

```sh
opencode mcp logout sentry
```

## Timeouts

Timeouts are positive integer milliseconds. Set defaults under `mcp.timeout`; a server's `timeout` object overrides matching defaults.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "timeout": {
      "startup": 45000,
      "catalog": 30000,
      "execution": 600000,
    },
    "servers": {
      "slow-tools": {
        "type": "remote",
        "url": "https://mcp.example.com/mcp",
        "timeout": {
          "catalog": 60000,
        },
      },
    },
  },
}
```

| Timeout | Default | Applies to |
| --- | --- | --- |
| `startup` | 30 seconds | Transport connection and server initialization. |
| `catalog` | 30 seconds | Listing tools, prompts, resources, and resource templates. |
| `execution` | 12 hours | Tool calls, prompt retrieval, and resource reads. |

## Protocol version

OpenCode opens every server with the classic MCP `initialize` handshake by default. Set a server's `protocol` to talk to one built on the 2026-07-28 revision:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "servers": {
      "modern": {
        "type": "remote",
        "url": "https://mcp.example.com/mcp",
        "protocol": "auto",
      },
    },
  },
}
```

| Value | Behavior |
| --- | --- |
| `legacy` | Default. Sends `initialize` and speaks protocol revisions up to 2025-11-25. |
| `auto` | Probes with `server/discover` for the 2026-07-28 revision and falls back to `legacy` when the server does not support it. |
| `2026-07-28` | Requires the 2026-07-28 revision. The connection fails against older servers. |

Probing a local `legacy` server adds a short-lived extra process and can wait up to the startup timeout when the server ignores unknown requests, so keep `auto` scoped to servers that need it.

## Names

OpenCode names a tool `<server>_<tool>`. It replaces characters other than letters, numbers, `_`, and `-` with `_`:

```text
server: context 7
tool:   resolve.library/id
name:   context_7_resolve_library_id
```

MCP prompts become commands named `<server>:<prompt>` with the same normalization. For example:

```text
/context_7:find_docs
```

Command text fills the prompt's arguments in order. Separate them with spaces and quote values that contain spaces:

```text
/context_7:find_docs react "server components"
```

Choose short server names that remain unique after normalization. Under the default Code Mode, tools are grouped by the normalized server name:

```text
tools.context_7.resolve_library_id(...)
```

## Permissions

Code Mode is the default. Set `codemode` to `false` when a server's tools must stay on the provider's native tool list:

```jsonc
{
  "mcp": {
    "servers": {
      "context7": {
        "type": "remote",
        "url": "https://mcp.context7.com/mcp",
        "codemode": false,
      },
    },
  },
}
```

Use permission actions to hide or deny tools without disconnecting their server. Match the normalized `<server>_<tool>` name:

```jsonc
{
  "permissions": [
    {
      "action": "context7_*",
      "resource": "*",
      "effect": "deny",
    },
  ],
}
```

## Resources

Agents read MCP resources through two built-in tools, `list_mcp_resources` and `read_mcp_resource`. Control them with these permission actions:

| Action | Resource |
| --- | --- |
| `opencode_list_mcp_resources` | The server name. |
| `opencode_read_mcp_resource` | `<server>:<uri>` |

For example, allow every read from the `docs` server:

```jsonc
{
  "permissions": [
    {
      "action": "opencode_read_mcp_resource",
      "resource": "docs:*",
      "effect": "allow",
    },
  ],
}
```

## Server instructions

When a server returns instructions during initialization, OpenCode adds them to the system prompt:

```text
<mcp_instructions>
  <server name="sentry">
    Search for an existing issue before creating a new one.
  </server>
</mcp_instructions>
```

For servers that use Code Mode, OpenCode adds a line that says where the agent can find the server's tools.

A server's instructions are omitted when the agent's permissions deny every one of its tools, or when they deny `execute` for a server that uses Code Mode.

## Input requests

Servers can ask for input during a call through MCP elicitation. OpenCode shows the request as a form, or as a link to open for URL requests:

```text
sentry is requesting input
```

Dismissing the form cancels the request.

## Context

For calls made on behalf of a session, OpenCode sends the session ID in `CallToolRequest.params._meta["ai.opencode/sessionID"]`. This applies to direct tools and Code Mode over stdio and Streamable HTTP:

```json
{
  "method": "tools/call",
  "params": {
    "name": "lookup",
    "arguments": { "query": "example" },
    "_meta": { "ai.opencode/sessionID": "ses_..." }
  }
}
```

The ID is request metadata, not a tool argument, so it is absent from the model-visible schema. Treat it as an opaque correlation value:

| Rule | Behavior |
| --- | --- |
| Identity | It identifies the invoking OpenCode session, not the MCP transport session. |
| Presence | It can be absent for calls without session context. |
| Security | Do not use it by itself for authentication or authorization. |
| Privacy | Remote servers receive the raw ID and may log or retain it. |

## Management

List servers and their current connection state from any project:

```sh
opencode mcp list
```

Use `/mcps` in OpenCode to view, connect, disconnect, or authenticate servers. Use the CLI to add servers and manage OAuth credentials:

```sh
opencode mcp add sentry --url https://mcp.sentry.dev/mcp
opencode mcp auth sentry
opencode mcp logout sentry
```

Run `opencode mcp auth` without a name to pick from the OAuth-capable servers:

```sh
opencode mcp auth
```

To remove a server, delete its entry from the project or global configuration where it was added:

```jsonc
{
  "mcp": {
    "servers": {},
  },
}
```

Disconnecting a server in `/mcps` does not change configuration. Edit configuration directly for OAuth client settings, timeouts, working directories, or to keep a server disconnected:

```jsonc
{
  "mcp": {
    "servers": {
      "sentry": {
        "type": "remote",
        "url": "https://mcp.sentry.dev/mcp",
        "disabled": true,
      },
    },
  },
}
```

---

### Services Www Src Docs Content Migrate V1 (`services/www/src/docs/content/migrate-v1.mdx`)

---
title: "Migrate from V1"
---

OpenCode 1 and OpenCode 2 both use the `opencode` command and are no longer installed side by side by default. Remove a
package-managed V1 installation before installing V2; the V2 curl installer replaces the V1 binary.

## Breaking changes

V2 has three intentional breaking changes:

- [Plugins](/build/plugins/migrate-v1) use a new plugin API.
- The [server API and clients](#server-api-and-clients) have new contracts.
- [Terminal client configuration](/cli/config) moves from layered `tui.json(c)` files to one global `cli.json` file (auto
  migrated).

Supported V1 functionality outside those areas is intended to remain compatible with V1. Some fields accepted by the V1
schema never had a V2 equivalent and are intentionally ignored; these are listed under
[Accepted but unsupported fields](#accepted-but-unsupported-fields).

Existing supported server config fields, agent definitions, command definitions, skills, and other files in `.opencode/`
should continue to work without changes. If supported behavior described in this guide stops working in V2, treat it as a
compatibility bug rather than an expected migration requirement.

<Callout type="tip">
  If supported V1 functionality does not work in V2, follow the issue-reporting guidance in
  [Troubleshooting](/troubleshooting) and file a compatibility issue.
</Callout>

## Install V2

Install the V2 terminal client with the [terminal startup guide](/cli).

You do not need to rewrite everything before starting V2. A practical migration is:

1. Keep your existing configuration and file-based definitions.
2. Start V2 and verify models, credentials, agents, permissions, and MCP servers.
3. Port plugins, because V1 plugin implementations do not run in V2.
4. Port integrations that call the server API.
5. Convert configuration to the native V2 shape when you are ready. This step is optional.

Keep a copy of your V1 setup while validating the migration. V1 and V2 use the same configuration locations, so do not
point V1 at files after converting them to native V2-only shapes.

## Configuration

This section covers both JSON/JSONC configuration and file-based definitions under `.opencode/`.

### Use your existing configuration

V2 reads existing system, global, and project configuration from the same locations as V1:

```text
/Library/Application Support/opencode/opencode.json(c)
/etc/opencode/opencode.json(c)
%ProgramData%\opencode\opencode.json(c)
/Library/Managed Preferences/<user>/ai.opencode.managed.plist
/Library/Managed Preferences/ai.opencode.managed.plist
~/.config/opencode/opencode.json(c)
<project>/opencode.json(c)
<project>/.opencode/opencode.json(c)
```

V2 reads these same locations. It normalizes supported V1 and native V2 fields in memory without rewriting the source
file. Existing supported V1 configuration is intended to keep working, so you do not need to convert it to try or adopt
V2.

As in V1, system configuration and macOS managed preferences have the highest precedence, so their settings override
global and project files. Their [policies](/policies#precedence), including migrated `enabled_providers` and
`disabled_providers`, also outrank global and project policies. Overriding a setting cannot stop users from adding
providers, MCP servers, agents, or plugins, so express admin-enforced restrictions as `policies` rather
than ordinary settings such as `permissions`.

### Ask OpenCode to migrate

The V1 config format remains supported. The native V2 format is optional and makes several settings more explicit and
ergonomic.

The recommended migration path is to ask OpenCode to update the configuration for you:

```text
Migrate my OpenCode configuration, including file-based definitions, from the V1 format to the native V2 format.
Preserve its behavior and all unrelated settings.
```

OpenCode can inspect the complete file, apply the relevant changes below, and avoid rewriting settings that do not need to
change. Conversion does not need to happen all at once: supported V1 and native V2 fields may coexist at the top level.
When both forms set the same canonical value, a valid native V2 value takes precedence regardless of JSON key order.

Nested mixing is intentionally bounded. OpenCode recognizes mixed V1 and V2 members within `mcp`, `compaction`, and
`experimental`, but it does not recursively infer formats inside individual agents, providers, commands, or models. Keep
each of those nested entries entirely in one format. Supported V1 syntax remains quiet by itself; malformed values,
unsupported legacy fields, and conflicting V1/V2 values produce warnings while unrelated valid settings continue to load.

### Permissions and tools

V1 groups permission effects by tool. V2 uses one ordered `permissions` array, making precedence and exceptions explicit:

```jsonc
// V1
{
  "permission": {
    "bash": {
      "git push *": "ask"
    },
    "edit": "allow"
  },
  "tools": {
    "websearch": false
  }
}

// V2
{
  "permissions": [
    { "action": "shell", "resource": "git push *", "effect": "ask" },
    { "action": "edit", "resource": "*", "effect": "allow" },
    { "action": "websearch", "resource": "*", "effect": "deny" }
  ]
}
```

Permission actions also changed: `bash` is now `shell`, `task` is now `subagent`, and `write` and `patch` are now `edit`.
See [Permissions](/permissions) for the ordered V2 rule format.

Todos are off by default in V2. To turn them on, use the experimental flag. It may change or be removed in a future
release; see [Experimental](/config#experimental).

```jsonc
{
  "experimental": {
    "todo": true,
  },
}
```

<Callout type="warning">
  V1 asks before accessing paths outside the project. V2 does not: `external_directory` is allowed by default. To keep
  the V1 behavior, add `{ "action": "external_directory", "resource": "*", "effect": "ask" }` to `permissions`.
</Callout>

### Agents and modes

The singular `agent` and deprecated `mode` maps become `agents`. Agent fields become more consistent with the rest of the
V2 config:

```jsonc
// V1
{
  "agent": {
    "reviewer": {
      "prompt": "Review for correctness and missing tests.",
      "model": "anthropic/claude-sonnet-4-5",
      "variant": "high",
      "disable": false,
      "permission": {
        "edit": "deny"
      }
    }
  }
}

// V2
{
  "agents": {
    "reviewer": {
      "system": "Review for correctness and missing tests.",
      "model": "anthropic/claude-sonnet-4-5#high",
      "disabled": false,
      "permissions": [
        { "action": "edit", "resource": "*", "effect": "deny" }
      ]
    }
  }
}
```

`prompt` becomes `system`, `disable` becomes `disabled`, and a separate `variant` joins the model reference after `#`.
`temperature`, `top_p`, and provider-specific `options` move under `request.body`. `maxSteps` becomes `steps`. Entries from
the old `mode` map become primary agents.

### Snapshots

Rename the singular `snapshot` field to `snapshots`. Its boolean value does not change:

```jsonc
// V1
{ "snapshot": false }

// V2
{ "snapshots": false }
```

### Media

Rename the singular `attachment` object to `media`. Nested image settings keep the same names:

```jsonc
// V1
{ "attachment": { "image": { "auto_resize": true } } }

// V2
{ "media": { "image": { "auto_resize": true } } }
```

### MCP servers

V2 groups servers under `mcp.servers`, replaces `enabled` with the inverse `disabled`, and separates timeout purposes:

```jsonc
// V1
{
  "mcp": {
    "playwright": {
      "type": "local",
      "command": ["npx", "@playwright/mcp"],
      "enabled": true,
      "timeout": 30000
    }
  }
}

// V2
{
  "mcp": {
    "servers": {
      "playwright": {
        "type": "local",
        "command": ["npx", "@playwright/mcp"],
        "disabled": false,
        "timeout": {
          "catalog": 30000,
          "execution": 30000
        }
      }
    }
  }
}
```

Remote OAuth fields use snake case: `clientId` becomes `client_id`, `clientSecret` becomes `client_secret`,
`callbackPort` becomes `callback_port`, and `redirectUri` becomes `redirect_uri`. The V1 `experimental.mcp_timeout` value
also becomes the default `mcp.timeout.catalog` and `mcp.timeout.execution` values. See [MCP servers](/mcp-servers).

### Compaction

V2 groups the retained-context token budget under `keep` and gives the reserve a clearer name:

```jsonc
// V1
{
  "compaction": {
    "preserve_recent_tokens": 8000,
    "reserved": 20000
  }
}

// V2
{
  "compaction": {
    "keep": {
      "tokens": 8000
    },
    "buffer": 20000
  }
}
```

`auto` keeps its name. V2 has no native `tail_turns` or `prune` field; both legacy fields are ignored with a warning. Recent
context is retained by token budget instead. See [Compaction](/compaction).

### Skills

V1 separates extra skill paths and URLs. V2 combines both into one ordered array:

```jsonc
// V1
{
  "skills": {
    "paths": ["./team-skills"],
    "urls": ["https://example.com/skills/"]
  }
}

// V2
{
  "skills": ["./team-skills", "https://example.com/skills/"]
}
```

Existing skill files and automatic `.opencode/skills/` discovery do not change. See [Skills](/skills).

### Commands

Rename the singular `command` map to `commands` and `subtask` to `subagent`. Join a separate model `variant` to the model reference:

```jsonc
// V1
{
  "command": {
    "review": {
      "template": "Review the current changes.",
      "model": "anthropic/claude-sonnet-4-5",
      "variant": "high",
      "subtask": true
    }
  }
}

// V2
{
  "commands": {
    "review": {
      "template": "Review the current changes.",
      "model": "anthropic/claude-sonnet-4-5#high",
      "subagent": true
    }
  }
}
```

`template`, `description`, and `agent` keep their names. Legacy `subtask` remains accepted; delegated commands now run
automatically in the background and report their results to the parent session. Existing Markdown command definitions remain supported.
See [Commands](/commands).

### References

Rename the deprecated singular `reference` map to `references`:

```jsonc
// V1
{ "reference": { "docs": "../docs" } }

// V2
{ "references": { "docs": "../docs" } }
```

V1 already accepts `references`, so no change is needed when the file uses it. Reference entries keep the
same shapes. See [References](/references).

### Providers

Rename the singular `provider` map to `providers`. V2 separates the runtime package, endpoint, and request settings:

```jsonc
// V1
{
  "provider": {
    "acme": {
      "npm": "@ai-sdk/openai-compatible",
      "api": "https://llm.example.com/v1",
      "options": {
        "apiKey": "{env:ACME_API_KEY}"
      }
    }
  }
}

// V2
{
  "providers": {
    "acme": {
      "package": "aisdk:@ai-sdk/openai-compatible",
      "settings": {
        "baseURL": "https://llm.example.com/v1",
        "apiKey": "{env:ACME_API_KEY}"
      }
    }
  }
}
```

V1 `npm` becomes `package`, and AI SDK packages receive the `aisdk:` prefix. `api` becomes `settings.baseURL`. Provider
`options` are separated into `settings`, `headers`, and `body` according to their request role. `options.setCacheKey`
becomes `compatibility.supportsPromptCacheKey` on the provider. See [Providers](/providers).

V2 consolidated two legacy provider namespaces:

| V1 provider ID             | Canonical V2 provider ID |
| -------------------------- | ------------------------ |
| `azure-cognitive-services` | `azure`                  |
| `google-vertex-anthropic`  | `google-vertex`          |

Migration of unambiguous V1 provider, agent, command, and provider-filter fields uses these canonical IDs. The shared
top-level `model` field keeps its exact provider ID because the same syntax is valid in native V2 config; update that field
to the canonical ID when migrating a legacy built-in provider.

### Models and variants

Models remain nested under their provider, but several model fields become more explicit:

- `id` becomes `modelID`.
- `tool_call` and `modalities` become `capabilities.tools`, `capabilities.input`, and `capabilities.output`.
- A `status` of `"deprecated"` becomes `disabled: true`.
- Cache costs move from `cache_read` and `cache_write` to `cache.read` and `cache.write`.
- Provider-specific `options` become `settings`.
- A V1 variants object becomes a V2 array with an `id` on each entry.

```jsonc
// V1
{
  "variants": {
    "high": {
      "reasoningEffort": "high"
    }
  }
}

// V2
{
  "variants": [
    {
      "id": "high",
      "settings": {
        "reasoningEffort": "high"
      }
    }
  ]
}
```

See [Models](/models) for the complete native model shape.

### Supported fields without direct native equivalents

Most fields that keep the same shape, including `shell`, `model`, `default_agent`, `watcher`, `formatter`,
`instructions`, `enterprise`, and `tool_output`, require no migration.

V2 accepts and preserves `lsp` configuration, but it does not run language servers, expose LSP tools, or produce LSP
diagnostics. Replace workflows that depend on those capabilities with the project's lint, typecheck, or compiler commands.

The V1 provider filters do not have one-to-one native V2 config fields, but their behavior remains supported through
[policies](/policies):

- `enabled_providers` becomes an internal deny-by-default provider policy followed by allows for the listed providers.
- `disabled_providers` becomes internal deny policies for the listed providers.
- `autoupdate` becomes `update`: `false` maps to `"disable"`, `"notify"` maps to `"notify"`, and `true` maps to `"auto"`.
- `small_model` becomes the `model` selection for the built-in `title` agent. Native V2 configuration should use
  `agents.title.model` instead.

You may keep these fields in V1 syntax. OpenCode normalizes them without warning.

### Accepted but unsupported fields

The V1 schema also accepted fields that have no supported V2 behavior. V2 ignores these values and emits a warning so
they are not mistaken for active configuration:

- `logLevel`: use `OPENCODE_LOG_LEVEL` when starting OpenCode.
- `server`: use the V2 service and explicit server options; the server API is an intentional breaking change.
- Top-level `subagent_depth`: use `experimental.subagent_depth` instead.
- `compaction.tail_turns` and `compaction.prune`: V2 uses `compaction.keep.tokens` and checkpoint-based compaction instead.
- Agent `name` inside V1 JSON configuration.
- An enabled-only V1 MCP entry without a `type`.
- V1 experimental fields `batch_tool`, `openTelemetry`, `primary_tools`, and `continue_loop_on_deny`.
- V1 provider fields `id`, `whitelist`, and `blacklist`.
- V1 provider-model fields `release_date`, `attachment`, `reasoning`, `temperature`, `experimental`, a non-`deprecated`
  `status`, and boolean `interleaved`.

Ignoring these fields is intentional and is not a compatibility regression. If V2 does not preserve behavior identified
as supported elsewhere in this guide, follow the issue-reporting guidance in [Troubleshooting](/troubleshooting).

### Agent files

V1 agent files may use `agent/`, `agents/`, `mode/`, or `modes/`. V2 still discovers all four directories. The preferred
V2 location is:

```text
.opencode/agents/<name>.md
```

Files under a V1 `mode/` or `modes/` directory represent primary agents. When moving one into `agents/`, add
`mode: primary` to its frontmatter. Files under `agent/` can move to `agents/` without changing their path-derived ID.

When converting the frontmatter to native V2 fields:

- Keep the Markdown body as the agent's system instructions.
- Rename `prompt` to `system` when it appears in JSON configuration; file bodies do not need a `system` field.
- Rename `disable` to `disabled` and `permission` to `permissions`.
- Join `model` and `variant` as `provider/model#variant`.
- Move `temperature`, `top_p`, and provider-specific options under `request.body`.

V1 agent frontmatter is deprecated but still translated automatically. Each file is read as one format. A file that
uses any of `permissions`, `request`, `system`, or `disabled` is read as V2, and V1 fields in it, such as `name`,
`tools`, `permission`, or `temperature`, are ignored with a warning in the log. Other files that use V1 fields are read
as V1. Convert a file's frontmatter all at once rather than mixing the two formats. See [Agents](/agents).

### Command files

V1 command files may use `command/` or `commands/`. V2 discovers both. The preferred location is:

```text
.opencode/commands/<name>.md
```

Move files from `command/` to the same relative path under `commands/` to preserve command names. The Markdown body remains
the command template, and `description` and `agent` frontmatter keep the same names. Rename `subtask` to `subagent` to use
the native name for background delegation. If frontmatter has separate
`model` and `variant` fields, append the variant to the model and remove `variant`:

```yaml
# V1
model: anthropic/claude-sonnet-4-5
variant: high
subtask: true

# V2
model: anthropic/claude-sonnet-4-5#high
subagent: true
```

See [Commands](/commands).

### Skill files

V2 discovers skills from both `.opencode/skill/` and `.opencode/skills/`. The preferred layout is:

```text
.opencode/skills/<skill-id>/SKILL.md
```

Move the complete skill directory, not only `SKILL.md`, so relative scripts, references, and other supporting files remain
available. Keep the directory name stable to preserve the skill ID. Existing skill frontmatter and Markdown bodies do not
require a V2 rewrite. See [Skills](/skills).

### Instruction files

Existing `AGENTS.md` files stay in place. V2 discovers the global `~/.config/opencode/AGENTS.md` and ambient `AGENTS.md`
files from the current directory up to home. For projects outside home, discovery stops at the project root.

If a V1 setup relied on a `CLAUDE.md` fallback, move that guidance into the applicable `AGENTS.md`. V2 currently only
discovers `AGENTS.md`; because non-API V1 behavior is intended to remain compatible, also file a compatibility issue with
the affected project details. See [Instructions](/instructions).

## Terminal client configuration

V2 replaces layered V1 `tui.json(c)` files with one global terminal client configuration file:

```text
~/.config/opencode/cli.json
```

The terminal client owns this file; the background service does not load it. When `cli.json` is absent, the first V2
terminal client startup migrates supported global `tui.json` settings and persisted preferences while leaving V1 files
unchanged. Project-local client configuration is not migrated because V2 client configuration is global. See
[CLI settings](/cli/config) for the current client settings reference.

## Plugins

Rename `plugin` to `plugins`. Replace a package-and-options tuple with an object:

```jsonc
// V1
{
  "plugin": ["opencode-example-plugin", ["./plugin/local.ts", { "enabled": true }]]
}

// V2
{
  "plugins": [
    "opencode-example-plugin",
    {
      "package": "./plugin/local.ts",
      "options": { "enabled": true }
    }
  ]
}
```

V2 discovers local plugins from both `.opencode/plugin/` and `.opencode/plugins/`; use `.opencode/plugins/` for V2 files.

<Callout type="warning">
  V1 plugin implementations do not run in V2. Moving a file or renaming its config entry is not enough.
</Callout>

Port entrypoints, hooks, tools, events, and package exports with the dedicated
[plugin migration guide](/build/plugins/migrate-v1).

## Server API and clients

OpenCode 2 has a revised, more ergonomic server API and a new set of clients. Integrations that call the V1 server API
must migrate to the V2 API.

Use the `@opencode/client` package to access the released V2 API. See the generated [API reference](/api) for its
endpoints, request types, and responses.

## Verify your setup

Verify your model, provider credentials, agents, permissions, MCP servers, and plugins in a project before relying on V2
for regular work. Keep your V1 setup until you have confirmed the V2 behavior you need, and do not point V1 at
configuration that you have converted to the native V2 shape.

---

### Services Www Src Docs Content Models (`services/www/src/docs/content/models.mdx`)

---
title: "Models"
---

Choose a model for the current session with `/models`:

```text
/models
```

OpenCode lists models from [models.dev](https://models.dev), provider integrations, and your configuration. The selector
only shows enabled models whose provider is available in the current project. Connect providers in
[Providers](/providers).

## Select

Pick an entry from `/models` instead of guessing its provider or model ID. The selection applies to the current session
and does not change your configuration.

```text
anthropic/claude-sonnet-4-5
```

Availability is project-specific:

- The model must be enabled.
- Its provider must be available in the current project.
- Credentials and configuration from another project do not carry over automatically.

## Runs

Use `--model` to choose a model for one command-line run without changing the configured default:

```bash
opencode run --model anthropic/claude-sonnet-4-5 "Refactor parseToken"
```

Agents and commands can also choose their own model. See [Agents](/agents) and [Commands](/commands).

## Defaults

Set `model` in `opencode.json` or `opencode.jsonc` to choose the default for new work:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "model": "anthropic/claude-sonnet-4-5",
}
```

The configured model becomes the catalog default when it is enabled and its provider is available. Otherwise, OpenCode
falls back to the newest available supported model.

- A model already selected for a session takes precedence over the configured default.
- Switching a session's model does not rewrite the config file.
- The root `model` currently retains only the default provider and model, not a variant.

See [Config](/config) for configuration locations and precedence.

## Free models

Set `OPENCODE_DISABLE_FREE_MODELS=1` (or `true`) on the server process to hide [free OpenCode models](/console/models#free-models):

```bash
OPENCODE_DISABLE_FREE_MODELS=1 opencode serve
```

For the shared background server:

```bash
opencode service set env OPENCODE_DISABLE_FREE_MODELS 1
```

Free means an `opencode` or `opencode-go` model with no input price. These models disappear from the catalog and defaults;
explicitly selecting one fails with `Model unavailable`. Signed out, the `opencode` provider is absent until you connect
an OpenCode Console account or set `OPENCODE_API_KEY`, which restores its paid models.

## Variants

Variants are named options for one model, often used for reasoning effort or token budgets. Add `#variant` when selecting
one for a run, session, agent, or command:

```bash
opencode run --model openai/gpt-5.2#high "Review this migration plan"
```

Variant names come from the selected model's current catalog metadata. Names such as `low`, `high`, and `max` are not
available for every model, and an unknown variant produces a model-resolution error.

Define new variants, or replace catalog variants with the same ID, in the model's `variants` array:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "openai": {
      "models": {
        "gpt-5.2": {
          "settings": {
            "reasoningEffort": "medium",
          },
          "variants": [
            {
              "id": "fast",
              "settings": {
                "reasoningEffort": "low",
              },
            },
            {
              "id": "deep",
              "settings": {
                "reasoningEffort": "high",
                "reasoningSummary": "auto",
              },
            },
          ],
        },
      },
    },
  },
}
```

Each variant can contain `settings`, `headers`, and `body`. Its values are applied after provider and model values.

To replace a model's reasoning variants, describe its reasoning controls in `capabilities.reasoning`, using the
[models.dev](https://models.dev) v2 shape. OpenCode builds the variants for the model's package from them:

```jsonc title="opencode.jsonc"
{
  "providers": {
    "openai": {
      "models": {
        "gpt-5.2": {
          "capabilities": {
            "reasoning": {
              "supported": true,
              "effort": ["low", "medium", "high"],
            },
          },
        },
      },
    },
  },
}
```

| Field       | Purpose                                                                    |
| ----------- | -------------------------------------------------------------------------- |
| `supported` | Whether the model reasons. `false`, or `true` without controls, adds no variants. |
| `toggle`    | Adds a `none` variant that turns reasoning off.                             |
| `effort`    | Effort levels to offer. `default` keeps the provider default and adds no variant. |
| `budget`    | Optional `min` and `max` thinking tokens. Ignored when `effort` is set.     |

Variants listed in `variants` are applied on top of the ones built from `capabilities.reasoning`.

## Options

Provider and model entries can customize requests with `settings`, `headers`, and `body`:

```jsonc title="opencode.jsonc"
{
  "providers": {
    "openai": {
      "settings": {
        "baseURL": "https://api.example.com/v1",
      },
      "headers": {
        "X-Team": "platform",
      },
      "models": {
        "gpt-5.2": {
          "settings": {
            "reasoningEffort": "high",
          },
          "body": {
            "store": false,
          },
        },
      },
    },
  },
}
```

| Field      | Purpose                                                            |
| ---------- | ------------------------------------------------------------------ |
| `settings` | Provider-package options such as `baseURL` or `reasoningEffort`.  |
| `headers`  | Additional HTTP request headers.                                 |
| `body`     | Provider-specific request body fields.                            |

OpenCode applies provider values first, model values second, and the selected variant last.

- Nested `settings` and `body` objects are merged.
- Later arrays and scalar values replace earlier values.
- Header names are matched case-insensitively.
- Options are provider-specific and may be ignored or rejected by another provider package.

## Aliases

Use `modelID` to give an API model a friendlier catalog ID:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "model": "openai/coding-default",
  "providers": {
    "openai": {
      "models": {
        "coding-default": {
          "modelID": "gpt-5.2",
          "name": "Coding default",
          "capabilities": {
            "tools": true,
            "input": ["text", "image"],
            "output": ["text"],
          },
          "limit": {
            "context": 200000,
            "output": 32000,
          },
        },
      },
    },
  },
}
```

Here, `openai/coding-default` is the selectable reference and `gpt-5.2` is sent to the provider. For a model that is not
already in the catalog, OpenCode assumes:

- Tool support, text and image input, and text output.
- A 200,000-token context limit and 32,000-token output limit.
- An unspecified input limit.

These are fallback assumptions, not detected capabilities. Set accurate `capabilities` and `limit` values when known;
explicit values replace the fallbacks. Add `disabled: true` to hide a model from the available catalog:

```jsonc title="opencode.jsonc"
{
  "providers": {
    "openai": {
      "models": {
        "legacy-model": {
          "disabled": true,
        },
      },
    },
  },
}
```

## Reasoning

For an OpenAI-compatible model that streams reasoning in a custom assistant-message field, set
`compatibility.reasoningField`:

```jsonc title="opencode.jsonc"
{
  "providers": {
    "local": {
      "models": {
        "reasoner": {
          "compatibility": {
            "reasoningField": "reasoning_content",
          },
        },
      },
    },
  },
}
```

OpenCode recognizes `reasoning`, `reasoning_content`, and `reasoning_text`, and also accepts another provider-specific
string. It reads streamed reasoning from that field and restores the field when sending prior assistant messages back to
the model.

## Prompt caching

OpenCode places prompt-cache breakpoints automatically on routes that are known to need them, such as Anthropic. When
Claude models are served through an OpenAI-compatible proxy such as LiteLLM, OpenCode cannot tell that they need
Anthropic-style `cache_control` breakpoints. Set `compatibility.cacheFormat` on those Claude models:

```jsonc title="opencode.jsonc"
{
  "providers": {
    "litellm": {
      "package": "@opencode/ai/providers/openai-compatible",
      "settings": { "baseURL": "https://litellm.example.com/v1" },
      "models": {
        "claude-sonnet-5": {
          "compatibility": { "cacheFormat": "anthropic" },
        },
        "claude-opus-5-5": {
          "compatibility": { "cacheFormat": "anthropic" },
        },
        // Other models on the same proxy cache automatically and need no setting.
        "gpt-6.1": {},
      },
    },
  },
}
```

OpenCode then marks the last tool definition, the system prompt, and the latest message with
`cache_control: { "type": "ephemeral" }`, which uses the endpoint's default five-minute cache lifetime. Use `"alibaba"`
for Alibaba Model Studio models, which accept the same markers but ignore them on tool definitions. Set
`compatibility.cacheFormat` on the provider instead when every model it serves accepts the same format.

## Local

OpenCode automatically discovers models from Ollama, LM Studio, and vLLM at their default local addresses. You can also
configure any OpenAI-compatible server manually.

```text
ollama/gemma3:4b
lmstudio/google/gemma-4-26b-a4b
vllm/Qwen/Qwen3-Coder-30B-A3B-Instruct
```

### Ollama

With Ollama listening at `http://127.0.0.1:11434`, select a discovered model with the `ollama` provider ID:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "model": "ollama/gemma3:4b",
}
```

OpenCode refreshes the inventory in the background and reads context, vision, and tool-use capabilities from Ollama.
Embedding-only models are excluded.

For another host or port, set Ollama's OpenAI-compatible URL. Discovery still uses the native Ollama API at the same
path prefix:

```jsonc title="opencode.jsonc"
{
  "providers": {
    "ollama": {
      "settings": {
        "baseURL": "http://127.0.0.1:5678/v1",
        "apiKey": "{env:OLLAMA_API_KEY}",
      },
    },
  },
}
```

- Omit `apiKey` when the endpoint does not require bearer authentication.
- Disable discovery with `"plugins": ["-opencode.provider.ollama"]`.

### LMStudio

With an unauthenticated LM Studio server at `http://127.0.0.1:1234`, select a discovered model with the `lmstudio`
provider ID:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "model": "lmstudio/google/gemma-4-26b-a4b",
}
```

OpenCode refreshes the inventory in the background and reads context, vision, and tool-use capabilities from LM Studio.
Embedding models are excluded.

For another host or port, set the OpenAI-compatible URL. Models are still discovered automatically:

```jsonc title="opencode.jsonc"
{
  "providers": {
    "lmstudio": {
      "settings": {
        "baseURL": "http://127.0.0.1:5678/v1",
        "apiKey": "{env:LMSTUDIO_API_KEY}",
      },
    },
  },
}
```

- Omit `apiKey` when LM Studio authentication is disabled.
- Disable discovery with `"plugins": ["-opencode.provider.lmstudio"]`.

### vLLM

With vLLM listening at `http://127.0.0.1:8000`, select a discovered model with the `vllm` provider ID:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "model": "vllm/Qwen/Qwen3-Coder-30B-A3B-Instruct",
}
```

OpenCode checks `/health`, refreshes `/v1/models` in the background, uses the reported `max_model_len` as the context
limit, and includes only model cards owned by `vllm`.

Discovered models advertise text input and output, but not vision or tools. vLLM enables tool calling with server flags
such as `--enable-auto-tool-choice` and `--tool-call-parser`, which discovery does not report.

For another endpoint or an authenticated server, set its OpenAI-compatible URL:

```jsonc title="opencode.jsonc"
{
  "providers": {
    "vllm": {
      "settings": {
        "baseURL": "http://127.0.0.1:9000/v1",
        "apiKey": "{env:VLLM_API_KEY}",
      },
    },
  },
}
```

- Omit `apiKey` when authentication is disabled.
- Disable discovery with `"plugins": ["-opencode.provider.vllm"]`.
- Path-prefixed proxies are supported. For example, `https://example.com/vllm/v1` checks `/vllm/health` and discovers
  `/vllm/v1/models`.

### Compatible

For another OpenAI-compatible server, define its provider package, endpoint, and at least one model:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "model": "local/coder",
  "providers": {
    "local": {
      "name": "Local server",
      "package": "@opencode/ai/providers/openai-compatible",
      "settings": {
        "baseURL": "http://127.0.0.1:1234/v1",
      },
      "models": {
        "coder": {
          "modelID": "model-name-on-server",
          "capabilities": {
            "tools": true,
            "input": ["text"],
            "output": ["text"],
          },
          "limit": {
            "context": 32768,
            "output": 8192,
          },
        },
      },
    },
  },
}
```

Use the server's real model name, limits, input and output types, and tool support. OpenCode cannot detect whether the
custom-model fallback values are accurate. If the endpoint requires a key, add `apiKey` to `settings` with an environment
substitution such as `"apiKey": "{env:LOCAL_API_KEY}"`; do not commit secrets.

## References

Model selectors use `provider/model` with an optional `#variant`:

```text
openai/gpt-5.2
openai/gpt-5.2#high
openrouter/anthropic/claude-sonnet-4.5#high
```

| Part       | Rule                                                       |
| ---------- | ---------------------------------------------------------- |
| Provider   | Ends at the first `/`; cannot contain `/` or `#`.          |
| Model      | May contain additional `/` characters; cannot contain `#`. |
| Variant    | Follows `#` when present.                                  |
| Casing     | Provider and model IDs are case-sensitive.                 |

Use catalog IDs rather than provider display names. Root, agent, and command `model` fields accept the string form above
or an expanded object:

```jsonc
{
  "model": {
    "providerID": "openrouter",
    "model": "anthropic/claude-sonnet-4.5",
  },
}
```

The expanded form is useful for generated or programmatic configuration.

## Caveats

Keep these rules in mind when configuring models:

```jsonc
{
  "model": "openai/gpt-5.2"
}
```

- A selector object uses `model`; a provider catalog entry uses `modelID` for the ID sent to the provider.
- Although the root selection shape accepts a variant, the V2 catalog default does not retain it. Select variants for a
  session, run, agent, or command instead.
- Model options are provider-specific. Another provider package may ignore or reject them.
- Catalog data, credentials, and configuration are location-scoped. A model available in one project may be unavailable
  in another.
- Configuration files normally reload automatically. A model request already in progress keeps the settings it started
  with.

---

### Services Www Src Docs Content Network (`services/www/src/docs/content/network.mdx`)

---
title: Network
description: Configure proxies and custom certificate authorities.
---

Set the standard proxy variables and exclude loopback addresses. OpenCode uses local HTTP connections between the CLI and
its background service, so the loopback exclusion is required when a proxy is configured in the CLI environment.

```bash
export HTTP_PROXY=http://proxy.example.com:8080
export HTTPS_PROXY=http://proxy.example.com:8080
export NO_PROXY=localhost,127.0.0.1,::1

opencode
```

`HTTP_PROXY` handles HTTP destinations and `HTTPS_PROXY` handles HTTPS destinations. The proxy URL itself can use `http://`
for both variables. `NO_PROXY` is a comma-separated list of hosts and addresses that connect directly.

## Service

Shell exports affect a background service only when that service starts from the shell. Persist the variables in the managed
service configuration so later service starts use the same network settings.

```bash
opencode service set env HTTP_PROXY http://proxy.example.com:8080
opencode service set env HTTPS_PROXY http://proxy.example.com:8080
opencode service set env NO_PROXY localhost,127.0.0.1,::1
opencode service start
```

Changing a managed environment variable stops the running service. `service start` starts it again with the new environment.
Keep `NO_PROXY` in the CLI shell too when that shell sets a proxy, because managed service variables apply to the server
process, not the CLI process.

Remove a persisted variable with `service unset env`:

```bash
opencode service unset env HTTPS_PROXY
```

## Authentication

For a proxy that accepts URL credentials, include the username and password in each proxy URL that needs authentication.
Percent-encode characters such as `@`, `:`, and `/` inside either credential.

```bash
export HTTPS_PROXY='http://user:p%40ssword@proxy.example.com:8080'
```

For the background service, persist the complete URL. The value is stored in the private service configuration and is
shown by `opencode service get env`, so do not share that output.

```bash
opencode service set env HTTPS_PROXY 'http://user:p%40ssword@proxy.example.com:8080'
```

## Certificates

Set `NODE_EXTRA_CA_CERTS` to a PEM file when the proxy or destination uses a certificate signed by a private certificate
authority. The extra authorities are added to the runtime trust store when the process starts.

```bash
export NODE_EXTRA_CA_CERTS=/etc/company/ca.pem
opencode --standalone
```

Persist the file path for the background service, then restart it:

```bash
opencode service set env NODE_EXTRA_CA_CERTS /etc/company/ca.pem
opencode service start
```

## Foreground

`--standalone` and `serve` use the environment of their own process. `opencode service set env` does not configure these
processes.

```bash
HTTP_PROXY=http://proxy.example.com:8080 \
HTTPS_PROXY=http://proxy.example.com:8080 \
NO_PROXY=localhost,127.0.0.1,::1 \
opencode --standalone
```

Apply the same pattern to a foreground server:

```bash
HTTPS_PROXY=http://proxy.example.com:8080 \
NO_PROXY=localhost,127.0.0.1,::1 \
opencode serve
```

## Verify

Check that the CLI can reach the background service after applying the settings:

```bash
opencode api get /api/info
```

A successful health response verifies the local client-to-service connection. Run a normal provider request to verify the
service's outbound proxy and certificate path.

---

### Services Www Src Docs Content Permissions (`services/www/src/docs/content/permissions.mdx`)

---
title: "Permissions"
---

Permissions control whether an agent may perform an action on a resource.

## Configure

A common setup is to ask before running shell commands, allow routine Git
inspection, and always block pushes. Add these ordered rules to `opencode.jsonc`:

```jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "permissions": [
    { "action": "shell", "resource": "*", "effect": "ask" },
    { "action": "shell", "resource": "git status *", "effect": "allow" },
    { "action": "shell", "resource": "git diff *", "effect": "allow" },
    { "action": "shell", "resource": "git push *", "effect": "deny" },
  ],
}
```

The last matching rule wins, so the specific exceptions follow the broad rule.

<Callout type="warning">
  V1 uses different field and action names. In V2, use `permissions`, `shell`, and `subagent` instead of `permission`,
  `bash`, and `task`.
</Callout>

## Rules

Each rule requires three string fields:

| Field      | Meaning                                                                    |
| ---------- | -------------------------------------------------------------------------- |
| `action`   | Tool permission action                                                     |
| `resource` | Value being used, such as a path, command, URL, query, skill ID, or agent ID |
| `effect`   | `allow`, `deny`, or `ask`                                                   |

```jsonc
{
  "permissions": [
    { "action": "read", "resource": "*", "effect": "allow" },
    { "action": "read", "resource": "*.env", "effect": "deny" },
  ],
}
```

| Effect  | Result                              |
| ------- | ----------------------------------- |
| `allow` | Continue without prompting          |
| `deny`  | Block the operation                 |
| `ask`   | Wait for a decision from the client |

If no rule matches, OpenCode uses `ask`.

## Matching

Actions and resources use simple whole-value wildcards:

| Pattern | Match                                      |
| ------- | ------------------------------------------ |
| `*`     | Zero or more characters, including `/`    |
| `?`     | Exactly one character                     |
| Other   | The literal character                     |

```jsonc
{
  "permissions": [
    { "action": "edit", "resource": "packages/docs/*.mdx", "effect": "allow" },
  ],
}
```

This pattern matches the entire normalized path. Backslashes are normalized to
slashes, and matching is case-insensitive on Windows.

A shell pattern ending in ` *` also matches the command without arguments:

```jsonc
{ "action": "shell", "resource": "git status *", "effect": "allow" }
```

This matches both `git status` and `git status --short`.

OpenCode combines rules in order and uses the last match. Lower-priority
configuration is loaded first, global rules are appended next, and agent rules
are appended last.

```jsonc
{
  "permissions": [
    { "action": "read", "resource": "*", "effect": "allow" },
    { "action": "read", "resource": "secrets/*", "effect": "deny" },
  ],
}
```

Operations may check several resources, such as a patch that touches multiple
files. Any `deny` denies the operation; otherwise any `ask` asks; otherwise the
operation is allowed.

## Actions

V2 action names are strings, so plugins may define more actions. Built-in tools
currently use these actions and resources:

| Action               | Resource                                                                    |
| -------------------- | --------------------------------------------------------------------------- |
| `read`               | Location-relative internal path or canonical absolute external path         |
| `edit`               | Target path for `edit`, `write`, and `patch`                                |
| `glob`               | Requested glob pattern                                                      |
| `grep`               | Requested regular expression, not the search path                           |
| `shell`              | Scanner-produced command string; compound commands may produce several      |
| `subagent`           | Target agent ID                                                             |
| `skill`              | Skill ID                                                                    |
| `question`           | `*`                                                                         |
| `webfetch`           | Requested URL                                                               |
| `websearch`          | Search query                                                                |
| `external_directory` | Canonical external directory boundary, normally ending in `/*`              |
| `<server>_<tool>`    | `*` for an MCP tool; unsupported characters in both names become `_`        |
| `opencode_list_mcp_resources` | MCP server name                                                    |
| `opencode_read_mcp_resource`  | `<server>:<uri>`                                                   |
| `execute`            | `*`; a deny removes Code Mode and the tools reached only through it, while nested tools enforce their rules |

For example, allow one skill and deny all other skills:

```jsonc
{
  "permissions": [
    { "action": "skill", "resource": "*", "effect": "deny" },
    { "action": "skill", "resource": "effect", "effect": "allow" },
  ],
}
```

`doom_loop` and `lsp` are not current V2 Core permission actions.

## Directories

A path outside both the active Location and its non-root project worktree is
checked against `external_directory` before its `read` or `edit` rules. The
default policy allows `external_directory`, so external paths are not prompted
unless you add a rule. To be asked before any access outside the project:

```jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "permissions": [
    { "action": "external_directory", "resource": "*", "effect": "ask" },
  ],
}
```

Narrower rules after it can allow or deny specific directories:

```jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "permissions": [
    { "action": "external_directory", "resource": "~/projects/reference/*", "effect": "allow" },
    { "action": "read", "resource": "~/projects/reference/*", "effect": "allow" },
    { "action": "edit", "resource": "~/projects/reference/*", "effect": "deny" },
  ],
}
```

This applies to external paths used by `read`, `edit`, `write`, and `patch`.
Shell checks its external working directory and directories inferred by its
scanner before checking `shell` resources.

For `external_directory`, `read`, and `edit`, a leading `~`, `~/`, `$HOME`, or
`$HOME/` is expanded when configuration loads:

```jsonc
{ "action": "read", "resource": "$HOME/reference/*", "effect": "allow" }
```

Shell resources remain raw command text and are not home-expanded.

<Callout type="warning">
  `shell` runs with the host user's filesystem, process, and network authority. Directory inference from command text is
  best effort, so prefer a narrow shell allowlist instead of patterns intended to recognize every dangerous command.
</Callout>

Relative mutation paths may leave the active Location while remaining inside
its project worktree. Explicit external paths are canonicalized before matching,
so authorize only trusted directory boundaries.

## Scanner

Enable the experimental portable shell scanner with the following setting. Like all
[experimental settings](/config#experimental), it may change or be removed in a future release.

```jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "experimental": {
    "portable_shell_scanner": true,
  },
}
```

The portable scanner replaces the default tree-sitter scanner; tree-sitter is
not a fallback or second opinion. A command the portable scanner cannot analyze
returns a scanner error, not a permission denial.

The flag changes only parser selection. Existing permission rules, saved
approval patterns, and best-effort directory inference still apply. There is no
extra approval mode or blanket restriction for unknown directories.

## Defaults

Every agent, including custom agents, starts with this ordered base policy:

```jsonc
[
  { "action": "*", "resource": "*", "effect": "allow" },
  { "action": "read", "resource": "*.env", "effect": "ask" },
  { "action": "read", "resource": "*.env.*", "effect": "ask" },
  { "action": "read", "resource": "*.env.example", "effect": "allow" },
]
```

Shipped agents append these policies:

| Agent        | Additional policy                                                              |
| ------------ | ------------------------------------------------------------------------------ |
| `build`      | Allows questions                                                               |
| `plan`       | Allows questions; denies edits except files under `~/.opencode/plan`           |
| `general`    | Denies questions and launching subagents                                       |
| `explore`    | Denies everything except shell, reads, globs, grep, web fetches, web searches, and external directories; asks for `.env` reads |
| `title`      | Denies all actions                                                              |
| `summary`    | Denies all actions                                                              |
| `compaction` | Keeps the base policy                                                          |

Because no default rule asks for `external_directory`, reads and edits outside
the Location and worktree proceed without a prompt. Add an
`external_directory` `ask` or `deny` rule, as shown in
[Directories](#directories), to restore a prompt or block outside access.
Later global and agent rules override these defaults.

## Agents

Put shared rules at the top level and narrower rules under
`agents.<id>.permissions`:

```jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "permissions": [
    { "action": "shell", "resource": "*", "effect": "ask" },
    { "action": "shell", "resource": "git status *", "effect": "allow" },
  ],
  "agents": {
    "reviewer": {
      "description": "Review code without changing it",
      "mode": "subagent",
      "permissions": [
        { "action": "edit", "resource": "*", "effect": "deny" },
      ],
    },
  },
}
```

Agent rules are appended after global rules; they do not replace the global
array. A custom subagent uses its own permissions, not a subset of its parent's
permissions.

## Approvals

When a rule resolves to `ask`, clients can reply with:

| Choice       | Reply      | Result                                                               |
| ------------ | ---------- | -------------------------------------------------------------------- |
| Allow once   | `once`     | Approve only the pending request                                     |
| Allow always | `always`   | Approve it and save the tool's proposed patterns for the project     |
| Reject       | `reject`   | Reject it and every other pending permission request in that session |

For example, choosing **Allow always** for `git status --short` may save a
shell prefix that covers later `git status` commands:

```text
shell: git status * → allow
```

Saved approvals are durable, project-scoped `allow` rules. They never override
a configured `deny`. Tools choose the proposed saved pattern: some propose `*`,
shell proposes command prefixes, and skills and subagents propose their IDs.
Review broad approvals and remove those no longer needed.

Clients may attach feedback when rejecting. Non-interactive clients must decide
how to handle approval requests; configured `deny` rules always remain enforced.

## Policies

A [policy](/policies) can hard-deny a permission check after these rules and saved
approvals run. It turns `allow` or `ask` into `deny` and never grants access.

```jsonc
{
  "policies": [{ "action": "tool.use", "resource": "shell:sudo *", "effect": "deny" }],
}
```

Global and Console-managed policies override project configuration, which is how an
organization blocks a command that a repository would allow.

---

### Services Www Src Docs Content Plugins (`services/www/src/docs/content/plugins.mdx`)

---
title: "Plugins"
---

Add published packages, versioned packages, scoped packages, or local plugin directories to `opencode.json(c)`.

## Configure

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "plugins": [
    "opencode-acme-plugin",
    "opencode-acme-plugin@1.2.0",
    "@acme/opencode-plugin",
    "./plugins/local",
    "../shared/plugin.ts",
    "/absolute/path/plugin.ts",
    "file:///home/me/plugins/local",
    {
      "package": "@acme/opencode-plugin",
      "options": {
        "agent": "reviewer",
        "strict": true,
      },
    },
  ],
}
```

Relative paths resolve from the config file containing the entry. Plugin arrays from applicable config files are applied
from lowest to highest precedence instead of replacing one another.

```text
~/.config/opencode/opencode.jsonc
./opencode.jsonc
./.opencode/opencode.jsonc
```

## Discover

OpenCode also loads direct `.ts` and `.js` files and immediate plugin package directories from every discovered
`.opencode/plugins/` directory.

```text
.opencode/
└── plugins/
    ├── concise.ts
    ├── reviewer.js
    └── acme-package/
```

Global plugins use the same discovery layout under the OpenCode config directory.

```text
~/.config/opencode/plugins/
```

A `plugins/` directory beside a project-root `opencode.json(c)` is not discovered automatically; configure its files
explicitly or move it under `.opencode/`.

```jsonc title="opencode.jsonc"
{
  "plugins": ["./plugins/local"]
}
```

## Control

Plugin entries are processed in order. Prefix an ID or wildcard with `-` to disable it, use `*` for every plugin, and
use `.*` to match an ID prefix. A later ID re-enables a plugin.

```jsonc title="opencode.jsonc"
{
  "plugins": ["*", "-opencode.provider.*", "opencode.provider.openai", "-acme.reviewer"]
}
```

Two built-in plugins ignore removals so that a repository cannot switch off
[policy](/policies) enforcement: `opencode.config.policy` and
`opencode.provider.opencode`, the Console connection that delivers organization
policy.

## Manage

Install, list, check, update, or remove global package plugins with the CLI.

```sh
opencode plugin add opencode-acme-plugin@1.2.0
opencode plugin list
opencode plugin list --builtin
opencode plugin check
opencode plugin update
opencode plugin update opencode-acme-plugin
opencode plugin remove opencode-acme-plugin@1.2.0
```

`plugin check` checks server and TUI-only package plugins for updates. `plugin update` updates every outdated package;
pass a configured package target to check or update only that package. Local plugins and exact package revisions are skipped.

Package installation accepts npm names with versions, tags, or ranges, plus npm-compatible Git package specifications.
Git repositories can use hosted shortcuts, HTTPS, or SSH, including private repositories available through your existing
Git credentials.

```sh
opencode plugin add @acme/opencode-plugin@latest
opencode plugin add github:acme/opencode-plugin
opencode plugin add git+ssh://git@github.com/acme/opencode-plugin.git#main
opencode plugin add 'github:acme/plugins#main::path:packages/opencode-plugin'
```

Branches, tags, complete commit hashes, and npm's `::path:` repository-subdirectory selectors are supported. Configure
local paths directly; tarball and npm alias targets are not accepted by `plugin add`.

## Reload

Changes under watched config directories reload automatically. Server startup loads cached package plugins immediately,
installs missing packages in the background, and checks unpinned npm and Git plugins for updates without changing the
installed package. Exact npm versions and full Git commit hashes stay pinned. Changes to unwatched local dependencies may
still require restarting OpenCode.

```sh
touch .opencode/plugins/concise/index.ts
opencode service restart
```

## Terminal

CLI-only plugins are configured separately and remain active when connected to a remote server.

```json title="cli.json"
{
  "plugins": ["opencode-acme-cli"]
}
```

<Card title="Build a plugin" href="/build/plugins">
  Create plugins that add tools, hooks, integrations, commands, agents, and other behavior.
</Card>

---

### Services Www Src Docs Content Policies (`services/www/src/docs/content/policies.mdx`)

---
title: "Policies"
description: "Allow or deny OpenCode actions on named resources, with organization policy taking final authority."
---

Policies decide whether OpenCode may perform an action on a named resource. They are
authored under `policies` and can also be delivered by a connected
[OpenCode Console](/console) workspace.

Policies are separate from [permissions](/permissions). Permissions are per-agent tool
rules that can `allow`, `deny`, or `ask`. Policies are binary, never prompt, and only
ever tighten what permissions and providers would otherwise allow.

## Configure

Deny one provider everywhere by adding a statement to `opencode.jsonc`:

```jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "policies": [{ "action": "provider.use", "resource": "openai", "effect": "deny" }],
}
```

A denied provider disappears from the catalog and model selection even when it has
valid credentials.

Earlier releases read policies from `experimental.policies`. That key still works and
merges into `policies`:

```jsonc
{
  "experimental": {
    "policies": [{ "action": "provider.use", "resource": "openai", "effect": "deny" }],
  },
}
```

## Statements

Each statement has three fields:

| Field      | Values                                        | Meaning                                              |
| ---------- | --------------------------------------------- | ---------------------------------------------------- |
| `action`   | `provider.use`, `tool.use`, `integration.use` | The operation being controlled                       |
| `resource` | string or wildcard pattern                    | What the statement applies to; depends on the action |
| `effect`   | `allow`, `deny`                               | The decision when this statement matches             |

Statements that fail validation are dropped with a warning in the server log and
the rest of the list still applies. Check the log after editing a `deny`.

## Matching

Resources use the same whole-value wildcards as permissions: `*` matches zero or
more characters and `?` matches one.

```jsonc
{
  "policies": [{ "action": "provider.use", "resource": "company-*", "effect": "deny" }],
}
```

This denies `company-us` and `company-eu`. A pattern ending in ` *` also matches the
value without arguments, so `shell:git push *` covers `git push` on its own.

## Order

When several statements match, the last one wins. There is no specificity rule, so
put broad statements first and exceptions after them. If nothing matches, the
action is allowed.

```jsonc
{
  "policies": [
    { "action": "provider.use", "resource": "*", "effect": "deny" },
    { "action": "provider.use", "resource": "anthropic", "effect": "allow" },
  ],
}
```

Only Anthropic remains available.

## Providers

`provider.use` controls whether a provider is usable at all. The resource is the
provider ID: `anthropic`, `openai`, `opencode`, or a custom ID from
[`providers`](/providers).

```jsonc
{
  "providers": {
    "company-ai": {
      "package": "@opencode/ai/providers/openai-compatible",
      "settings": { "baseURL": "https://ai.company.example/v1" },
    },
  },
  "policies": [
    { "action": "provider.use", "resource": "*", "effect": "deny" },
    { "action": "provider.use", "resource": "company-ai", "effect": "allow" },
  ],
}
```

The `providers` entry configures the endpoint; the statements make it the only
provider OpenCode will use. Policy applies however a provider became known: catalog
data, environment variables, saved accounts, built-in plugins, or configuration.

Use `provider.use` instead of the V1 `enabled_providers` and `disabled_providers`
lists. V1 files still load; see
[Migrate from V1](/migrate-v1#supported-fields-without-direct-native-equivalents).

## Tools

`tool.use` statements hard-deny a [permission](/permissions) check. The resource is
`<action>:<value>`, matched against every resource the tool checks.

```jsonc
{
  "policies": [
    { "action": "tool.use", "resource": "shell:git push *", "effect": "deny" },
    { "action": "tool.use", "resource": "edit:*.env", "effect": "deny" },
    { "action": "tool.use", "resource": "webfetch:*", "effect": "deny" },
  ],
}
```

A denied check fails with `Blocked by configuration policy` instead of prompting. It
applies after agent rules and saved approvals, so it overrides an `ask` and an
"Allow always" approval alike.

| Pattern                      | Blocks                                      |
| ---------------------------- | ------------------------------------------- |
| `shell:*`                    | Every shell command                         |
| `read:*/.ssh/*`              | Reading SSH material                        |
| `external_directory:*`       | Any access outside the Location or worktree |
| `subagent:general`           | Launching one subagent                      |
| `github_delete_repository:*` | One MCP tool                                |
| `*`                          | Everything not already denied               |

A `tool.use` statement with `allow` never grants access. It only lifts an earlier
broader `deny`, after which the agent's own rules decide.

```jsonc
{
  "policies": [
    { "action": "tool.use", "resource": "shell:*", "effect": "deny" },
    { "action": "tool.use", "resource": "shell:git status *", "effect": "allow" },
  ],
}
```

`git status` falls back to the agent's `shell` rule; every other command is blocked.

## Integrations

`integration.use` controls whether an MCP server, skill, or plugin is loaded. The
resource is the integration kind and its ID:

| Resource          | Applies to                                                        |
| ----------------- | ----------------------------------------------------------------- |
| `mcp:<server>`    | An [MCP server](/mcp-servers) by its configured name              |
| `skill:<id>`      | A [skill](/skills) by its ID                                      |
| `plugin:<target>` | A [plugin](/plugins) by unversioned package name or absolute path |

```jsonc
{
  "policies": [
    { "action": "integration.use", "resource": "mcp:*", "effect": "deny" },
    { "action": "integration.use", "resource": "mcp:github", "effect": "allow" },
    { "action": "integration.use", "resource": "plugin:opencode-acme-cli", "effect": "deny" },
  ],
}
```

A denied MCP server or skill is removed, and a denied plugin is not loaded, however
it was configured.

## Precedence

Ordinary settings let the nearest configuration win. Policies reverse that: statements
from broader configuration are evaluated later, so they override narrower ones. Managed
configuration and the connected Console always have the final say.

| Authority   | Source                                                                                                         |
| ----------- | -------------------------------------------------------------------------------------------------------------- |
| 1 (highest) | Connected OpenCode Console workspace                                                                           |
| 2           | macOS managed preferences (`/Library/Managed Preferences/ai.opencode.managed.plist`)                           |
| 3           | System `opencode.json(c)` (`/Library/Application Support/opencode`, `/etc/opencode`, `%ProgramData%\opencode`) |
| 4           | Global `~/.config/opencode/opencode.json(c)`                                                                   |
| 5           | Direct `opencode.json(c)`; outer directories beat inner ones                                                   |
| 6 (lowest)  | `.opencode/opencode.json(c)`; outer directories beat inner ones                                                |

A repository cannot re-enable a provider you deny globally:

```jsonc title="~/.config/opencode/opencode.jsonc"
{
  "policies": [{ "action": "provider.use", "resource": "openai", "effect": "deny" }],
}
```

```jsonc title="project/opencode.jsonc"
{
  "policies": [{ "action": "provider.use", "resource": "openai", "effect": "allow" }],
}
```

`openai` stays denied. Within one file, statements keep their written order.

## Console

A workspace on the [OpenCode Console](/console) compiles its Providers and Tools
policies into statements and returns them with the workspace configuration. OpenCode
appends them after every authored statement, so they have the final say: an
organization `deny` cannot be lifted by a repository or user `allow`, and an
organization `allow` lifts a lower-authority `deny`.

Denials from these statements name the workspace:

```text
Blocked by Acme's policy
```

Statements follow the connected account.

| Event                       | Result                                             |
| --------------------------- | -------------------------------------------------- |
| Console policy changes      | Applied on the next fetch, about once a minute     |
| Switch to another workspace | Statements replaced with that workspace's          |
| Disconnect                  | Statements cleared                                 |
| Console unreachable         | Last statements for that connection stay in effect |

The Console plugin and the policy plugin cannot be disabled from `plugins`; see
[plugin control](/plugins#control).

<Callout type="note">
  Policies do not configure endpoints or credentials, and they cannot make an unusable provider usable. They also do not
  sandbox plugin code: a denied provider is blocked on the normal provider and model path.
</Callout>

---

### Services Www Src Docs Content Providers (`services/www/src/docs/content/providers.mdx`)

---
title: "Providers"
---

OpenCode includes a provider and model catalog from [models.dev](https://models.dev). For most providers, connect an
account first, then select a model.

## Setup

Run `/connect`, choose a provider, and enter its credentials. Then run `/models` to select one of its models.

```text
/connect
/models
```

## Go

[OpenCode Go](/console/go) is an optional subscription for coding models tested by the OpenCode team. Subscribe in the
[console](https://opencode.ai/console), copy your API key, then connect it as **OpenCode Go**.

```text
/connect
# Select OpenCode Go, then paste your API key.
/models
```

See the [Go guide](/console/go) for usage limits, endpoints, and privacy details.

## Custom

Add a provider when its API is not already in the catalog. This OpenAI-compatible example defines the credential,
runtime package, endpoint, and first model together.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "acme": {
      "name": "Acme",
      "env": ["ACME_API_KEY"],
      "package": "@opencode/ai/providers/openai-compatible",
      "settings": {
        "baseURL": "https://llm.acme.example/v1",
      },
      "models": {
        "qwen3-coder": {
          "name": "Qwen 3 Coder",
        },
      },
    },
  },
}
```

The `providers` object is keyed by the provider ID used in model references, such as `acme/qwen3-coder`.

| Field | Purpose |
| --- | --- |
| `name` | Display name. |
| `env` | Ordered environment variable names that can provide the credential. |
| `package` | Runtime provider package. |
| `canonical` | Built-in provider ID whose catalog defaults this provider inherits. |
| `compatibility` | Request and response compatibility overrides for every model of this provider. Model `compatibility` overrides individual fields. `supportsThinkingBlockBinding` and `supportsEffortUpdates` are model-only. |
| `settings` | Typed OpenCode controls and JSON options passed to the runtime package. |
| `headers` | String-valued HTTP headers added to requests. |
| `body` | JSON fields merged into request bodies. |
| `models` | Models to add or override, keyed by the OpenCode model ID. |

## Endpoint

Override `settings.baseURL` to send a catalog provider through a proxy or compatible endpoint. Its existing package,
models, and connection still apply.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "anthropic": {
      "settings": {
        "baseURL": "https://llm-proxy.example.com/anthropic",
      },
    },
  },
}
```

`settings` is package-specific. A field only has an effect when the selected package supports it.

## Requests

Use `headers` for additional HTTP headers and `body` for JSON fields that should be merged into every request body.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "openai": {
      "headers": {
        "X-Gateway-Tenant": "engineering",
      },
      "body": {
        "metadata": {
          "application": "opencode",
        },
      },
    },
  },
}
```

Both fields can also be set on a model or variant when only part of a provider's traffic needs the override.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "openai": {
      "models": {
        "gpt-5.2": {
          "headers": { "X-Model-Tier": "coding" },
          "variants": [
            {
              "id": "batch",
              "body": { "service_tier": "flex" },
            },
          ],
        },
      },
    },
  },
}
```

## Timeouts

HTTP requests wait up to five minutes for response headers and up to five minutes between streamed response chunks.
Set the provider's `settings.headerTimeout` or `settings.chunkTimeout` to a number of milliseconds to change a limit,
or to `false` to disable it. `settings.timeout` additionally bounds the whole request from send until the response
completes; it has no default. These configuration settings apply provider-wide, not per model or variant. On a
WebSocket transport, `chunkTimeout` bounds the gap between frames instead and defaults to thirty minutes.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "anthropic": {
      "settings": {
        "headerTimeout": 600000,
        "chunkTimeout": false,
      },
    },
  },
}
```

A request that exceeds either limit fails with a transport error. OpenCode retries a timed-out request up to three
times before giving up.

## Request encoding

`settings.encoding` compresses HTTP request bodies with `"zstd"` or `"gzip"`, or sends plain JSON with `"none"`. Set it
on a provider, model, or variant; the most specific value wins. Only enable an encoding the endpoint decodes: most
providers and gateways reject compressed bodies. OpenAI defaults to `"zstd"` when signed in with ChatGPT and no custom
`baseURL` is configured; API keys send plain JSON. WebSocket messages are unaffected.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "openai": {
      "settings": { "encoding": "none" },
    },
  },
}
```

## Packages

The `package` field selects the runtime that communicates with a provider. Use the compatible runtime for APIs that
implement the OpenAI request format.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "acme": {
      "package": "@opencode/ai/providers/openai-compatible",
      "settings": {
        "baseURL": "https://llm.acme.example/v1",
      },
      "models": {
        "qwen3-coder": {},
      },
    },
  },
}
```

Native package options include:

- `@opencode/ai/providers/openai`
- `@opencode/ai/providers/openai/chat`
- `@opencode/ai/providers/openai/responses`
- `@opencode/ai/providers/openai-compatible`
- `@opencode/ai/providers/openai-compatible/responses`
- `@opencode/ai/providers/anthropic`
- `@opencode/ai/providers/anthropic-compatible`
- `@opencode/ai/providers/google`
- `@opencode/ai/providers/google-vertex`
- `@opencode/ai/providers/google-vertex/gemini`
- `@opencode/ai/providers/google-vertex/chat`
- `@opencode/ai/providers/google-vertex/responses`
- `@opencode/ai/providers/google-vertex/messages`
- `@opencode/ai/providers/azure`
- `@opencode/ai/providers/azure/chat`
- `@opencode/ai/providers/azure/responses`
- `@opencode/ai/providers/amazon-bedrock`
- `@opencode/ai/providers/amazon-bedrock/mantle`
- `@opencode/ai/providers/amazon-bedrock/mantle/chat`
- `@opencode/ai/providers/amazon-bedrock/mantle/messages`
- `@opencode/ai/providers/amazon-bedrock/mantle/responses`
- `@opencode/ai/providers/openrouter`
- `@opencode/ai/providers/xai`

You can also use an npm package such as `@acme/opencode-provider` or an absolute `file://` URL for a local package.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "acme": {
      "package": "@acme/opencode-provider",
      "models": { "acme-coder": {} },
    },
  },
}
```

## Models

Add or override models in a provider's `models` map. The map key is the model ID used by OpenCode; `modelID` changes the
ID sent to the provider.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "model": "openai/coding",
  "providers": {
    "openai": {
      "models": {
        "coding": {
          "modelID": "gpt-5.2",
          "name": "GPT-5.2 Coding",
        },
      },
    },
  },
}
```

| Field | Purpose |
| --- | --- |
| `modelID` | Model or deployment ID sent to the provider. |
| `name` | Display name. |
| `family` | Model family used for grouping related models. |
| `releaseDate` | Release date as `YYYY-MM-DD` or `YYYY-MM`. |
| `package` | Runtime override for this model. |
| `settings` | Model-level OpenCode controls and package-specific JSON settings. |
| `headers` | Additional string-valued request headers. |
| `body` | Additional JSON request body fields. |
| `capabilities` | Tool support, accepted input and output media types, temperature support, and reasoning controls. |
| `compatibility` | Request and response compatibility overrides. |
| `variants` | Named variants with their own `settings`, `headers`, and `body`. |
| `cost` | Input, output, and optional cache pricing per million tokens. |
| `limit` | Context, input, and output token limits. |
| `disabled` | Removes the model from selection when `true`. |

See [Models](/models) for selection, defaults, capabilities, limits, costs, and variants.

## Azure

Azure's standard catalog endpoint needs a resource name in addition to its credential. Set `settings.resourceName`
once, then connect an API key or use the Microsoft Entra ID session from the Azure CLI as described in
[Provider accounts](/cli/providers).

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "azure": {
      "settings": {
        "resourceName": "my-models",
      },
    },
  },
}
```

Find the **Resource name** in the [Azure portal](https://portal.azure.com/) or
[Microsoft Foundry](https://ai.azure.com/). It is also the first part of endpoints such as
`https://my-models.openai.azure.com/` and `https://my-models.services.ai.azure.com/`.

```bash
az cognitiveservices account list \
  --query "[].{name:name,resourceGroup:resourceGroup}" \
  --output table
```

To use Entra ID, install the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli), sign in, then
choose **Microsoft Entra ID (Azure CLI)** when connecting Azure.

```bash
az login
```

Enter the resource name when connecting if it is not already supplied by configuration or the environment. A resource
name saved with a connection takes precedence over configuration; connect again to change it.

Azure CLI connections use the account selected in the Azure CLI. For a resource in another tenant or subscription,
select both explicitly.

```bash
az login --tenant TENANT_ID
az account set --subscription NAME_OR_ID
```

Instead of configuration, `AZURE_RESOURCE_NAME` supplies the resource name to the OpenCode server. The legacy
`AZURE_COGNITIVE_SERVICES_RESOURCE_NAME` variable also works.

### Deployments

Azure serves a model only through a deployment, so OpenCode lists the deployments of your resource and shows those
instead of the whole Azure catalog. The list loads in the background after startup, after connecting, and after
switching accounts. To pick up a deployment added later, restart OpenCode or connect again.

- Until the list loads for a connection, or if it fails, the whole catalog stays available.
- A failed reload for the same connection keeps its last complete inventory.
- Switching accounts never shows the previous account's inventory; the new account starts from the whole catalog.
- Deployments inherit limits, costs, and capabilities from their catalog models.

Deployment names are their model IDs, in lowercase because Azure ignores case in names, for example
`azure/gpt-production`. A deployment named after its model, such as `gpt-5-mini`, keeps the catalog ID. These IDs stay
stable when other deployments are added or removed.

OpenCode matches a deployment to the catalog by the model it deploys, or by its name when Azure spells the model
differently, as with `gpt-4` for GPT-4 Turbo. A deployment named after another model, such as `gpt-5` deploying
`gpt-5-mini`, shows that model's name, limits, and costs.

With the Azure CLI, OpenCode lists deployments through the Azure management API, which needs read access to the
resource. If that fails, and always with an API key, it uses the resource's legacy deployment inventory. Discovery reads
every page before publishing the list. A custom `settings.baseURL` keeps the catalog.

Configure a deployment explicitly when its model is not in the catalog, such as a fine-tuned model, or to map a model ID
to a deployment yourself. OpenCode logs a warning naming such deployments. Explicitly configured models are always
kept.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "azure": {
      "models": {
        "gpt-5-mini": {
          "modelID": "gpt-production",
        },
      },
    },
  },
}
```

Your identity needs one of these roles:

- **Cognitive Services OpenAI User** for Azure OpenAI models.
- **Cognitive Services User** for other Foundry models.

If a request uses a token from the wrong tenant, sign in again with the required tenant.

```bash
az login --tenant TENANT_ID
```

## Bedrock

Amazon Bedrock uses the AWS default credential chain. A named AWS profile is the simplest durable setup; OpenCode also
recognizes access-key environments, web identity, and container credentials.

```bash
aws configure sso --profile work
aws sso login --profile work
```

Select the profile and region in provider settings. A configured `profile`, `AWS_PROFILE`, `AWS_ACCESS_KEY_ID`, web
identity token file, or container credential URI activates the provider; a region alone does not.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "amazon-bedrock": {
      "settings": {
        "profile": "work",
        "region": "us-west-2",
      },
    },
  },
}
```

Without an explicit region, OpenCode uses `AWS_REGION`, then `AWS_DEFAULT_REGION`, then `us-east-1`. For a private or
VPC endpoint, set `baseURL` while keeping the same profile and region.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "amazon-bedrock": {
      "settings": {
        "profile": "work",
        "region": "us-west-2",
        "baseURL": "https://bedrock-runtime.vpce.example.com",
      },
    },
  },
}
```

Bedrock API keys use `AWS_BEARER_TOKEN_BEDROCK`. Other AWS variables feed SigV4 and are not stored as OpenCode API-key
accounts.

## Vertex

Google Vertex uses Application Default Credentials (ADC) and needs a project before its models become available.
Create local ADC, then set the project and location in provider settings.

```bash
gcloud auth application-default login
```

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "google-vertex": {
      "settings": {
        "project": "my-project",
        "location": "us-central1",
      },
    },
  },
}
```

OpenCode also resolves the project from `GOOGLE_VERTEX_PROJECT`, `GOOGLE_CLOUD_PROJECT`, `GCP_PROJECT`, or
`GCLOUD_PROJECT`, in that order. It resolves the location from `GOOGLE_VERTEX_LOCATION`, `GOOGLE_CLOUD_LOCATION`, or
`VERTEX_LOCATION`, and defaults to `us-central1`.

```bash
GOOGLE_CLOUD_PROJECT=my-project GOOGLE_VERTEX_LOCATION=europe-west4 opencode --standalone
```

Service accounts work through the same ADC path. Point `GOOGLE_APPLICATION_CREDENTIALS` at the service-account JSON
file and still provide a project through settings or one of the project variables above.

```bash
GOOGLE_APPLICATION_CREDENTIALS=/secure/vertex.json \
GOOGLE_CLOUD_PROJECT=my-project \
opencode --standalone
```

Use the single `google-vertex` provider ID for Gemini, Anthropic, and OpenAI-compatible Vertex catalog models. The old
`google-vertex-anthropic` provider ID is unavailable in V2.

## Copilot

GitHub Copilot supports device OAuth rather than manual API-key entry. Connect **GitHub Copilot**, choose GitHub.com or
GitHub Enterprise, finish the device flow, then open `/models`.

```text
/connect
# Select GitHub Copilot, then Login with GitHub Copilot.
/models
```

For GitHub Enterprise, enter the deployment URL or domain when prompted. OpenCode uses a Copilot API endpoint returned
by GitHub when available; otherwise it derives the endpoint from the enterprise domain.

```text
company.ghe.com
```

The connected account needs Copilot Chat access. If GitHub reports no entitlement, sign up for Copilot Free or ask the
organization to assign a Copilot seat, then connect again. OpenCode fetches the account's current model list after login
and whenever the active Copilot account changes.

## Ollama

Start Ollama and pull a model. OpenCode probes `http://127.0.0.1:11434`, discovers completion models, and adds them to
`/models` without an account connection.

```bash
ollama serve
ollama pull qwen3:8b
```

Point OpenCode at a remote or proxied Ollama server with `settings.baseURL`. Include `/v1`; OpenCode derives the native
`/api/tags` and `/api/show` discovery paths from it. `apiKey` is optional and is sent as a bearer token to discovery and
model requests.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "ollama": {
      "settings": {
        "baseURL": "https://ollama.example.com/v1",
        "apiKey": "{env:OLLAMA_API_KEY}",
      },
    },
  },
}
```

Discovery refreshes periodically and keeps the last successful inventory during a temporary outage. Embedding-only
models do not appear because OpenCode only adds models whose Ollama metadata includes the `completion` capability.

## Runtimes

LM Studio and vLLM also have built-in local discovery. Their default endpoints are
`http://127.0.0.1:1234/v1` and `http://127.0.0.1:8000/v1`.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "lmstudio": {
      "settings": { "baseURL": "http://gpu-host:1234/v1" },
    },
    "vllm": {
      "settings": { "baseURL": "http://gpu-host:8000/v1" },
    },
  },
}
```

LM Studio discovers language models from `/api/v1/models`. vLLM checks `/health` before reading `/v1/models`; its
discovery cannot infer tool support, so discovered vLLM models start with tools disabled. For another OpenAI-compatible
runtime, use the [custom provider](#custom) recipe and list its models explicitly.

## Gateways

OpenRouter uses its native runtime and catalog. Provide `OPENROUTER_API_KEY` to the OpenCode server or connect an
OpenRouter account, then refer to models with the full OpenRouter model ID after the provider prefix.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "model": "openrouter/anthropic/claude-sonnet-4",
}
```

Keep the native OpenRouter package when overriding its endpoint or routing through an OpenRouter-compatible gateway.
This preserves OpenRouter request and reasoning behavior.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "openrouter": {
      "settings": {
        "baseURL": "https://openrouter-gateway.example.com/api/v1",
      },
      "headers": {
        "X-Gateway-Tenant": "engineering",
      },
    },
  },
}
```

For a gateway that exposes an OpenAI-compatible API but has its own model inventory, define a custom provider instead.
The configuration key becomes the provider prefix and each `models` key becomes a selectable model ID.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "model": "company/coder",
  "providers": {
    "company": {
      "env": ["COMPANY_GATEWAY_KEY"],
      "package": "@opencode/ai/providers/openai-compatible",
      "settings": {
        "baseURL": "https://gateway.example.com/v1",
      },
      "models": {
        "coder": { "modelID": "upstream/coder-v2" },
      },
    },
  },
}
```

## Errors

Provider and model errors usually identify the failed stage. Check the server process environment and the exact model
ID before changing packages.

| Error or symptom | Check |
| --- | --- |
| `No model is available for session ...` | No enabled model is currently selectable. Finish the provider-specific setup, then choose a model in `/models`. |
| `Model unavailable: provider/model` | The provider is inactive, the model ID is absent or disabled, or dynamic discovery no longer returns it. For custom aliases, check the `models` map key rather than `modelID`. |
| `Cannot initialize provider/model: NAME is required to resolve the provider endpoint` | A `${NAME}` placeholder remains in `baseURL`. Set that variable on the OpenCode server or replace the template with a complete endpoint. |
| `Azure resource name is missing` | Set `providers.azure.settings.resourceName`, `AZURE_RESOURCE_NAME`, or a complete `settings.baseURL`. |
| Vertex does not appear | Set a resolvable project in provider settings or a supported project variable. ADC alone does not activate the provider. |
| Bedrock does not appear | Provide a profile or another supported AWS credential-chain input. `AWS_REGION` by itself only selects a region. |
| Ollama has no models | Confirm the server exposes `/api/tags` and `/api/show` at the path derived from `baseURL`, and that `/api/show` reports the `completion` capability. |
| Copilot has no models | Confirm the active OAuth account has Copilot Chat access. A failed model sync is logged as `failed to sync GitHub Copilot models`. |

V2 rejects the retired provider IDs with a direct replacement. Use `azure/<model>` instead of
`azure-cognitive-services/<model>`, and `google-vertex/<model>` instead of `google-vertex-anthropic/<model>`.

## WebSockets

OpenAI, xAI, and supported Azure Responses models can keep one WebSocket connection open per session. Consecutive steps
reuse the unchanged request prefix and only send content added since the previous response, reducing uploads in long
sessions.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "openai": {
      "settings": { "transport": "http" },
    },
  },
}
```

WebSocket behavior follows these rules:

- Built-in providers opt supported routes in according to their own policy.
- Provider `settings.transport: "websocket"` enables it; `"http"` disables it.
- `"websocket"` on a route without a WebSocket channel logs a warning and falls back to HTTP.
- OpenAI provider compaction uses the same connection.
- xAI continues from stored responses only. With its default `store: false`, each step is sent in full over the reused
  connection.
- A closed socket reconnects on the next step. If the connection cannot open, the session continues over HTTP.
- Provider plugins with `http.request` or `http.response` hooks stay on HTTP so each request remains observable.

---

### Services Www Src Docs Content References (`services/www/src/docs/content/references.mdx`)

---
title: "References"
---

References give OpenCode named access to directories outside the current
project. Add one in `opencode.json` or `opencode.jsonc`, then attach its alias in
your client when you need it.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "references": {
    "docs": {
      "path": "../product-docs",
      "description": "Use for product behavior and terminology",
    },
  },
}
```

After attaching `docs`, ask the agent to inspect the relevant path:

```text
Read the attached docs reference and summarize api/authentication.md.
```

Use references for documentation, shared libraries, examples, or source from
another repository.

## Local

Use `path` for a local directory:

```jsonc
{
  "references": {
    "design-system": {
      "path": "../design-system",
      "description": "Use when working with components or design tokens",
    },
  },
}
```

Paths behave as follows:

- Relative paths resolve from the directory containing the config file.
- Absolute paths are supported.
- Home-relative paths such as `~/docs` are supported.

Use the string shorthand when no other fields are needed:

```jsonc
{
  "references": {
    "docs": "../docs",
    "shared": "~/work/shared",
  },
}
```

<Callout type="note">
  A shorthand string is a local path only when it starts with `.`, `/`, or `~`. Use `./docs`, not `docs`; a bare `docs`
  value is interpreted as a Git repository.
</Callout>

## Git

Use `repository` for a remote Git repository:

```jsonc
{
  "references": {
    "effect": {
      "repository": "Effect-TS/effect",
      "branch": "main",
    },
    "internal-sdk": {
      "repository": "git@gitlab.example.com:platform/sdk.git",
      "branch": "release/v2",
    },
  },
}
```

Supported remote forms include:

- GitHub `owner/repo` shorthand
- Git URLs
- Host/path forms
- SCP-style remotes

Local `file:` repositories are not supported.

Use the string shorthand to follow the remote's default branch:

```jsonc
{
  "references": {
    "effect": "Effect-TS/effect",
    "sdk": "gitlab.com/platform/sdk",
  },
}
```

Without `branch`, OpenCode checks out and refreshes the remote's default branch.
Branch names may contain letters, numbers, `/`, `_`, `.`, and `-`, but cannot
start with `-` or contain `..`.

```jsonc
{
  "references": {
    "sdk": {
      "repository": "example/sdk",
      "branch": "release/v2.1",
    },
  },
}
```

## Storage

OpenCode normalizes each remote and stores one checkout per remote and branch
under its global data directory. Without an explicit branch, the path uses this
shape:

```text
opencode/repos/<host>/<repository-path>
```

On a typical Linux installation, `Effect-TS/effect` is stored at:

```text
~/.local/share/opencode/repos/github.com/Effect-TS/effect
```

An explicit branch adds an encoded `@<branch>` suffix:

```text
~/.local/share/opencode/repos/github.com/Effect-TS/effect@main
```

## Refresh

Missing repositories are cloned asynchronously. Existing checkouts are checked
in the background when references load or reload and after a new user prompt is
admitted in their Location.

```text
Prompt admitted → refresh check starts in background → agent continues
```

A checkout is eligible when its last refresh attempt was at least 24 hours ago,
or when no attempt has been recorded. A refresh fetches and resets to the
configured branch or the remote's default branch.

```text
Last attempt: 25 hours ago → eligible
Last attempt: 2 hours ago  → skipped
```

Refresh behavior follows these rules:

- Timestamps persist across service restarts.
- Locations using the same checkout share its timestamp.
- Failed attempts are logged and remain subject to the 24-hour limit.
- There is no periodic polling while a Location is unused.
- Clone or refresh failures do not stop other references from loading.

Prompts do not wait for cloning or refreshing. An attachment can contain older
content even if a later tool read sees the updated checkout, and a new reference
can appear before its checkout is ready.

```text
Attachment created → cached content
Background refresh completes → later tool read sees newer content
```

<Callout type="warning">
  Cached checkouts are shared and can update while an agent is using them. Avoid editing cached checkouts because a
  refresh resets them.
</Callout>

## Guidance

`description` tells agents when a reference is relevant. References with a
description appear in agent instructions with their alias and resolved path.

```jsonc
{
  "references": {
    "docs": {
      "path": "../docs",
      "description": "Use for product behavior and terminology",
    },
  },
}
```

References without a description remain available to clients but are not
advertised automatically.

```jsonc
{
  "references": {
    "archive": {
      "path": "../archive",
    },
  },
}
```

## Visibility

Set `hidden` to `true` to remove a reference from interactive client selectors:

```jsonc
{
  "references": {
    "internal": {
      "path": "../internal",
      "description": "Use for internal service behavior",
      "hidden": true,
    },
  },
}
```

`hidden` affects only interactive visibility. The reference remains in the
reference API and, when it has a description, in agent instructions.

## Usage

Clients attach a reference by its root alias. The attachment contains a
non-recursive listing of the root's immediate files and directories.

```text
Attached alias: docs
Ask: Inspect docs/guides/deployment.md and explain the deployment steps.
```

Ask the agent to inspect a specific path when you need content below the root.

## Permissions

References do not grant extra tool permissions. Access outside the active
Location still follows normal tool rules and the `external_directory`
permission; editing also requires the applicable edit permission.

```text
Read ../product-docs/api.md
```

The request succeeds only when the active permissions allow that external read.

## Fields

| Field         | Local    | Git      | Description                                   |
| ------------- | -------- | -------- | --------------------------------------------- |
| `path`        | Required | No       | Local directory path                          |
| `repository`  | No       | Required | Remote Git repository                         |
| `branch`      | No       | Optional | Branch to fetch and check out                 |
| `description` | Optional | Optional | Guidance describing when agents should use it |
| `hidden`      | Optional | Optional | Hide it from interactive client selectors     |

A complete Git entry can use every Git-compatible field:

```jsonc
{
  "references": {
    "sdk": {
      "repository": "example/sdk",
      "branch": "main",
      "description": "Use for SDK implementation details",
      "hidden": false,
    },
  },
}
```

## Aliases

An alias cannot be empty or contain `/`, `\`, whitespace, a backtick, or a
comma.

```text
Valid:   docs
Invalid: product docs
Invalid: docs/api
```

---

### Services Www Src Docs Content Skills (`services/www/src/docs/content/skills.mdx`)

---
title: "Skills"
---

Create a skill to give an agent reusable instructions for a specific task. Put a `SKILL.md` file in `.opencode/skills/<skill-id>` and describe when to use it in `description`.

```markdown title=".opencode/skills/git-release/SKILL.md"
---
name: Git Release
description: Prepare release notes, version bumps, and GitHub releases
---

## Workflow

1. Read `references/release-policy.md`.
2. Summarize merged changes since the previous tag.
3. Propose the version bump before changing files.
4. Run `scripts/changelog.ts` only after the user approves the version.
```

OpenCode advertises this skill when it is relevant. The agent can then load its instructions with the `skill` tool instead of adding every skill to every prompt.

## Create

Keep related scripts, references, and templates beside `SKILL.md`:

```text
.opencode/skills/
└── git-release/
    ├── SKILL.md
    ├── scripts/
    │   └── changelog.ts
    └── references/
        └── release-policy.md
```

Paths written inside the skill are relative to the directory containing `SKILL.md`. The directory form is recommended because it gives supporting files a private base directory.

## Discovery

OpenCode automatically searches these locations:

| Scope                 | Sources                                |
| --------------------- | -------------------------------------- |
| Global                | `~/.config/opencode/skills`            |
| Global compatibility  | `~/.claude/skills`, `~/.agents/skills` |
| Project               | `.opencode/skills`                     |
| Project compatibility | `.claude/skills`, `.agents/skills`     |

For project sources, OpenCode searches from the current directory up to the project root and includes matching directories at every level.

Each source can contain either form:

```text
skills/
├── review.md
└── git-release/
    └── SKILL.md
```

- Markdown files must be at the source root, such as `skills/review.md`.
- Files named exactly `SKILL.md` can be nested in grouping directories, such as `skills/git-release/SKILL.md` or `skills/teams/release/SKILL.md`.
- A directory containing `SKILL.md` is one skill. OpenCode does not search inside it for more skills.
- Hidden files and directories and `node_modules` are skipped.
- Search stops six directories below the source root.

## Sources

Add more local directories or HTTP catalogs with the `skills` array in any `opencode.json` or `opencode.jsonc`:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "skills": [
    "./team-skills",
    "~/shared/opencode-skills",
    "/opt/company-skills",
    "https://example.com/opencode/skills/",
  ],
}
```

| Value | Resolution |
| ----- | ---------- |
| Relative path | From the active OpenCode working directory, not the config file |
| `~/` path | From the current user's home directory |
| Absolute path | Used as written |
| `http://` or `https://` URL | Loaded as an HTTP catalog |

Every discovered config file contributes its entries. `skills` arrays are combined rather than replaced.

## Catalogs

An HTTP catalog is a base URL with an `index.json` file:

```json title="index.json"
{
  "skills": [
    {
      "name": "git-release",
      "version": "3",
      "files": ["git-release.md", "references/release-policy.md"]
    }
  ]
}
```

For that entry, OpenCode downloads each file from `<base-url>/git-release/<file>`.

| Rule | Requirement |
| ---- | ----------- |
| Paths | Must be safe, relative, and same-origin |
| Entry file | Include `SKILL.md` or `<name>.md`, such as `git-release.md` |
| Updates | Increment `version` when files change so OpenCode refreshes its cache |

Each downloaded skill directory becomes a source root named after the entry, so both `git-release.md` and `SKILL.md` have the ID `git-release`.

## Frontmatter

Use frontmatter to name the skill and control where it appears:

```markdown title="SKILL.md"
---
name: Git Release
description: Prepare a repository release
metadata:
  opencode/autoinvoke: false
---

Prepare the changelog, version bump, tag, and release notes.
```

| Field                          | Behavior                                                          |
| ------------------------------ | ----------------------------------------------------------------- |
| `name`                         | Display name; defaults to the path-derived ID                     |
| `description`                  | Summary used to show the skill to the model                       |
| `metadata.opencode/autoinvoke` | Set to `false` to omit the skill from the model's available list  |
| `disable-model-invocation`     | Set to `true` for the same effect as `opencode/autoinvoke: false` |

All frontmatter is optional at runtime. Add a clear `description` when the model should discover the skill; skills without one are not advertised.

`opencode/autoinvoke: false` only hides the skill from the model's available list. The skill remains registered and can still be loaded explicitly by ID. When both `disable-model-invocation` and `opencode/autoinvoke` are set, `opencode/autoinvoke` wins. V2 accepts portability fields such as `license` and `compatibility` but does not interpret them.

## IDs

The file path determines the skill ID. The frontmatter `name` is only a display label.

| File                              | ID            |
| --------------------------------- | ------------- |
| `<source>/git-release.md`         | `git-release` |
| `<source>/git-release/SKILL.md`   | `git-release` |
| `<source>/teams/release/SKILL.md` | `release`     |

IDs are exact and case-sensitive. For portable skills, use a unique lowercase kebab-case ID of 1–64 characters and keep it aligned with the directory name:

```text
^[a-z0-9]+(-[a-z0-9]+)*$
```

V2 currently does not enforce this pattern, the 1–64 character recommendation, a match between `name` and the directory, or a maximum description length.

## Precedence

Skills are selected by ID. If two sources define `git-release`, the source registered later supplies the skill that OpenCode loads:

```text
~/.config/opencode/skills/git-release/SKILL.md  ← lower precedence
.opencode/skills/git-release/SKILL.md           ← loaded
```

Sources are registered from lower to higher precedence:

1. Built-in skills
2. `.claude/skills`, global first and then from the farthest ancestor toward the current directory
3. `.agents/skills`, global first and then from the farthest ancestor toward the current directory
4. `~/.config/opencode/skills`
5. Project `.opencode/skills`, from the project root toward the current directory
6. Explicit `skills` config entries, in config priority and array order

Avoid duplicate IDs unless you intend to override an earlier skill.

## Loading

At each model step, OpenCode lists permitted skills that have a description and do not set `opencode/autoinvoke` to `false`. The list includes only the ID, name, and description, not the full Markdown body.

The model loads a skill by calling the `skill` tool with its exact ID:

```json title="skill tool input"
{
  "id": "git-release"
}
```

OpenCode then:

1. Selects the current definition for that ID.
2. Checks the selected agent's `skill` permission.
3. Adds the Markdown body, without frontmatter, to the conversation.
4. Provides the skill's base directory and a sample of up to ten supporting file paths.

To load a skill yourself, mention it in your prompt as `@skill-id`.

Supporting file contents are not loaded automatically. The agent reads them when the skill directs it to do so. The file sample is available for directory-based `SKILL.md` skills; flat Markdown skills do not receive a neighboring file list.

## Permissions

Use the `skill` action and the skill ID as the resource. Rules run in order, and the last matching rule wins:

```jsonc title="opencode.jsonc"
{
  "permissions": [
    { "action": "skill", "resource": "*", "effect": "allow" },
    { "action": "skill", "resource": "internal-*", "effect": "deny" },
    { "action": "skill", "resource": "experimental-*", "effect": "ask" },
  ],
}
```

| Effect | Behavior |
| ------ | -------- |
| `allow` | Advertises and loads matching skills without approval |
| `ask` | Advertises matching skills and asks before loading them |
| `deny` | Hides matching skills from the model and rejects loading |

Place the same rules under `agents.<id>.permissions` to apply them only to one agent.

## Troubleshooting

For example, this skill's ID is `release`, not its frontmatter name `Git Release`:

```text
.opencode/skills/release/SKILL.md
                      └─ ID: release
```

If a skill is missing or loads the wrong content:

1. Confirm the file is either a root-level `*.md` or a nested file named exactly `SKILL.md`.
2. Check the path-derived, case-sensitive ID rather than the frontmatter `name`.
3. Add a `description` if the model should discover the skill.
4. Check `opencode/autoinvoke` and the selected agent's `skill` permissions.
5. Look for a later source that defines the same ID.
6. For HTTP catalogs, verify `index.json`, same-origin file paths, and a changed `version`.

---

### Services Www Src Docs Content Snapshots (`services/www/src/docs/content/snapshots.mdx`)

---
title: "Snapshots"
---

Snapshots let you undo recent conversation and file changes together. Use them to revise recent work, but keep Git commits
or backups for anything important.

## Workflow

Run `/undo` after a response you want to revise. OpenCode stages the rollback, restores the affected files, and puts the
removed prompt back in the composer so you can edit it.

```text
/undo

# Edit the restored prompt, then submit it again.
Add validation without changing the public API.
```

Submitting the edited prompt commits the staged rollback. Before submitting, run `/redo` to cancel it and restore the
conversation and files you had before `/undo`.

```text
/redo
```

The terminal also provides default shortcuts:

| Action | Command | Shortcut |
| --- | --- | --- |
| Stage the previous message rollback | `/undo` | `<leader>u` |
| Cancel the staged rollback | `/redo` | `<leader>r` |

You can also select an earlier message and choose **Revert** to stage a rollback to that point.

## Capture

For each model step, OpenCode attempts a snapshot immediately before the model call and another when the step reaches a
recorded success or failure. The assistant message records which paths changed between those snapshots.

```text
before model step ── snapshot A
model edits src/api.ts
step finishes ────── snapshot B ── changed: src/api.ts
```

Capture is best effort. If either snapshot is unavailable, the conversation continues, but that step may not have file
changes available to restore.

## Scope

Snapshots cover the session's active directory inside a Git worktree. For example, a session opened in `packages/app`
captures eligible files below `packages/app`, not changes elsewhere in the repository.

| Content | Captured | Example |
| --- | --- | --- |
| Tracked files in the active directory | Yes | `packages/app/src/app.tsx` |
| Non-ignored untracked files up to 2 MiB each | Yes | `packages/app/notes.txt` |
| Git-ignored files | No | `packages/app/dist/app.js` |
| Individual untracked files larger than 2 MiB | No | `packages/app/debug.log` |
| Files outside the active directory | No | `packages/server/src/index.ts` |
| Git metadata and other side effects | No | commits, branches, databases, or processes |

Filesystem snapshots require a Git repository. Outside one, `/undo` can still roll back conversation history, but it
cannot restore files.

## Restore

A rollback restores only paths attributed to assistant steps after the selected conversation boundary. Each path returns
to its state before the first reverted step; a file created by those steps is removed if it did not exist then.

| Timeline | `src/api.ts` | `src/new.ts` |
| --- | --- | --- |
| Selected boundary | version A | missing |
| Later assistant steps | version B | created |
| After rollback | version A | removed |

Paths not attributed to those steps are left alone. Current edits to an affected path can be overwritten, so review the
restored summary and `git diff` before continuing.

```sh
git diff --stat
git diff
```

## Storage

OpenCode stores snapshots locally in a separate internal Git object database under its data directory. Snapshot capture
does not create commits, move branches, or intentionally change your repository's index.

```sh
# Your repository remains an ordinary dirty worktree after capture.
git status --short
```

Snapshot objects can contain the complete contents of tracked and eligible untracked files. Treat the OpenCode data
directory as sensitive local data.

## Settings

Snapshots are enabled by default. Set `snapshots` to `false` in your [configuration](/config#snapshots) to stop future
filesystem capture.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "snapshots": false,
}
```

Disabling snapshots does not delete snapshots already stored. Conversation rollback remains available, but without a
captured filesystem state it cannot restore related file changes.

## Safety

Snapshots are a convenience, not a transaction or backup:

- Shell commands can change services, processes, network resources, databases, Git state, ignored output, or files outside
  the active directory. Restoring a snapshot does not reverse those effects.
- Interrupted or failed work can leave changes when capture fails or no usable snapshot pair exists.
- Restoring affected paths overwrites their current contents. Cancelling a staged rollback can also overwrite later edits.
- OpenCode rejects rollback operations while the session is running, but external editors and commands can still change
  the worktree between capture and restoration.
- Committing a rollback removes messages from the active conversation view, not from durable session history or existing
  snapshot storage. It is not secure erasure.

Commit or back up important work before using `/undo` on a dirty worktree.

---

### Services Www Src Docs Content Themes (`services/www/src/docs/content/themes.mdx`)

---
title: "Themes"
---

Choose a theme from the terminal UI by pressing `Ctrl+P`, selecting **Open settings**, and opening **Theme**. You can also
set it directly in your global CLI config:

```json title="~/.config/opencode/cli.json"
{
  "theme": {
    "name": "tokyonight",
    "mode": "system"
  }
}
```

Themes belong to the terminal client. Put theme selection in `cli.json`, not `opencode.json`. See
[CLI settings](/cli/config) for the config location and other terminal settings.

## Modes

Use `system` to follow your terminal's appearance, or lock the theme to one mode:

```json title="~/.config/opencode/cli.json"
{
  "theme": {
    "name": "opencode",
    "mode": "dark"
  }
}
```

| Value    | Behavior                                      |
| -------- | --------------------------------------------- |
| `system` | Follows the light or dark mode of the terminal. |
| `dark`   | Always uses the dark theme.                   |
| `light`  | Always uses the light theme.                  |

If a custom theme provides only one mode, OpenCode uses that mode when the other is requested.

## Builtins

Select a built-in theme by its name:

```json title="~/.config/opencode/cli.json"
{
  "theme": {
    "name": "catppuccin"
  }
}
```

Available themes include:

- `aura`, `ayu`, `carbonfox`, `cobalt2`, `cursor`, `dracula`, `everforest`, `flexoki`
- `catppuccin`, `catppuccin-frappe`, `catppuccin-macchiato`
- `github`, `gruvbox`, `kanagawa`, `material`, `matrix`, `mercury`, `monokai`, `nightowl`, `nord`
- `one-dark`, `opencode`, `orng`, `lucent-orng`, `osaka-jade`, `palenight`, `rosepine`
- `solarized`, `synthwave84`, `tokyonight`, `vercel`, `vesper`, `zenburn`

The `system` theme is available when OpenCode can read your terminal palette.

## Files

To create a global theme named `ocean`, use the theme tool to generate a complete file in the global theme directory.
Its relevant structure looks like this:

```json title="~/.config/opencode/themes/ocean.json (excerpt)"
{
  "base": {
    "text": {
      "base": "#d8f3ff"
    }
  },
  "dark": {
    "hue": {
      "accent": "$hue.cyan"
    }
  }
}
```

Then select `ocean` in settings or set `theme.name` to `ocean` in `cli.json`. The filename, without `.json`, is the
theme name.

| Scope   | Directory                                  |
| ------- | ------------------------------------------ |
| Global  | `~/.config/opencode/themes/`               |
| Project | `.opencode/themes/` in the project tree    |

OpenCode reads `.json` files only. A theme closer to the current directory replaces a global or parent theme with the
same name.

## Format

Every V2 theme declares one complete `base` token tree and at least one `light` or `dark` hue palette.
Modes inherit only from that file's base; they do not inherit from the built-in OpenCode theme or from each other. Use
the theme tool to generate a complete base before customizing it.

The examples below show only the sections relevant to each concept; they are not complete theme files.

```json title="themes/ocean.json"
{
  "base": {
    "text": {
      "base": "#16324f"
    }
  },
  "light": {
    "hue": {}
  },
  "dark": {
    "hue": {},
    "text": { "base": "#d8f3ff" }
  }
}
```

## Colors

Use a hex color, `transparent`, or a reference to another theme color:

```json title="themes/ocean.json"
{
  "base": {
    "text": {
      "base": "#d8f3ff",
      "muted": "$hue.neutral.400"
    },
    "background": {
      "base": "transparent"
    }
  }
}
```

Hex values may use 3, 4, 6, or 8 digits. References begin with `$`; hue references use the form
`$hue.<name>.<step>`.

## Hues

Override a hue alias to change a family of related colors at once:

```json title="themes/ocean.json"
{
  "base": {
    "categorical": ["accent", "purple", "green"]
  },
  "dark": {
    "hue": {
      "accent": "$hue.cyan",
      "interactive": "$hue.blue"
    }
  }
}
```

| Kind    | Values                                                               |
| ------- | -------------------------------------------------------------------- |
| Base    | `gray`, `red`, `orange`, `yellow`, `green`, `cyan`, `blue`, `purple` |
| Alias   | `accent`, `interactive`, `neutral`                                 |
| Step    | `100`, `200`, `300`, `400`, `500`, `600`, `700`, `800`, `900`      |

Hue steps follow the mode's contrast direction: light themes run from dark at `100` to light at `900`, while dark
themes run from light at `100` to dark at `900`.

`categorical` sets the ordered hues used to distinguish agents and other repeated items. It must contain at least one
base hue or alias.

## States

Use state keys to change interactive colors. Unspecified states use the nearest base value:

```json title="themes/ocean.json"
{
  "base": {
    "text": {
      "action": {
        "primary": {
          "base": "$hue.interactive.400",
          "$hovered": "$hue.interactive.300",
          "$disabled": "$hue.neutral.600"
        }
      }
    }
  }
}
```

| Group     | Values                                                    |
| --------- | --------------------------------------------------------- |
| Actions   | `primary`, `secondary`, `destructive`                     |
| States    | `$hovered`, `$focused`, `$pressed`, `$selected`, `$disabled` |

Form fields use the same state keys directly under `text.formfield` or `background.formfield`.

## Tokens

The complete `base` contains every token group. A mode may override any part of it after providing its complete hue
palette:

```json title="themes/ocean.json"
{
  "base": {
    "border": {
      "base": "$hue.neutral.700"
    },
    "syntax": {
      "comment": "$hue.neutral.500",
      "keyword": "$hue.accent.400"
    },
    "diff": {
      "text": {
        "added": "$hue.green.400",
        "removed": "$hue.red.400"
      }
    }
  }
}
```

| Group        | Purpose                                                       |
| ------------ | ------------------------------------------------------------- |
| `text`       | Base, muted, faint, action, form-field, and feedback text  |
| `background` | Base, surfaces, actions, form fields, and feedback fills    |
| `border`     | Borders                                                       |
| `scrollbar`  | Scrollbars                                                    |
| `diff`       | Added, removed, context, highlight, and line-number colors     |
| `syntax`     | Source-code highlighting                                      |
| `markdown`   | Markdown elements                                              |

Syntax keys are `comment`, `keyword`, `function`, `variable`, `string`, `number`, `type`, `operator`, and
`punctuation`. Markdown keys are `text`, `heading`, `link`, `linkText`, `code`, `blockQuote`, `emphasis`, `strong`,
`horizontalRule`, `listItem`, `listEnumeration`, `image`, `imageText`, and `codeBlock`.

## Raised surfaces

Panels, dialogs, menus, and toasts select their depth from `background.raised`. Dialogs additionally support a
contextual `@dialog` surface. The TUI re-resolves the palette after applying `@dialog`, so tokens that reference
`$background.base` follow the dialog background:

```json title="themes/ocean.json"
{
  "base": {
    "background": {
      "base": "#071521",
      "raised": {
        "base": "#0c1f2e",
        "high": "#102a3c",
        "max": "#16364b"
      }
    },
    "@dialog": {
      "background": {
        "base": "$background.raised.base"
      }
    }
  }
}
```

`@dialog` accepts the same token groups as the base mode. An action's contextual `base` also becomes the fallback
for its unspecified states; an explicit state override still wins.

---

### Services Www Src Docs Content Tools (`services/www/src/docs/content/tools.mdx`)

---
title: "Tools"
---

Ask for the outcome you want. OpenCode chooses the available tools, requests
approval when required, and returns the result.

```text
Find where request timeouts are configured, change the default to 30 seconds,
and run the relevant existing tests.
```

This task typically uses `grep` or `glob`, `read`, an editing tool, and `shell`.
You can also name a tool when you want a specific approach.

```text
Use grep to find every reference to DEFAULT_TIMEOUT, then read the matching files.
```

## Files

### Read

`read` returns a file or a non-recursive directory listing. Give it a `path`;
use `offset` and `limit` to page through large results.

```text
Read src/server.ts starting at line 120 and return at most 80 lines.
```

Text reads contain numbered lines and are limited to 2,000 lines and 50 KiB per
page. Individual lines are shortened after 2,000 characters. The tool also
passes PNG, JPEG, GIF, WebP, and PDF files to the model, up to 20 MiB of source
data. Other binary files fail. See [Attachments](/attachments) for supported
media and image processing.

Permission: `read` with the normalized path as its resource.

### Glob

`glob` finds file paths from a pattern such as `**/*.ts`. It searches the
current directory unless `path` selects another relative directory; `hidden`
includes hidden entries and `limit` caps the results.

```text
Use glob with **/*.test.ts under packages/core and return at most 50 files.
```

The default limit is 100 files and the search timeout is 30 seconds.
Permission: `glob` with the requested pattern as its resource.

### Grep

`grep` searches file contents and returns paths, line numbers, and previews.
Its `pattern` uses regular-expression syntax unless `literal` is true. Narrow a
search with `path`, `include`, `caseSensitive`, or `limit`.

```text
Use grep for the literal text "request timed out" in src, including only *.ts files.
```

The default limit is 100 matching lines and the search timeout is 30 seconds.
Permission: `grep` with the requested pattern, not the search path, as its
resource.

### Edit

`edit` replaces text in an existing file. Supply `path`, `oldString`, and a
different `newString`; the old text must match exactly once unless `replaceAll`
is true.

```text
In src/config.ts, replace the unique text "timeout: 60" with "timeout: 30".
```

Use `edit` for a focused change. OpenCode may format the file after writing it.
Permission: `edit` with the target path as its resource.

### Write

`write` creates or completely replaces a text file from `path` and `content`.
It creates missing parent directories and may run the configured formatter.

```text
Create docs/example.md with a heading and one setup command.
```

Use `edit` instead when only part of an existing file should change.
Permission: `edit` with the target path as its resource.

### Patch

`patch` applies one patch that can add, update, move, or delete several files.
Its `patchText` uses `*** Add File`, `*** Update File`, and `*** Delete File`
sections.

```text
Use patch to rename src/old.ts to src/new.ts and update its exported name.
```

OpenCode exposes `patch` for supported GPT models; other models receive `edit`
and `write` instead. Permission: `edit` with every affected path as a resource.

Paths outside the active Location or its project worktree are also checked
against `external_directory`, which is allowed by default. See
[Permissions](/permissions) for path normalization, rule order, and saved
approvals. To make outside material
available by name, configure [References](/references).

## Commands

### Shell

`shell` executes a command in the host user's shell. Set `workdir` instead of
putting `cd` in the command, and set `timeout` in milliseconds when the default
two-minute foreground timeout is not suitable.

```text
Run bun test from packages/core with a five-minute timeout.
```

Set `background` to true for a dev server or another long-running process.
Background calls return immediately and notify the session when they finish;
they have no timeout unless one is supplied. Large output is shortened and the
complete output is retained in a managed file.

Permission: `shell` with each scanner-produced command as a resource. The
scanner also checks an external working directory and directories it can infer
from the command. Shell has the host user's filesystem, process, and network
authority, so use narrow rules in [Permissions](/permissions).

## Web

### Webfetch

`webfetch` retrieves one HTTP or HTTPS URL as `markdown`, `text`, or `html`.
Markdown is the default; `timeout` accepts up to 120 seconds.

```text
Fetch https://example.com/docs as markdown.
```

It accepts textual responses such as HTML, plain text, JSON, and XML, but not
images or other binary downloads. Large output can be shortened while the full
text is retained in managed storage. Permission: `webfetch` with the requested
URL as its resource.

### Websearch

`websearch` searches the selected integration for current information. Its
input is a search `query`.

```text
Search the web for the latest Bun release notes.
```

Permission: `websearch` with the query as its resource. See [Websearch](/websearch)
for providers, selection, rate limits, and disabling the tool.

## Interaction

### Question

`question` pauses execution and presents one or more questions to the user.
Each question has a short header, prompt, and choices; `multiple` allows more
than one choice. A free-form answer is always available.

```text
Before changing the API, ask me to choose between a breaking change and a compatibility layer.
```

Permission: `question` with `*` as its resource. A client must support the
interactive form, and dismissing it cancels the question.

### Skill

`skill` loads the instructions and bundled resources for one available skill
ID into the conversation.

```text
Load the effect skill before changing this Effect code.
```

The ID must be in the advertised skill list or explicitly named by the user.
Permission: `skill` with the skill ID as its resource. See [Skills](/skills) for
creation, discovery, and loading rules.

## Automation

### Subagent

`subagent` starts a child session with a configured subagent. Supply the agent
ID, a short `description`, and a complete `prompt`.

```text
Ask the explore subagent to map the authentication flow and return the key files.
```

Foreground calls wait for the result. `background: true` returns immediately
and notifies the parent when the child finishes. Pass the returned `sessionID`
to continue that same child conversation. Only subagent-mode agents can be
used, and the default nesting depth is one.

Permission: `subagent` with the selected agent ID as its resource.

### Execute

`execute` runs JavaScript in Code Mode so the agent can call and combine tools
from the catalog. It is useful for parallel independent calls and for processing
results without adding every intermediate value to the model context.

```text
Read package.json and README.md in parallel, then return their relevant setup details.
```

The runtime has no direct filesystem access, imports, or timers. It provides
`fetch` for HTTP requests; everything else goes through tools in its catalog.
Denying `execute` with resource `*` removes Code Mode and every tool reached only
through it, including MCP tools from servers that do not set `codemode: false`.
Nested built-in and MCP tools still enforce their own permissions, and plugin
tools enforce the permissions they assert.

### Sessions

The `opencode` Code Mode namespace contains session utilities:

- `session_rename` changes the title of the current session, or another session
  selected by `sessionID`.
- `session_move` moves the current session, or another selected session, to a
  relative or absolute `directory`. The move takes effect at a safe boundary,
  so destination-dependent work belongs in a later call.

```text
Rename this session to "Timeout cleanup", then move it to the new worktree.
```

These utilities do not request a built-in permission action.

### Worktrees

The same namespace manages worktrees for the session's project:

- `worktree_create` creates a worktree from a `name` and returns its
  `directory`. The project's worktree configuration selects the destination and
  strategy.
- `worktree_list` lists the project's worktrees.
- `worktree_remove` removes a worktree OpenCode recorded for the project. Set
  `force` to discard uncommitted changes.

```text
Create a worktree named "login" and move this session into it.
```

`worktree_remove` uses the `edit` permission with the worktree directory as its
resource. The other worktree utilities do not request a built-in permission
action.

## Browser

The `browser` Code Mode namespace controls the browser attached by the OpenCode
desktop app. Open a tab, keep its returned `tabID`, then pass that explicit ID to
every page operation.

```text
Open https://example.com, take a snapshot of that tab, and report the main heading.
```

The namespace includes tab and navigation commands, page snapshots and search,
clicking and form input, screenshots, file transfer, console and network
inspection, performance traces, heap inspection, and Lighthouse audits.
Screenshots require a focused visible tab. Upload paths are server-local;
captures return server-local paths, and each file transfer is limited to 5 MiB.

Page content, logs, headers, and response bodies are untrusted data, not agent
instructions. A `browser` deny rule with resource `*` removes the browser catalog;
browser operations do not issue individual permission prompts.

## Extensions

[MCP servers](/mcp-servers) add tools whose names and inputs come from each
connected server. Their permission action is `<server>_<tool>` with resource
`*`. They are not a fixed part of the built-in catalog. By default, agents reach
them through `execute` under the server's namespace; set `codemode: false` on a
server to list its tools directly.

[Skills](/skills) add task instructions rather than new executable tools.
[Attachments](/attachments) put user-selected content into a prompt, while
[References](/references) provide named outside directories. These features
complement tools without bypassing their permission checks.

---

### Services Www Src Docs Content Troubleshooting (`services/www/src/docs/content/troubleshooting.mdx`)

---
title: "Troubleshooting"
---

<Callout type="tip">
  You can ask OpenCode to debug itself. Describe the problem and ask it to use this troubleshooting page; it can read
  the steps below, inspect its service and logs, and help identify the issue.
</Callout>

OpenCode uses a client-server architecture. A background server owns sessions, plugins, permissions, and other application
state. Start by determining whether an issue is in a client, the shared server, or a specific project.

## Check the background service

Show the current server information:

```bash
opencode service status
```

Verify that its API is healthy:

```bash
opencode api get /api/info
```

If the service is stuck or unhealthy, restart it:

```bash
opencode service restart
```

You can also stop and start it explicitly:

```bash
opencode service stop
opencode service start
```

<Callout type="note">
  OpenCode normally discovers or starts the shared background service automatically. The service commands are only
  needed when diagnosing its lifecycle.
</Callout>

## Allow a browser origin

If a browser client on another origin cannot connect because of CORS, add the client's origin to the service configuration:

```bash
opencode service set cors http://192.168.1.10:3001
opencode service get cors
```

Use an exact HTTP or HTTPS origin, including the port when needed, without a path or trailing slash. To allow multiple
origins, pass a comma-separated list as one argument; whitespace around each origin is trimmed:

```bash
opencode service set cors "http://192.168.1.10:3001, https://app.example.com"
```

`service get cors` prints a JSON array. Remove the configured list with:

```bash
opencode service unset cors
```

Setting or unsetting service configuration stops the background service. Its next start picks up the new configuration;
use `opencode service start` to start it explicitly.

For a foreground server, repeat `--cors` for each additional allowed origin:

```bash
opencode serve --cors http://192.168.1.10:3001 --cors https://app.example.com
```

With `serve --service`, supplied `--cors` flags override the persisted list for that process. Without those flags, service
mode uses the persisted list. CORS does not change the listening address or bypass server authentication.

## Inspect the API

The `api` command uses the local service discovery and authentication flow. It accepts either an HTTP method and path or an
OpenAPI operation ID.

See the [API reference](/api) for all endpoints and operation IDs.

Pass a JSON request body with `--data` or `-d`, and add headers with `--header` or `-H`.

<Callout type="warning">
  Running `opencode api` may start the background service when no compatible healthy service is available.
</Callout>

## Read logs

Installed builds write logs to:

```text
~/.local/share/opencode/log/opencode.log
```

Follow the log while reproducing the problem:

```bash
tail -f ~/.local/share/opencode/log/opencode.log
```

Each line includes a process `run` ID and a `role` field. Use `role=server` for session, provider, plugin, permission, and
tool activity.

```bash
grep 'role=server' ~/.local/share/opencode/log/opencode.log
grep 'run=8fc3b1d5' ~/.local/share/opencode/log/opencode.log
```

## Capture a heap snapshot

Write a memory (heap) snapshot of the running background server on any platform:

```bash
opencode debug heap-dump
```

The command waits until the snapshot is complete, then prints its path:

```text
/home/me/.local/share/opencode/log/heap-48213-2026-10-23T013012345Z.heapsnapshot
```

- It only uses a server that is already running. It never starts, replaces, or restarts one.
- Use `--server <url>` to capture a server you started with `opencode serve`. Set `OPENCODE_PASSWORD` if it has one.
- Open the file in the Memory panel of Chrome DevTools.

<Callout type="warning">
  The server pauses while it writes the snapshot, and its memory use can increase for a short time. The snapshot can
  contain prompts, file contents, and credentials. Do not share it publicly.
</Callout>

## Capture CPU and memory profiles

On macOS and Linux, you can signal a running OpenCode process to capture diagnostic data. Get the background server PID
from the health endpoint:

```bash
opencode api get /api/info
```

Use the `pid` from the response with one of these signals:

- `SIGPROF` captures a ten-second CPU profile:

  ```bash
  kill -SIGPROF <pid>
  ```

  The result is written to the log directory as `cpu-<pid>-<timestamp>.cpuprofile`.

- `SIGUSR1` captures a memory (heap) snapshot:

  ```bash
  kill -SIGUSR1 <pid>
  ```

  The result is written to the log directory as `heap-<pid>-<timestamp>.heapsnapshot`.

Wait for `CPU profile written` or `heap snapshot written` in `opencode.log` before opening the file. The corresponding
log entry includes its complete path. You can inspect both file types in Chrome DevTools.

<Callout type="note">
  Signal-triggered profiles are not available on Windows. Use `opencode debug heap-dump` for heap snapshots instead.
  Writing a heap snapshot can pause the process and temporarily increase its memory usage.
</Callout>

## Service files

The shared server registers itself at:

```text
~/.local/state/opencode/service.json
```

Its private service configuration is stored separately at:

```text
~/.config/opencode/service.json
```

The database normally lives at:

```text
~/.local/share/opencode/opencode.db
```

`OPENCODE_DB` can override the database location.

<Callout type="warning">
  Do not delete or edit service files or the database while troubleshooting. Use the service commands to manage the
  daemon, and make a backup before inspecting persistent data with external tools.
</Callout>

## Report an issue

Include the following when reporting a reproducible problem:

- Output from `opencode --version`
- Output from `opencode service status`
- The smallest sequence of steps that reproduces the issue
- Whether the issue affects the shared service, a specific client, or one project
- Relevant log lines, including their `run` and `role` fields

Remove API keys, authorization headers, prompts, file contents, and other sensitive data before sharing logs.

File reproducible problems in [GitHub Issues](https://github.com/anomalyco/opencode/issues).

---

### Services Www Src Docs Content Warming (`services/www/src/docs/content/warming.mdx`)

---
title: "Warming"
---

Session warming sends periodic model requests to preserve provider-side prompt
caches or other short-lived state while you pause between prompts. It is
disabled by default.

Enable warming in any [OpenCode configuration file](/config):

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "warming": true,
}
```

With this configuration, OpenCode warms a recently active session after four
minutes without a model request. It continues every four minutes until 30
minutes have passed since the latest non-warming request.

## Options

Use the object form to change the warming prompt, idle interval, or active
window:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "warming": {
    "prompt": "Do not perform any work. Reply with exactly: OK",
    "interval": "5 minutes",
    "duration": "1 hour",
  },
}
```

| Field | Default | Purpose |
| --- | --- | --- |
| `prompt` | Keep-alive instruction | Appended as a transient user message for each warming request. The default asks the model to do no work, use no tools, and reply with `OK`. |
| `interval` | `"4 minutes"` | Idle time before the next warming request. |
| `duration` | `"30 minutes"` | Warming window measured from the latest non-warming model request. |

Omitted object fields keep their defaults. For example, this changes only the
interval:

```jsonc title="opencode.jsonc"
{
  "warming": {
    "interval": "2 minutes",
  },
}
```

## Durations

`interval` and `duration` accept duration strings. Both must resolve to finite
values greater than zero; otherwise OpenCode skips warming and logs a warning.

```jsonc title="opencode.jsonc"
{
  "warming": {
    "interval": "30 seconds",
    "duration": "1 hour",
  },
}
```

## Timing

Warming starts after a non-warming model request. After a warming request
finishes, the next idle interval starts, but the active window is not extended.

```text
00:00  normal model request
00:04  warming request
00:08  warming request
00:30  warming stops
```

Any new non-warming model activity resets both timers. If the interval is as
long as or longer than the duration, the active window expires before a warming
request is sent.

```text
00:00  normal model request
00:20  normal model request; window restarts
00:24  warming request
00:50  warming stops
```

## Requests

A warming request uses the session's current model, agent, instructions, and
conversation context. OpenCode appends the configured prompt transiently,
makes one model call, and discards the response.

```text
[current session context]
[transient user message: keep-alive prompt]
→ one model response, discarded
```

The request does not admit input, add messages to history, or mutate durable
session state. OpenCode does not dispatch local tool calls or continue a tool
loop; the default prompt also tells the model not to use tools.

## Failures

Warming failures are logged without failing or changing the session. OpenCode
waits until the next interval before trying again, while the original active
window continues to count down.

```text
00:04  warming request fails; session is unchanged
00:08  next warming attempt
```

## Costs

Warming requests are real provider requests. They can consume tokens, incur
costs, count against rate limits, and fail like other model requests.

- Shorter intervals increase request volume.
- Longer durations allow more warming requests.
- Enable warming only when its provider-side benefit is worth the added usage.

For example, the defaults allow up to seven warming attempts during one
uninterrupted 30-minute window: at minutes 4, 8, 12, 16, 20, 24, and 28.

## Disabling

Set `warming` to `false` to disable it explicitly. Omitting the field also
leaves warming disabled.

```jsonc title="opencode.jsonc"
{
  "warming": false,
}
```

---

### Services Www Src Docs Content Websearch (`services/www/src/docs/content/websearch.mdx`)

---
title: "Websearch"
---

Ask OpenCode for current information and it can search the web, read the results, and include source links in its response.

```text
Find the latest Bun release and summarize the changes.
```

The first search asks you to allow web search and select a provider. OpenCode remembers your choice for later sessions.

## Providers

OpenCode includes five search providers:

| Provider | ID | Environment variable |
| --- | --- | --- |
| Exa | `exa` | `EXA_API_KEY` |
| Firecrawl | `firecrawl` | `FIRECRAWL_API_KEY` |
| Parallel | `parallel` | `PARALLEL_API_KEY` |
| Tavily | `tavily` | `TAVILY_API_KEY` |
| TinyFish | `tinyfish` | `TINYFISH_API_KEY` (optional) |

Connect an account from the TUI with `/connect`, or set the provider's environment variable before starting OpenCode.

```bash
$ TAVILY_API_KEY=your-key opencode
```

## Selection

Set a provider in `opencode.jsonc` to skip the selection prompt.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "websearch": {
    "provider": "tavily",
  },
}
```

Use `"random"` to choose an available provider automatically. Each session keeps using its selected provider until that provider is rate limited.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "websearch": {
    "provider": "random",
  },
}
```

## Limits

When a provider returns HTTP 429, random selection retries the search with another available provider. The rate-limited provider waits for its `Retry-After` period, or 60 seconds when the response does not include a valid period.

```text
Exa returns HTTP 429
→ Exa enters cooldown
→ OpenCode retries with another provider
```

If every provider is cooling down, the search fails immediately. Moving a session or restarting its server clears its remembered provider; cooldowns are shared by sessions in the same workspace.

## Permissions

Web searches use the `websearch` permission action and the search query as the resource. Ask before searches that are not explicitly allowed.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "permissions": [
    {
      "action": "websearch",
      "resource": "*",
      "effect": "ask",
    },
  ],
}
```

See [Permissions](/permissions) for rule order and matching.

## Disable

Set `websearch` to `false` to remove the web search tool from model requests.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "websearch": false,
}
```

---

### Packages Web Src Content Docs Ar Acp (`packages/web/src/content/docs/ar/acp.mdx`)

---
title: دعم ACP
description: استخدم OpenCode في أي محرر متوافق مع ACP.
---

يدعم OpenCode بروتوكول [Agent Client Protocol](https://agentclientprotocol.com) أو (ACP)، مما يتيح لك استخدامه مباشرة في المحررات وبيئات التطوير المتكاملة (IDEs) المتوافقة.

:::tip
للاطلاع على قائمة بالمحررات والأدوات التي تدعم ACP، راجع [ACP progress report](https://zed.dev/blog/acp-progress-report#available-now).
:::

ACP بروتوكول مفتوح يوحّد آلية التواصل بين محررات الشيفرة ووكلاء البرمجة بالذكاء الاصطناعي.

---

## الإعداد

لاستخدام OpenCode عبر ACP، اضبط محررك ليشغّل الأمر `opencode acp`.

يشغّل هذا الأمر OpenCode كعملية فرعية متوافقة مع ACP تتواصل مع محررك عبر JSON-RPC باستخدام stdio.

فيما يلي أمثلة لمحررات شائعة تدعم ACP.

---

### Zed

ثبّت OpenCode من [سجل ACP في Zed](https://zed.dev/docs/ai/external-agents#registry) عبر تشغيل `zed: acp registry` من لوحة الأوامر.

لاستخدام ملف OpenCode تنفيذي مخصص بدلاً من ذلك، أضفه إلى إعدادات [Zed](https://zed.dev) (`~/.config/zed/settings.json`):

```json title="~/.config/zed/settings.json"
{
  "agent_servers": {
    "OpenCode": {
      "type": "custom",
      "command": "opencode",
      "args": ["acp"]
    }
  }
}
```

لفتحه، استخدم الإجراء `agent: new thread` في **Command Palette**.

يمكنك أيضا ربط اختصار لوحة مفاتيح عبر تعديل `keymap.json`:

```json title="keymap.json"
[
  {
    "bindings": {
      "cmd-alt-o": [
        "agent::NewExternalAgentThread",
        {
          "agent": {
            "custom": {
              "name": "OpenCode",
              "command": {
                "command": "opencode",
                "args": ["acp"]
              }
            }
          }
        }
      ]
    }
  }
]
```

---

### JetBrains IDEs

أضف إلى ملف acp.json الخاص بـ [JetBrains IDE](https://www.jetbrains.com/) وفقا لـ [documentation](https://www.jetbrains.com/help/ai-assistant/acp.html):

```json title="acp.json"
{
  "agent_servers": {
    "OpenCode": {
      "command": "/absolute/path/bin/opencode",
      "args": ["acp"]
    }
  }
}
```

لفتحه، اختر الوكيل الجديد 'OpenCode' من محدد الوكلاء في AI Chat.

---

### Avante.nvim

أضف إلى إعدادات [Avante.nvim](https://github.com/yetone/avante.nvim):

```lua
{
  acp_providers = {
    ["opencode"] = {
      command = "opencode",
      args = { "acp" }
    }
  }
}
```

إذا احتجت إلى تمرير متغيرات البيئة:

```lua {6-8}
{
  acp_providers = {
    ["opencode"] = {
      command = "opencode",
      args = { "acp" },
      env = {
        OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY")
      }
    }
  }
}
```

---

### CodeCompanion.nvim

لاستخدام OpenCode كوكيل ACP في [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim)، أضف التالي إلى إعدادات Neovim:

```lua
require("codecompanion").setup({
  interactions = {
    chat = {
      adapter = {
        name = "opencode",
        model = "claude-sonnet-4",
      },
    },
  },
})
```

يضبط هذا الإعداد CodeCompanion لاستخدام OpenCode كوكيل ACP للدردشة.

إذا احتجت إلى تمرير متغيرات البيئة (مثل `OPENCODE_API_KEY`)، فارجع إلى [Configuring Adapters: Environment Variables](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) ضمن توثيق CodeCompanion.nvim للاطلاع على التفاصيل كاملة.

## الدعم

يعمل OpenCode عبر ACP بالطريقة نفسها التي يعمل بها في terminal. جميع الميزات مدعومة:

:::note
بعض أوامر الشرطة المائلة المضمنة مثل `/undo` و`/redo` غير مدعومة حاليا.
:::

- الأدوات المضمنة (عمليات الملفات، أوامر terminal، إلخ.)
- الأدوات المخصصة وأوامر الشرطة المائلة
- خوادم MCP المضبوطة في إعدادات OpenCode
- قواعد خاصة بالمشروع من `AGENTS.md`
- المنسقات (formatters) والمدققات (linters) المخصصة
- نظام الوكلاء والأذونات

---

### Packages Web Src Content Docs Ar Agents (`packages/web/src/content/docs/ar/agents.mdx`)

---
title: الوكلاء
description: هيّئ الوكلاء المتخصصين واستخدمهم.
---

الوكلاء هم مساعدون متخصصون بالذكاء الاصطناعي يمكن تهيئتهم لمهام وسير عمل محدد. يتيحون لك إنشاء أدوات مركزة مع موجّهات مخصصة ونماذج وصلاحية وصول للأدوات.

:::tip
استخدم وكيل plan لتحليل الشفرة ومراجعة الاقتراحات بدون إجراء أي تغييرات على الشفرة.
:::

يمكنك التبديل بين الوكلاء أثناء الجلسة أو استدعاؤهم عبر الإشارة بـ `@`.

---

## الأنواع

يوجد نوعان من الوكلاء في OpenCode: وكلاء أساسيون ووكلاء فرعيون.

---

### الوكلاء الأساسيون

الوكلاء الأساسيون هم المساعدون الرئيسيون الذين تتفاعل معهم مباشرة. يمكنك التنقل بينهم باستخدام مفتاح **Tab** أو اختصار `switch_agent` الذي قمت بتهيئته. يتولى هؤلاء الوكلاء محادثتك الرئيسية. يتم ضبط وصول الأدوات عبر الأذونات — على سبيل المثال، يمتلك Build جميع الأدوات مفعلة بينما يكون Plan مقيّدا.

:::tip
يمكنك استخدام مفتاح **Tab** للتبديل بين الوكلاء الأساسيين أثناء الجلسة.
:::

يأتي OpenCode مع وكيلين أساسيين مدمجين: **Build** و **Plan**. سنلقي نظرة عليهما أدناه.

---

### الوكلاء الفرعيون

الوكلاء الفرعيون هم مساعدين متخصصين يمكن للوكلاء الأساسيين استدعاؤهم لمهام محددة. يمكنك أيضا استدعاؤهم يدويا عبر **الإشارة بـ @** في رسائلك.

يأتي OpenCode مع ثلاثة وكلاء فرعيين مدمجين: **General** و **Explore** و **Scout**. سنلقي نظرة على ذلك أدناه.

---

## المدمجة

يأتي OpenCode مع وكيلين أساسيين مدمجين وثلاثة وكلاء فرعيين مدمجين.

---

### استخدام Build

_الوضع_: `primary`

Build هو الوكيل الأساسي **الافتراضي** مع تفعيل جميع الأدوات. هذا هو الوكيل القياسي لأعمال التطوير عندما تحتاج إلى وصول كامل لعمليات الملفات وأوامر النظام.

---

### استخدام Plan

_الوضع_: `primary`

وكيل مقيّد صُمم للتخطيط والتحليل. نستخدم نظام أذونات لمنحك تحكما أكبر ومنع التغييرات غير المقصودة.
افتراضيا، يتم ضبط كل ما يلي على `ask`:

- `file edits`: جميع عمليات الكتابة والتصحيح (patches) والتحرير
- `shell`: جميع أوامر shell

يفيد هذا الوكيل عندما تريد من LLM تحليل الشفرة أو اقتراح تغييرات أو إنشاء خطط بدون إجراء أي تعديلات فعلية على قاعدة الشفرة.

---

### استخدام General

_الوضع_: `subagent`

وكيل عام الغرض للبحث في أسئلة معقدة وتنفيذ مهام متعددة الخطوات. لديه وصول كامل للأدوات، لذا يمكنه إجراء تغييرات على الملفات عند الحاجة. استخدمه لتشغيل عدة وحدات عمل بالتوازي.

---

### استخدام Explore

_الوضع_: `subagent`

وكيل سريع للقراءة فقط لاستكشاف قواعد الشفرة. لا يستطيع تعديل الملفات. استخدمه عندما تحتاج إلى العثور بسرعة على ملفات عبر أنماط، أو البحث في الشفرة عن كلمات مفتاحية، أو الإجابة عن أسئلة حول قاعدة الشفرة.

---

### استخدام Scout

_الوضع_: `subagent`

وكيل للقراءة فقط مخصص للوثائق الخارجية وأبحاث التبعيات. استخدمه عندما تحتاج إلى استنساخ مستودع تبعية داخل ذاكرة التخزين المؤقت المُدارة في OpenCode، أو فحص الشفرة المصدرية لمكتبة، أو إجراء مراجع متقاطعة بين الشفرة المحلية والتنفيذات upstream بدون تعديل مساحة العمل الخاصة بك.

---

### استخدام Compaction

_الوضع_: `primary`

وكيل نظام مخفي يضغط السياق الطويل إلى ملخص أصغر. يعمل تلقائيا عند الحاجة ولا يمكن اختياره من واجهة المستخدم.

---

### استخدام Title

_الوضع_: `primary`

وكيل نظام مخفي ينشئ عناوين قصيرة للجلسات. يعمل تلقائيا ولا يمكن اختياره من واجهة المستخدم.

---

### استخدام Summary

_الوضع_: `primary`

وكيل نظام مخفي ينشئ ملخصات للجلسات. يعمل تلقائيا ولا يمكن اختياره من واجهة المستخدم.

---

## الاستخدام

1. للوكلاء الأساسيين، استخدم مفتاح **Tab** للتنقل بينهم أثناء الجلسة. يمكنك أيضا استخدام اختصار `switch_agent` الذي قمت بتهيئته.

2. يمكن استدعاء الوكلاء الفرعيين:
   - **تلقائيا** بواسطة الوكلاء الأساسيين لمهام متخصصة بناء على أوصافهم.
   - يدويا عبر **الإشارة بـ @** إلى وكيل فرعي في رسالتك. على سبيل المثال:

     ```txt frame="none"
     @general help me search for this function
     ```

3. **التنقل بين الجلسات**: عندما ينشئ الوكلاء الفرعيون جلسات فرعية خاصة بهم، يمكنك التنقل بين الجلسة الأم وجميع الجلسات الفرعية باستخدام:
   - **\<Leader>+Right** (أو اختصار `session_child_cycle` الذي قمت بتهيئته) للتنقل للأمام عبر parent → child1 → child2 → ... → parent
   - **\<Leader>+Left** (أو اختصار `session_child_cycle_reverse` الذي قمت بتهيئته) للتنقل للخلف عبر parent ← child1 ← child2 ← ... ← parent

   يتيح لك ذلك التبديل بسلاسة بين المحادثة الرئيسية وعمل الوكلاء الفرعيين المتخصص.

---

## التهيئة

يمكنك تخصيص الوكلاء المدمجين أو إنشاء وكلائك عبر التهيئة. يمكن تهيئة الوكلاء بطريقتين:

---

### JSON

هيّئ الوكلاء في ملف إعدادات `opencode.json`:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "agent": {
    "build": {
      "mode": "primary",
      "model": "anthropic/claude-sonnet-4-20250514",
      "prompt": "{file:./prompts/build.txt}",
      "tools": {
        "write": true,
        "edit": true,
        "shell": true
      }
    },
    "plan": {
      "mode": "primary",
      "model": "anthropic/claude-haiku-4-20250514",
      "tools": {
        "write": false,
        "edit": false,
        "shell": false
      }
    },
    "code-reviewer": {
      "description": "Reviews code for best practices and potential issues",
      "mode": "subagent",
      "model": "anthropic/claude-sonnet-4-20250514",
      "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.",
      "tools": {
        "write": false,
        "edit": false
      }
    }
  }
}
```

---

### Markdown

يمكنك أيضا تعريف الوكلاء باستخدام ملفات Markdown. ضعها في:

- عام: `~/.config/opencode/agents/`
- لكل مشروع: `.opencode/agents/`

```markdown title="~/.config/opencode/agents/review.md"
---
description: Reviews code for quality and best practices
mode: subagent
model: anthropic/claude-sonnet-4-20250514
temperature: 0.1
tools:
  write: false
  edit: false
  shell: false
---

You are in code review mode. Focus on:

- Code quality and best practices
- Potential bugs and edge cases
- Performance implications
- Security considerations

Provide constructive feedback without making direct changes.
```

يصبح اسم ملف Markdown هو اسم الوكيل. على سبيل المثال، ينشئ `review.md` وكيلا باسم `review`.

---

## الخيارات

لنلق نظرة على خيارات التهيئة هذه بمزيد من التفصيل.

---

### الوصف

استخدم خيار `description` لتقديم وصف موجز لما يفعله الوكيل ومتى ينبغي استخدامه.

```json title="opencode.json"
{
  "agent": {
    "review": {
      "description": "Reviews code for best practices and potential issues"
    }
  }
}
```

هذا خيار تهيئة **إلزامي**.

---

### درجة الحرارة

تحكم في العشوائية والإبداع في ردود LLM عبر إعداد `temperature`.

القيم الأقل تجعل الردود أكثر تركيزا وحتمية، بينما تزيد القيم الأعلى من الإبداع والتنوع.

```json title="opencode.json"
{
  "agent": {
    "plan": {
      "temperature": 0.1
    },
    "creative": {
      "temperature": 0.8
    }
  }
}
```

عادة تتراوح قيم `temperature` بين 0.0 و 1.0:

- **0.0-0.2**: ردود شديدة التركيز وحتمية، مثالية لتحليل الشفرة والتخطيط
- **0.3-0.5**: ردود متوازنة مع قدر من الإبداع، مناسبة لمهام التطوير العامة
- **0.6-1.0**: ردود أكثر إبداعا وتنوعا، مفيدة للعصف الذهني والاستكشاف

```json title="opencode.json"
{
  "agent": {
    "analyze": {
      "temperature": 0.1,
      "prompt": "{file:./prompts/analysis.txt}"
    },
    "build": {
      "temperature": 0.3
    },
    "brainstorm": {
      "temperature": 0.7,
      "prompt": "{file:./prompts/creative.txt}"
    }
  }
}
```

إذا لم يتم تحديد temperature، يستخدم OpenCode القيم الافتراضية الخاصة بالنموذج؛ عادة 0 لمعظم النماذج و 0.55 لنماذج Qwen.

---

### الحد الأقصى للخطوات

تحكم في الحد الأقصى لعدد التكرارات الوكيلة التي يمكن لوكيل تنفيذها قبل أن يُجبر على الرد بنص فقط. يتيح ذلك للمستخدمين الذين يرغبون في التحكم بالتكاليف وضع حد للإجراءات الوكيلة.

إذا لم يتم ضبط هذا الخيار، سيستمر الوكيل بالتكرار حتى يقرر النموذج التوقف أو يقاطع المستخدم الجلسة.

```json title="opencode.json"
{
  "agent": {
    "quick-thinker": {
      "description": "Fast reasoning with limited iterations",
      "prompt": "You are a quick thinker. Solve problems with minimal steps.",
      "steps": 5
    }
  }
}
```

عند بلوغ الحد، يتلقى الوكيل موجّها نظاميا خاصا يطلب منه الرد بملخص لعمله والمهام المتبقية الموصى بها.

:::caution
الحقل القديم `maxSteps` متقادم. استخدم `steps` بدلا منه.
:::

---

### التعطيل

اضبطه على `true` لتعطيل الوكيل.

```json title="opencode.json"
{
  "agent": {
    "review": {
      "disable": true
    }
  }
}
```

---

### الموجّه

حدد ملف موجّه نظامي مخصص لهذا الوكيل عبر إعداد `prompt`. يجب أن يحتوي ملف الموجّه على تعليمات خاصة بهدف الوكيل.

```json title="opencode.json"
{
  "agent": {
    "review": {
      "prompt": "{file:./prompts/code-review.txt}"
    }
  }
}
```

هذا المسار نسبي لمكان وجود ملف الإعدادات. لذلك يعمل هذا لكل من إعدادات OpenCode العامة وإعدادات المشروع.

---

### النموذج

استخدم إعداد `model` لتجاوز (override) النموذج لهذا الوكيل. يفيد ذلك لاستخدام نماذج مختلفة مُحسّنة لمهام مختلفة. على سبيل المثال، نموذج أسرع للتخطيط ونموذج أقدر للتنفيذ.

:::tip
إذا لم تحدد نموذجا، يستخدم الوكلاء الأساسيون [النموذج المُهيأ عالميا](/docs/config#models)، بينما يستخدم الوكلاء الفرعيون نموذج الوكيل الأساسي الذي استدعاهم.
:::

```json title="opencode.json"
{
  "agent": {
    "plan": {
      "model": "anthropic/claude-haiku-4-20250514"
    }
  }
}
```

يستخدم معرّف النموذج في إعدادات OpenCode الصيغة `provider/model-id`. على سبيل المثال، إذا كنت تستخدم [OpenCode Zen](https://opencode.ai/v2/docs/console/)، فستستخدم `opencode/gpt-5.1-codex` لـ GPT 5.1 Codex.

---

### الأدوات

تحكم في الأدوات المتاحة لهذا الوكيل عبر إعداد `tools`. يمكنك تفعيل أو تعطيل أدوات محددة بضبطها على `true` أو `false`.

```json title="opencode.json" {3-6,9-12}
{
  "$schema": "https://opencode.ai/config.json",
  "tools": {
    "write": true,
    "shell": true
  },
  "agent": {
    "plan": {
      "tools": {
        "write": false,
        "shell": false
      }
    }
  }
}
```

:::note
إعدادات الوكيل الخاصة تتجاوز الإعدادات العامة.
:::

يمكنك أيضا استخدام المحارف البديلة (wildcards) للتحكم في عدة أدوات دفعة واحدة. على سبيل المثال، لتعطيل جميع الأدوات القادمة من خادم MCP:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "agent": {
    "readonly": {
      "tools": {
        "mymcp_*": false,
        "write": false,
        "edit": false
      }
    }
  }
}
```

[اعرف المزيد عن الأدوات](/docs/tools).

---

### الأذونات

يمكنك تهيئة الأذونات لإدارة الإجراءات التي يستطيع الوكيل تنفيذها. حاليا، يمكن تهيئة أذونات أدوات `edit` و `shell` و `webfetch` إلى:

- `"ask"` — طلب الموافقة قبل تشغيل الأداة
- `"allow"` — السماح بكل العمليات بدون موافقة
- `"deny"` — تعطيل الأداة

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "edit": "deny"
  }
}
```

يمكنك تجاوز هذه الأذونات لكل وكيل.

```json title="opencode.json" {3-5,8-10}
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "edit": "deny"
  },
  "agent": {
    "build": {
      "permission": {
        "edit": "ask"
      }
    }
  }
}
```

يمكنك أيضا ضبط الأذونات في وكلاء Markdown.

```markdown title="~/.config/opencode/agents/review.md"
---
description: Code review without edits
mode: subagent
permission:
  edit: deny
  shell:
    "*": ask
    "git diff": allow
    "git log*": allow
    "grep *": allow
  webfetch: deny
---

Only analyze code and suggest changes.
```

يمكنك ضبط الأذونات لأوامر shell محددة.

```json title="opencode.json" {7}
{
  "$schema": "https://opencode.ai/config.json",
  "agent": {
    "build": {
      "permission": {
        "shell": {
          "git push": "ask",
          "grep *": "allow"
        }
      }
    }
  }
}
```

يمكن لهذا أن يقبل نمط glob.

```json title="opencode.json" {7}
{
  "$schema": "https://opencode.ai/config.json",
  "agent": {
    "build": {
      "permission": {
        "shell": {
          "git *": "ask"
        }
      }
    }
  }
}
```

ويمكنك أيضا استخدام المحرف البديل `*` لإدارة الأذونات لكل الأوامر.
وبما أن آخر قاعدة مطابقة لها الأولوية، ضع قاعدة `*` أولا ثم القواعد الأكثر تخصيصا بعدها.

```json title="opencode.json" {8}
{
  "$schema": "https://opencode.ai/config.json",
  "agent": {
    "build": {
      "permission": {
        "shell": {
          "*": "ask",
          "git status *": "allow"
        }
      }
    }
  }
}
```

[اعرف المزيد عن الأذونات](/docs/permissions).

---

### الوضع

تحكم في وضع الوكيل عبر إعداد `mode`. يُستخدم خيار `mode` لتحديد كيفية استخدام الوكيل.

```json title="opencode.json"
{
  "agent": {
    "review": {
      "mode": "subagent"
    }
  }
}
```

يمكن ضبط خيار `mode` على `primary` أو `subagent` أو `all`. إذا لم يتم تحديد `mode`، فالقيمة الافتراضية هي `all`.

---

### مخفي

أخفِ وكيلا فرعيا من قائمة الإكمال التلقائي لـ `@` عبر `hidden: true`. يفيد ذلك للوكلاء الفرعيين الداخليين الذين ينبغي استدعاؤهم برمجيا فقط بواسطة وكلاء آخرين عبر أداة Task.

```json title="opencode.json"
{
  "agent": {
    "internal-helper": {
      "mode": "subagent",
      "hidden": true
    }
  }
}
```

يؤثر هذا فقط على ظهور الوكيل للمستخدم في قائمة الإكمال التلقائي. لا يزال بإمكان النموذج استدعاء الوكلاء المخفيين عبر أداة Task إذا سمحت الأذونات.

:::note
ينطبق فقط على الوكلاء ذوي `mode: subagent`.
:::

---

### أذونات Task

تحكم في أي الوكلاء الفرعيين يمكن لوكيل استدعاؤهم عبر أداة Task باستخدام `permission.task`. يستخدم أنماط glob لمطابقة مرنة.

```json title="opencode.json"
{
  "agent": {
    "orchestrator": {
      "mode": "primary",
      "permission": {
        "task": {
          "*": "deny",
          "orchestrator-*": "allow",
          "code-reviewer": "ask"
        }
      }
    }
  }
}
```

عند ضبطها على `deny`، تتم إزالة الوكيل الفرعي بالكامل من وصف أداة Task، لذا لن يحاول النموذج استدعاءه.

:::tip
تُقيّم القواعد بالترتيب، و **آخر قاعدة مطابقة هي التي تفوز**. في المثال أعلاه، يطابق `orchestrator-planner` كلا من `*` (deny) و `orchestrator-*` (allow)، ولكن بما أن `orchestrator-*` تأتي بعد `*` فالنتيجة هي `allow`.
:::

:::tip
يمكن للمستخدمين دائما استدعاء أي وكيل فرعي مباشرة عبر قائمة الإكمال التلقائي لـ `@`، حتى لو كانت أذونات task للوكيل سترفض ذلك.
:::

---

### اللون

خصص المظهر البصري للوكيل في واجهة المستخدم عبر خيار `color`. يؤثر ذلك على كيفية ظهور الوكيل في الواجهة.

استخدم لونا سداسيا صالحا (مثل `#FF5733`) أو لون سمة: `primary` و `secondary` و `accent` و `success` و `warning` و `error` و `info`.

```json title="opencode.json"
{
  "agent": {
    "creative": {
      "color": "#ff6b6b"
    },
    "code-reviewer": {
      "color": "accent"
    }
  }
}
```

---

### Top P

تحكم في تنوع الردود عبر خيار `top_p`. بديل عن temperature للتحكم بالعشوائية.

```json title="opencode.json"
{
  "agent": {
    "brainstorm": {
      "top_p": 0.9
    }
  }
}
```

تتراوح القيم من 0.0 إلى 1.0. القيم الأقل أكثر تركيزا، والقيم الأعلى أكثر تنوعا.

---

### خيارات إضافية

أي خيارات أخرى تحددها في تهيئة الوكيل سيتم **تمريرها مباشرة** إلى مزود النموذج كخيارات للنموذج. يتيح لك ذلك استخدام ميزات ومعاملات خاصة بالمزود.

على سبيل المثال، مع نماذج الاستدلال من OpenAI يمكنك التحكم في مجهود الاستدلال:

```json title="opencode.json" {6,7}
{
  "agent": {
    "deep-thinker": {
      "description": "Agent that uses high reasoning effort for complex problems",
      "model": "openai/gpt-5",
      "reasoningEffort": "high",
      "textVerbosity": "low"
    }
  }
}
```

هذه الخيارات الإضافية تعتمد على النموذج والمزود. راجع توثيق مزودك لمعرفة المعاملات المتاحة.

:::tip
شغّل `opencode models` لعرض قائمة بالنماذج المتاحة.
:::

---

## إنشاء وكلاء

أنشئ وكيلا جديدا بإضافة ملف Markdown إلى `.opencode/agents/` للمشروع أو إلى `~/.config/opencode/agents/` على المستوى العام. يصبح اسم الملف اسم الوكيل، وتضبط الواجهة الأمامية (frontmatter) وصفه ووضعه ونموذجه وصلاحياته. راجع [Markdown](#markdown) أعلاه لمعرفة تنسيق الملف.

شغّل `opencode debug agents` لعرض الوكلاء الذين حمّلهم OpenCode.

---

## حالات الاستخدام

فيما يلي بعض حالات الاستخدام الشائعة لوكلاء مختلفين.

- **Build agent**: أعمال تطوير كاملة مع تفعيل جميع الأدوات
- **Plan agent**: تحليل وتخطيط بدون إجراء تغييرات
- **Review agent**: مراجعة الشفرة مع وصول للقراءة فقط بالإضافة إلى أدوات التوثيق
- **Debug agent**: يركز على التحقيق مع تفعيل أدوات shell والقراءة
- **Docs agent**: كتابة التوثيق مع عمليات الملفات بدون أوامر النظام

---

## أمثلة

فيما يلي بعض أمثلة الوكلاء التي قد تجدها مفيدة.

:::tip
هل لديك وكيل تود مشاركته؟ [قدّم PR](https://github.com/anomalyco/opencode).
:::

---

### وكيل التوثيق

```markdown title="~/.config/opencode/agents/docs-writer.md"
---
description: Writes and maintains project documentation
mode: subagent
tools:
  shell: false
---

You are a technical writer. Create clear, comprehensive documentation.

Focus on:

- Clear explanations
- Proper structure
- Code examples
- User-friendly language
```

---

### مدقق أمني

```markdown title="~/.config/opencode/agents/security-auditor.md"
---
description: Performs security audits and identifies vulnerabilities
mode: subagent
tools:
  write: false
  edit: false
---

You are a security expert. Focus on identifying potential security issues.

Look for:

- Input validation vulnerabilities
- Authentication and authorization flaws
- Data exposure risks
- Dependency vulnerabilities
- Configuration security issues
```

---

### Packages Web Src Content Docs Ar Cli (`packages/web/src/content/docs/ar/cli.mdx`)

---
title: CLI
description: أوامر وخيارات CLI في OpenCode.
---

import { Tabs, TabItem } from "@astrojs/starlight/components"

يبدأ CLI الخاص بـ OpenCode افتراضيا واجهة [TUI](/docs/tui) عند تشغيله بدون أي معاملات.

```bash
opencode
```

كما يدعم أيضا أوامر موثقة في هذه الصفحة، ما يتيح لك التفاعل مع OpenCode برمجيا.

```bash
opencode run "Explain how closures work in JavaScript"
```

---

### tui

بدء واجهة المستخدم terminal (TUI) الخاصة بـ OpenCode.

```bash
opencode [project]
```

#### الخيارات

| الخيار                                   | المختصر | الوصف                                                             |
| ---------------------------------------- | ------- | ----------------------------------------------------------------- |
| <nobr><code>{"--continue"}</code></nobr> | `-c`    | متابعة الجلسة الأخيرة                                             |
| <nobr><code>{"--session"}</code></nobr>  | `-s`    | معرّف الجلسة للمتابعة                                             |
| <nobr><code>{"--fork"}</code></nobr>     |         | تفريع الجلسة عند المتابعة (يستخدم مع `--continue` أو `--session`) |
| <nobr><code>{"--prompt"}</code></nobr>   |         | الموجّه المراد استخدامه                                           |
| <nobr><code>{"--model"}</code></nobr>    | `-m`    | النموذج المراد استخدامه بصيغة provider/model                      |
| <nobr><code>{"--agent"}</code></nobr>    |         | الوكيل المراد استخدامه                                            |
| <nobr><code>{"--port"}</code></nobr>     |         | المنفذ الذي يتم الاستماع عليه                                     |
| <nobr><code>{"--hostname"}</code></nobr> |         | اسم المضيف الذي يتم الاستماع عليه                                 |

---

## الأوامر

يتضمن CLI الخاص بـ OpenCode أيضا الأوامر التالية.

---

### attach

إرفاق terminal بخادم الواجهة الخلفية لـ OpenCode قيد التشغيل بالفعل، والذي تم تشغيله عبر الأمرين `serve` أو `web`.

```bash
opencode attach [url]
```

يتيح ذلك استخدام واجهة TUI مع واجهة خلفية لـ OpenCode تعمل عن بعد. على سبيل المثال:

```bash
# ابدأ خادم الواجهة الخلفية للوصول عبر الويب/الجوال
opencode web --port 4096 --hostname 0.0.0.0

# في محطة طرفية (terminal) أخرى، اربط TUI بالواجهة الخلفية قيد التشغيل
opencode attach http://10.20.30.40:4096
```

#### الرايات

| الراية                                   | المختصر | الوصف                                                                             |
| ---------------------------------------- | ------- | --------------------------------------------------------------------------------- |
| <nobr><code>{"--dir"}</code></nobr>      |         | دليل العمل الذي ستبدأ منه واجهة TUI                                               |
| <nobr><code>{"--continue"}</code></nobr> | `-c`    | متابعة آخر جلسة                                                                   |
| <nobr><code>{"--session"}</code></nobr>  | `-s`    | معرّف الجلسة للمتابعة                                                             |
| <nobr><code>{"--fork"}</code></nobr>     |         | تفريع الجلسة عند المتابعة (استخدمه مع `--continue` أو `--session`)                |
| <nobr><code>{"--password"}</code></nobr> | `-p`    | كلمة مرور المصادقة الأساسية (الافتراضي `OPENCODE_SERVER_PASSWORD`)                |
| <nobr><code>{"--username"}</code></nobr> | `-u`    | اسم مستخدم المصادقة الأساسية (الافتراضي `OPENCODE_SERVER_USERNAME` أو `opencode`) |

---

### auth

أمر لإدارة بيانات الاعتماد وتسجيل الدخول لمزودي الخدمة.

```bash
opencode auth [command]
```

---

#### login

يعتمد OpenCode على قائمة المزودين في [Models.dev](https://models.dev)، لذا يمكنك استخدام `opencode auth login` لتهيئة مفاتيح API لأي مزود ترغب باستخدامه. يتم حفظ ذلك في `~/.local/share/opencode/auth.json`.

```bash
opencode auth login
```

عند تشغيل OpenCode يقوم بتحميل المزودين من ملف بيانات الاعتماد، وكذلك أي مفاتيح معرّفة في متغيرات البيئة لديك أو في ملف `.env` ضمن مشروعك.

---

#### list

يسرد جميع المزودين الذين تم توثيقهم كما هم محفوظون في ملف بيانات الاعتماد.

```bash
opencode auth list
```

أو النسخة المختصرة.

```bash
opencode auth ls
```

---

#### logout

يسجلك خارج مزود عبر حذفه من ملف بيانات الاعتماد.

```bash
opencode auth logout
```

---

### github

إدارة وكيل GitHub لأتمتة المستودع.

```bash
opencode github [command]
```

---

#### install

تثبيت وكيل GitHub في مستودعك.

```bash
opencode github install
```

يقوم ذلك بإعداد سير عمل GitHub Actions اللازم ويرشدك خلال عملية التهيئة. [اعرف المزيد](/docs/github).

---

#### run

تشغيل وكيل GitHub. يُستخدم هذا عادة ضمن GitHub Actions.

```bash
opencode github run
```

##### الرايات

| الراية                                | الوصف                                |
| ------------------------------------- | ------------------------------------ |
| <nobr><code>{"--event"}</code></nobr> | حدث GitHub مُحاكى لتشغيل الوكيل عليه |
| <nobr><code>{"--token"}</code></nobr> | رمز وصول شخصي لـ GitHub              |

---

### mcp

إدارة خوادم Model Context Protocol.

```bash
opencode mcp [command]
```

---

#### add

إضافة خادم MCP إلى تهيئتك.

```bash
opencode mcp add
```

سيرشدك هذا الأمر خلال إضافة خادم MCP محلي أو بعيد.

---

#### list

عرض جميع خوادم MCP المُهيأة وحالة اتصالها.

```bash
opencode mcp list
```

أو استخدم النسخة المختصرة.

```bash
opencode mcp ls
```

---

#### auth

إجراء المصادقة مع خادم MCP يدعم OAuth.

```bash
opencode mcp auth [name]
```

إذا لم تُحدِّد اسم خادم، فسيُطلب منك الاختيار من الخوادم المتاحة الداعمة لـ OAuth.

يمكنك أيضا عرض الخوادم الداعمة لـ OAuth وحالة المصادقة الخاصة بها.

```bash
opencode mcp auth list
```

أو استخدم النسخة المختصرة.

```bash
opencode mcp auth ls
```

---

#### logout

إزالة بيانات اعتماد OAuth لخادم MCP.

```bash
opencode mcp logout [name]
```

---

#### debug

تشخيص مشاكل اتصال OAuth لخادم MCP.

```bash
opencode mcp debug <name>
```

---

### models

عرض جميع النماذج المتاحة من المزودين المُهيأين.

```bash
opencode models [provider]
```

يعرض هذا الأمر جميع النماذج المتاحة عبر المزودين المُهيأين لديك بصيغة `provider/model`.

هذا مفيد لتحديد اسم النموذج الدقيق الذي ستستخدمه في [تهيئتك](/docs/config/).

يمكنك اختياريا تمرير معرّف مزود لتصفية النماذج حسب ذلك المزود.

```bash
opencode models anthropic
```

#### الرايات

| الراية                                  | الوصف                                                         |
| --------------------------------------- | ------------------------------------------------------------- |
| <nobr><code>{"--refresh"}</code></nobr> | تحديث ذاكرة التخزين المؤقت للنماذج من models.dev              |
| <nobr><code>{"--verbose"}</code></nobr> | استخدام مخرجات أكثر تفصيلا للنماذج (تشمل بيانات مثل التكاليف) |

استخدم الراية `--refresh` لتحديث قائمة النماذج المخزنة مؤقتا. يفيد ذلك عند إضافة نماذج جديدة إلى مزود وتريد رؤيتها في OpenCode.

```bash
opencode models --refresh
```

---

### run

تشغيل opencode في وضع غير تفاعلي عبر تمرير موجه مباشرة.

```bash
opencode run [message..]
```

هذا مفيد للبرمجة النصية والأتمتة، أو عندما تريد إجابة سريعة دون تشغيل واجهة TUI كاملة. على سبيل المثال.

```bash "opencode run"
opencode run Explain the use of context in Go
```

يمكنك أيضا الإرفاق بمثيل `opencode serve` قيد التشغيل لتجنّب زمن الإقلاع البارد لخوادم MCP في كل تشغيل:

```bash
# ابدأ خادمًا بلا واجهة في محطة طرفية واحدة
opencode serve

# في محطة طرفية أخرى، شغّل الأوامر التي ترتبط به
opencode run --attach http://localhost:4096 "Explain async/await in JavaScript"
```

#### الرايات

| الراية                                   | المختصر | الوصف                                                                             |
| ---------------------------------------- | ------- | --------------------------------------------------------------------------------- |
| <nobr><code>{"--command"}</code></nobr>  |         | الأمر المراد تشغيله؛ استخدم الرسالة كوسائط                                        |
| <nobr><code>{"--continue"}</code></nobr> | `-c`    | متابعة الجلسة الأخيرة                                                             |
| <nobr><code>{"--session"}</code></nobr>  | `-s`    | معرّف الجلسة للمتابعة                                                             |
| <nobr><code>{"--fork"}</code></nobr>     |         | تفريع الجلسة عند المتابعة (يستخدم مع `--continue` أو `--session`)                 |
| <nobr><code>{"--model"}</code></nobr>    | `-m`    | النموذج المراد استخدامه بصيغة provider/model                                      |
| <nobr><code>{"--agent"}</code></nobr>    |         | الوكيل المراد استخدامه                                                            |
| <nobr><code>{"--file"}</code></nobr>     | `-f`    | ملف/ملفات لإرفاقها بالرسالة                                                       |
| <nobr><code>{"--format"}</code></nobr>   |         | التنسيق: default (منسق) أو json (أحداث JSON خام)                                  |
| <nobr><code>{"--title"}</code></nobr>    |         | عنوان للجلسة (يستخدم موجهًا مقتطعًا إن لم تُحدَّد قيمة)                           |
| <nobr><code>{"--attach"}</code></nobr>   |         | الإرفاق بخادم opencode قيد التشغيل (مثل http://localhost:4096)                    |
| <nobr><code>{"--password"}</code></nobr> | `-p`    | كلمة مرور المصادقة الأساسية (الافتراضي `OPENCODE_SERVER_PASSWORD`)                |
| <nobr><code>{"--username"}</code></nobr> | `-u`    | اسم مستخدم المصادقة الأساسية (الافتراضي `OPENCODE_SERVER_USERNAME` أو `opencode`) |
| <nobr><code>{"--dir"}</code></nobr>      |         | دليل التشغيل، أو المسار على الخادم البعيد عند الإرفاق                             |
| <nobr><code>{"--variant"}</code></nobr>  |         | متغير النموذج (جهد الاستدلال الخاص بالمزود)                                       |
| <nobr><code>{"--thinking"}</code></nobr> |         | عرض كتل التفكير                                                                   |
| <nobr><code>{"--port"}</code></nobr>     |         | منفذ الخادم المحلي (الافتراضي منفذ عشوائي)                                        |

---

### serve

بدء خادم OpenCode بدون واجهة للوصول عبر API. راجع [توثيق الخادم](/docs/server) لواجهة HTTP الكاملة.

```bash
opencode serve
```

يشغّل هذا خادم HTTP يوفّر وصولا عبر API لوظائف opencode دون واجهة TUI. اضبط `OPENCODE_SERVER_PASSWORD` لتفعيل مصادقة HTTP الأساسية (اسم المستخدم الافتراضي `opencode`).

#### الرايات

| الراية                                   | الوصف                                     |
| ---------------------------------------- | ----------------------------------------- |
| <nobr><code>{"--port"}</code></nobr>     | المنفذ الذي يتم الاستماع عليه             |
| <nobr><code>{"--hostname"}</code></nobr> | اسم المضيف الذي يتم الاستماع عليه         |
| <nobr><code>{"--mdns"}</code></nobr>     | تفعيل اكتشاف mDNS                         |
| <nobr><code>{"--cors"}</code></nobr>     | أصول/منشأات إضافية للمتصفح للسماح بـ CORS |

---

### session

إدارة جلسات OpenCode.

```bash
opencode session [command]
```

---

#### list

عرض جميع جلسات OpenCode.

```bash
opencode session list
```

##### الرايات

| الراية                                    | المختصر | الوصف                                 |
| ----------------------------------------- | ------- | ------------------------------------- |
| <nobr><code>{"--max-count"}</code></nobr> | `-n`    | حصر النتائج في أحدث N جلسات           |
| <nobr><code>{"--format"}</code></nobr>    |         | تنسيق المخرجات: table أو json (table) |

---

### stats

عرض إحصاءات استخدام الرموز والتكلفة لجلسات OpenCode لديك.

```bash
opencode stats
```

#### الرايات

| الراية                                  | الوصف                                                                     |
| --------------------------------------- | ------------------------------------------------------------------------- |
| <nobr><code>{"--days"}</code></nobr>    | عرض الإحصاءات لآخر N يومًا (الافتراضي: كل الوقت)                          |
| <nobr><code>{"--tools"}</code></nobr>   | عدد الأدوات المطلوب عرضها (الافتراضي: الكل)                               |
| <nobr><code>{"--models"}</code></nobr>  | عرض تفصيل استخدام النماذج (مخفي افتراضيا). مرّر رقمًا لعرض أعلى N         |
| <nobr><code>{"--project"}</code></nobr> | التصفية حسب المشروع (الافتراضي: كل المشاريع، سلسلة فارغة: المشروع الحالي) |

---

### export

تصدير بيانات الجلسة بصيغة JSON.

```bash
opencode export [sessionID]
```

إذا لم تُقدّم معرّف جلسة، فسيُطلب منك الاختيار من الجلسات المتاحة.

---

### import

استيراد بيانات الجلسة من ملف JSON.

```bash
opencode import <file>
```

```bash
opencode import session.json
```

---

### web

بدء خادم OpenCode بدون واجهة مع واجهة ويب.

```bash
opencode web
```

يشغّل هذا خادم HTTP ويفتح متصفح ويب للوصول إلى OpenCode عبر واجهة ويب. اضبط `OPENCODE_SERVER_PASSWORD` لتفعيل مصادقة HTTP الأساسية (اسم المستخدم الافتراضي `opencode`).

#### الرايات

| الراية                                   | الوصف                                     |
| ---------------------------------------- | ----------------------------------------- |
| <nobr><code>{"--port"}</code></nobr>     | المنفذ الذي يتم الاستماع عليه             |
| <nobr><code>{"--hostname"}</code></nobr> | اسم المضيف الذي يتم الاستماع عليه         |
| <nobr><code>{"--mdns"}</code></nobr>     | تفعيل اكتشاف mDNS                         |
| <nobr><code>{"--cors"}</code></nobr>     | أصول/منشأات إضافية للمتصفح للسماح بـ CORS |

---

### acp

بدء خادم ACP (Agent Client Protocol).

```bash
opencode acp
```

يشغّل هذا الأمر خادم ACP يتواصل عبر stdin/stdout باستخدام nd-JSON.

#### الرايات

| الراية                                   | الوصف                             |
| ---------------------------------------- | --------------------------------- |
| <nobr><code>{"--cwd"}</code></nobr>      | دليل العمل                        |
| <nobr><code>{"--port"}</code></nobr>     | المنفذ الذي يتم الاستماع عليه     |
| <nobr><code>{"--hostname"}</code></nobr> | اسم المضيف الذي يتم الاستماع عليه |

---

### uninstall

إلغاء تثبيت OpenCode وإزالة جميع الملفات ذات الصلة.

```bash
opencode uninstall
```

#### الرايات

| الراية                                      | المختصر | الوصف                               |
| ------------------------------------------- | ------- | ----------------------------------- |
| <nobr><code>{"--keep-config"}</code></nobr> | `-c`    | الإبقاء على ملفات التهيئة           |
| <nobr><code>{"--keep-data"}</code></nobr>   | `-d`    | الإبقاء على بيانات الجلسات واللقطات |
| <nobr><code>{"--dry-run"}</code></nobr>     |         | عرض ما سيتم حذفه دون تنفيذ الحذف    |
| <nobr><code>{"--force"}</code></nobr>       | `-f`    | تخطي مطالبات التأكيد                |

---

### upgrade

تحديث opencode إلى أحدث إصدار أو إلى إصدار محدد.

```bash
opencode upgrade [target]
```

للترقية إلى أحدث إصدار.

```bash
opencode upgrade
```

للترقية إلى إصدار محدد.

```bash
opencode upgrade v0.1.48
```

#### الرايات

| الراية                                 | المختصر | الوصف                                                       |
| -------------------------------------- | ------- | ----------------------------------------------------------- |
| <nobr><code>{"--method"}</code></nobr> | `-m`    | طريقة التثبيت المستخدمة: curl أو npm أو pnpm أو bun أو brew |

---

## الخيارات العامة

يدعم سطر أوامر opencode الخيارات العامة التالية.

| الراية                                     | المختصر | الوصف                                  |
| ------------------------------------------ | ------- | -------------------------------------- |
| <nobr><code>{"--help"}</code></nobr>       | `-h`    | عرض المساعدة                           |
| <nobr><code>{"--version"}</code></nobr>    | `-v`    | طباعة رقم الإصدار                      |
| <nobr><code>{"--print-logs"}</code></nobr> |         | طباعة السجلات إلى stderr               |
| <nobr><code>{"--log-level"}</code></nobr>  |         | مستوى السجل (DEBUG, INFO, WARN, ERROR) |

---

## متغيرات البيئة

يمكن تهيئة OpenCode باستخدام متغيرات البيئة.

| المتغير                               | النوع   | الوصف                                                     |
| ------------------------------------- | ------- | --------------------------------------------------------- |
| `OPENCODE_GIT_BASH_PATH`              | string  | مسار ملف Git Bash التنفيذي على Windows                    |
| `OPENCODE_CONFIG`                     | string  | مسار ملف التهيئة                                          |
| `OPENCODE_CONFIG_DIR`                 | string  | مسار دليل التهيئة                                         |
| `OPENCODE_CONFIG_CONTENT`             | string  | محتوى تهيئة JSON مُضمّن                                   |
| `OPENCODE_DISABLE_AUTOUPDATE`         | boolean | تعطيل التحقق التلقائي من التحديثات                        |
| `OPENCODE_DISABLE_PRUNE`              | boolean | تعطيل تنقية البيانات القديمة                              |
| `OPENCODE_DISABLE_TERMINAL_TITLE`     | boolean | تعطيل تحديث عنوان terminal تلقائيا                        |
| `OPENCODE_PERMISSION`                 | string  | تهيئة أذونات JSON مُضمّنة                                 |
| `OPENCODE_DISABLE_DEFAULT_PLUGINS`    | boolean | تعطيل الإضافات الافتراضية                                 |
| `OPENCODE_DISABLE_LSP_DOWNLOAD`       | boolean | تعطيل تنزيل خوادم LSP تلقائيا                             |
| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolean | تفعيل النماذج التجريبية                                   |
| `OPENCODE_DISABLE_AUTOCOMPACT`        | boolean | تعطيل ضغط السياق تلقائيا                                  |
| `OPENCODE_DISABLE_CLAUDE_CODE`        | boolean | تعطيل القراءة من `.claude` (الموجه + المهارات)            |
| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | boolean | تعطيل قراءة `~/.claude/CLAUDE.md`                         |
| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | boolean | تعطيل تحميل `.claude/skills`                              |
| `OPENCODE_DISABLE_MODELS_FETCH`       | boolean | تعطيل جلب النماذج من مصادر بعيدة                          |
| `OPENCODE_FAKE_VCS`                   | string  | مزود VCS وهمي لأغراض الاختبار                             |
| `OPENCODE_CLIENT`                     | string  | معرّف العميل (الافتراضي `cli`)                            |
| `OPENCODE_ENABLE_EXA`                 | boolean | تفعيل أدوات بحث الويب من Exa                              |
| `OPENCODE_SERVER_PASSWORD`            | string  | تفعيل المصادقة الأساسية لخادمي `serve`/`web`              |
| `OPENCODE_SERVER_USERNAME`            | string  | تجاوز اسم مستخدم المصادقة الأساسية (الافتراضي `opencode`) |
| `OPENCODE_MODELS_URL`                 | string  | رابط مخصص لجلب تهيئة النماذج                              |

---

### تجريبي

تقوم متغيرات البيئة التالية بتفعيل ميزات تجريبية قد تتغير أو تتم إزالتها.

| المتغير                                         | النوع   | الوصف                                        |
| ----------------------------------------------- | ------- | -------------------------------------------- |
| `OPENCODE_EXPERIMENTAL`                         | boolean | تفعيل الميزات التجريبية الخاضعة للعلم الشامل |
| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY`          | boolean | تفعيل اكتشاف الأيقونات                       |
| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT`  | boolean | تعطيل النسخ عند التحديد في TUI               |
| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | number  | المهلة الافتراضية لأوامر bash بالميلي ثانية  |
| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX`        | number  | الحد الأقصى لرموز المخرجات لاستجابات LLM     |
| `OPENCODE_EXPERIMENTAL_FILEWATCHER`             | boolean | تفعيل مراقب الملفات لكامل الدليل             |
| `OPENCODE_EXPERIMENTAL_OXFMT`                   | boolean | تفعيل مُنسّق oxfmt                           |
| `OPENCODE_EXPERIMENTAL_LSP_TOOL`                | boolean | تفعيل أداة LSP تجريبية                       |
| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER`     | boolean | تعطيل مراقب الملفات                          |
| `OPENCODE_EXPERIMENTAL_EXA`                     | boolean | تفعيل ميزات Exa التجريبية                    |
| `OPENCODE_EXPERIMENTAL_LSP_TY`                  | boolean | تمكين TY LSP لملفات python                   |
| `OPENCODE_EXPERIMENTAL_PLAN_MODE`               | boolean | تفعيل وضع الخطة                              |
| `OPENCODE_EXPERIMENTAL_EVENT_SYSTEM`            | boolean | تفعيل نظام الأحداث التجريبي                  |
| `OPENCODE_EXPERIMENTAL_NATIVE_LLM`              | boolean | تفعيل مسار طلبات LLM الأصلي                  |
| `OPENCODE_EXPERIMENTAL_PARALLEL`                | boolean | تفعيل تنفيذ بحث الويب بالتوازي               |
| `OPENCODE_EXPERIMENTAL_SCOUT`                   | boolean | تفعيل Scout subagent                         |
| `OPENCODE_EXPERIMENTAL_WORKSPACES`              | boolean | تفعيل دعم مساحات العمل                       |

---

### Packages Web Src Content Docs Ar Commands (`packages/web/src/content/docs/ar/commands.mdx`)

---
title: الأوامر
description: أنشئ أوامر مخصصة للمهام المتكررة.
---

تتيح لك الأوامر المخصصة تحديد مُطالبة (prompt) تريد تشغيلها عند تنفيذ ذلك الأمر في واجهة TUI.

```bash frame="none"
/my-command
```

تُعدّ الأوامر المخصصة إضافةً إلى الأوامر المضمنة مثل `/init` و`/undo` و`/redo` و`/help`. [اعرف المزيد](/docs/tui#commands).

---

## إنشاء ملفات الأوامر

أنشئ ملفات Markdown داخل الدليل `commands/` لتعريف أوامر مخصصة.

أنشئ الملف `.opencode/commands/test.md`:

```md title=".opencode/commands/test.md"
---
description: Run tests with coverage
agent: build
model: anthropic/claude-3-5-sonnet-20241022
---

Run the full test suite with coverage report and show any failures.
Focus on the failing tests and suggest fixes.
```

تُعرِّف ترويسة Frontmatter خصائص الأمر، بينما يصبح المحتوى هو القالب.

استخدم الأمر بكتابة `/` ثم اسم الأمر.

```bash frame="none"
"/test"
```

---

## الإعداد

يمكنك إضافة أوامر مخصصة عبر إعدادات OpenCode أو بإنشاء ملفات Markdown داخل الدليل `commands/`.

---

### JSON

استخدم خيار `command` في [config](/docs/config) الخاص بـ OpenCode:

```json title="opencode.jsonc" {4-12}
{
  "$schema": "https://opencode.ai/config.json",
  "command": {
    // يصبح هذا اسم الأمر
    "test": {
      // هذه هي المطالبة التي ستُرسل إلى LLM
      "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.",
      // يظهر هذا كوصف في TUI
      "description": "Run tests with coverage",
      "agent": "build",
      "model": "anthropic/claude-3-5-sonnet-20241022"
    }
  }
}
```

يمكنك الآن تشغيل هذا الأمر في واجهة TUI:

```bash frame="none"
/test
```

---

### Markdown

يمكنك أيضًا تعريف الأوامر باستخدام ملفات Markdown. ضعها في:

- على مستوى النظام: `~/.config/opencode/commands/`
- لكل مشروع: `.opencode/commands/`

```markdown title="~/.config/opencode/commands/test.md"
---
description: Run tests with coverage
agent: build
model: anthropic/claude-3-5-sonnet-20241022
---

Run the full test suite with coverage report and show any failures.
Focus on the failing tests and suggest fixes.
```

يصبح اسم ملف Markdown هو اسم الأمر. على سبيل المثال، يتيح لك `test.md` تشغيل:

```bash frame="none"
/test
```

---

## إعداد المُطالبة

تدعم مُطالبات الأوامر المخصصة عدة عناصر نائبة (placeholders) وبنى خاصة.

---

### الوسائط

مرِّر وسائط إلى الأوامر باستخدام العنصر النائب `$ARGUMENTS`.

```md title=".opencode/commands/component.md"
---
description: Create a new component
---

Create a new React component named $ARGUMENTS with TypeScript support.
Include proper typing and basic structure.
```

شغِّل الأمر مع وسائط:

```bash frame="none"
/component Button
```

وسيُستبدل `$ARGUMENTS` بالقيمة `Button`.

يمكنك أيضًا الوصول إلى كل وسيط على حدة باستخدام المعاملات الموضعية:

- `$1` - الوسيط الأول
- `$2` - الوسيط الثاني
- `$3` - الوسيط الثالث
- وهكذا...

على سبيل المثال:

```md title=".opencode/commands/create-file.md"
---
description: Create a new file with content
---

Create a file named $1 in the directory $2
with the following content: $3
```

شغِّل الأمر:

```bash frame="none"
/create-file config.json src "{ \"key\": \"value\" }"
```

سيؤدي ذلك إلى استبدال:

- `$1` بـ `config.json`
- `$2` بـ `src`
- `$3` بـ `{ "key": "value" }`

---

### خرج shell

استخدم _!`command`_ لحقن خرج [أمر shell](/docs/tui#shell-commands) داخل مُطالبتك.

على سبيل المثال، لإنشاء أمر مخصص يُحلل تغطية الاختبارات:

```md title=".opencode/commands/analyze-coverage.md"
---
description: Analyze test coverage
---

Here are the current test results:
!`npm test`

Based on these results, suggest improvements to increase coverage.
```

أو لمراجعة التغييرات الأخيرة:

```md title=".opencode/commands/review-changes.md"
---
description: Review recent changes
---

Recent git commits:
!`git log --oneline -10`

Review these changes and suggest any improvements.
```

تُشغَّل الأوامر في دليل جذر مشروعك ويصبح خرجها جزءًا من المُطالبة.

---

### مراجع الملفات

ضمِّن الملفات في أمرك باستخدام `@` ثم اسم الملف.

```md title=".opencode/commands/review-component.md"
---
description: Review component
---

Review the component in @src/components/Button.tsx.
Check for performance issues and suggest improvements.
```

يُدرج محتوى الملف في المُطالبة تلقائيًا.

---

## الخيارات

لنلقِ نظرةً على خيارات الإعداد بالتفصيل.

---

### القالب (`template`)

يُعرِّف خيار `template` المُطالبة التي ستُرسل إلى نموذج اللغة (LLM) عند تنفيذ الأمر.

```json title="opencode.json"
{
  "command": {
    "test": {
      "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes."
    }
  }
}
```

هذا خيار إعداد **إلزامي**.

---

### الوصف (`description`)

استخدم خيار `description` لتقديم وصف موجز لما يفعله الأمر.

```json title="opencode.json"
{
  "command": {
    "test": {
      "description": "Run tests with coverage"
    }
  }
}
```

يظهر هذا الوصف في واجهة TUI عند كتابة الأمر.

---

### الوكيل (`agent`)

استخدم إعداد `agent` لتحديد أي [agent](/docs/agents) ينبغي أن ينفّذ هذا الأمر (اختياريًا).
إذا كان هذا [subagent](/docs/agents/#subagents)، فسيؤدي الأمر افتراضيًا إلى تشغيل استدعاء subagent.
لإيقاف هذا السلوك، عيِّن `subtask` إلى `false`.

```json title="opencode.json"
{
  "command": {
    "review": {
      "agent": "plan"
    }
  }
}
```

هذا خيار إعداد **اختياري**. إن لم تُحدده، فسيُستخدم agent الحالي افتراضيًا.

---

### مهمة فرعية (`subtask`)

استخدم القيمة المنطقية `subtask` لفرض أن يُشغِّل الأمر استدعاء [subagent](/docs/agents/#subagents).
يفيد هذا إذا أردت ألا يلوّث الأمر السياق الأساسي لديك، إذ سيُجبر (**force**) الـ agent على العمل كـ subagent،
حتى لو كان `mode` مضبوطًا على `primary` في إعدادات [agent](/docs/agents).

```json title="opencode.json"
{
  "command": {
    "analyze": {
      "subtask": true
    }
  }
}
```

هذا خيار إعداد **اختياري**.

---

### النموذج (`model`)

استخدم إعداد `model` لتجاوز النموذج الافتراضي لهذا الأمر.

```json title="opencode.json"
{
  "command": {
    "analyze": {
      "model": "anthropic/claude-3-5-sonnet-20241022"
    }
  }
}
```

هذا خيار إعداد **اختياري**.

---

## الأوامر المضمنة

يتضمن opencode عدة أوامر مضمنة مثل `/init` و`/undo` و`/redo` و`/help`؛ [اعرف المزيد](/docs/tui#commands).

:::note
يمكن للأوامر المخصصة تجاوز الأوامر المضمنة.
:::

إذا عرّفت أمرًا مخصصًا بالاسم نفسه، فسيستبدل الأمر المضمن.

---

### Packages Web Src Content Docs Ar Config (`packages/web/src/content/docs/ar/config.mdx`)

---
title: الإعدادات
description: استخدام ملف إعدادات OpenCode بصيغة JSON.
---

يمكنك ضبط OpenCode باستخدام ملف إعدادات بصيغة JSON.

---

## التنسيق

يدعم OpenCode تنسيقي **JSON** و**JSONC** (JSON مع تعليقات).

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  // إعدادات السمة
  "theme": "opencode",
  "model": "anthropic/claude-sonnet-4-5",
  "autoupdate": true,
}
```

---

## المواقع

يمكنك وضع ملف الإعدادات في عدة مواقع مختلفة، ولكل موقع
ترتيب أولوية مختلف.

:::note
تُدمَج ملفات الإعدادات **معًا** ولا تُستبدَل.
:::

تُدمَج ملفات الإعدادات معًا ولا تُستبدَل. يتم جمع الإعدادات من مواقع الإعدادات التالية. تتجاوز الإعدادات اللاحقة الإعدادات السابقة فقط عند تعارض المفاتيح. أما الإعدادات غير المتعارضة فتبقى محفوظة من جميع الملفات.

على سبيل المثال، إذا كان الإعداد العام يضبط `theme: "opencode"` و`autoupdate: true`، وكان إعداد المشروع يضبط `model: "anthropic/claude-sonnet-4-5"`، فستتضمن الإعدادات النهائية الخيارات الثلاثة جميعها.

---

### ترتيب الأولوية

تُحمَّل مصادر الإعدادات بهذا الترتيب (المصادر اللاحقة تتجاوز السابقة):

1. **الإعدادات البعيدة** (من `.well-known/opencode`) - الإعدادات الافتراضية على مستوى المؤسسة
2. **الإعدادات العامة** (`~/.config/opencode/opencode.json`) - تفضيلات المستخدم
3. **إعدادات مخصصة** (`OPENCODE_CONFIG` env var) - تجاوزات مخصصة
4. **إعدادات المشروع** (`opencode.json` داخل المشروع) - إعدادات خاصة بالمشروع
5. **أدلة `.opencode`** - الوكلاء، الأوامر، الإضافات
6. **إعدادات ضمنية** (`OPENCODE_CONFIG_CONTENT` env var) - تجاوزات وقت التشغيل

هذا يعني أن إعدادات المشروع يمكنها تجاوز الإعدادات العامة، وأن الإعدادات العامة يمكنها تجاوز الإعدادات الافتراضية البعيدة على مستوى المؤسسة.

:::note
يستخدم الدليلان `.opencode` و`~/.config/opencode` **أسماء جمع** للأدلة الفرعية: `agents/` و`commands/` و`modes/` و`plugins/` و`skills/` و`tools/` و`themes/`. كما تُدعَم أسماء المفرد (مثل `agent/`) للتوافق مع الإصدارات السابقة.
:::

---

### عن بُعد

يمكن للمؤسسات توفير إعدادات افتراضية عبر نقطة النهاية `.well-known/opencode`. يتم جلب ذلك تلقائيًا عندما تقوم بالمصادقة مع مزوّد يدعم هذه الميزة.

تُحمَّل الإعدادات البعيدة أولًا لتكون طبقة الأساس. ويمكن لجميع مصادر الإعدادات الأخرى (العامة، وإعدادات المشروع) تجاوز هذه القيم الافتراضية.

على سبيل المثال، إذا كانت مؤسستك توفر خوادم MCP معطّلة افتراضيًا:

```json title="Remote config from .well-known/opencode"
{
  "mcp": {
    "jira": {
      "type": "remote",
      "url": "https://jira.example.com/mcp",
      "enabled": false
    }
  }
}
```

يمكنك تفعيل خوادم محددة في إعداداتك المحلية:

```json title="opencode.json"
{
  "mcp": {
    "jira": {
      "type": "remote",
      "url": "https://jira.example.com/mcp",
      "enabled": true
    }
  }
}
```

---

### عام

ضع إعدادات OpenCode العامة في `~/.config/opencode/opencode.json`. استخدم الإعدادات العامة للتفضيلات على مستوى المستخدم مثل السمات، والمزوّدين، أو اختصارات المفاتيح.

تتجاوز الإعدادات العامة القيم الافتراضية البعيدة الخاصة بالمؤسسة.

---

### لكل مشروع

أضف `opencode.json` في جذر مشروعك. تمتلك إعدادات المشروع أعلى أولوية بين ملفات الإعدادات القياسية، إذ تتجاوز الإعدادات العامة والبعيدة معًا.

:::tip
ضع إعدادات المشروع الخاصة في جذر مشروعك.
:::

عند تشغيل OpenCode، يبحث عن ملف إعدادات في الدليل الحالي أو يصعد حتى أقرب دليل Git.

ومن الآمن أيضًا تضمينه في Git، كما يستخدم نفس المخطط الخاص بالإعدادات العامة.

---

### مسار مخصص

حدّد مسار ملف إعدادات مخصصًا باستخدام متغير البيئة `OPENCODE_CONFIG`.

```bash
export OPENCODE_CONFIG=/path/to/my/custom-config.json
opencode run "Hello world"
```

تُحمَّل الإعدادات المخصصة بين الإعدادات العامة وإعدادات المشروع ضمن ترتيب الأولوية.

---

### دليل مخصص

حدّد دليل إعدادات مخصصًا باستخدام متغير البيئة `OPENCODE_CONFIG_DIR`.
سيتم البحث داخل هذا الدليل عن الوكلاء والأوامر والأوضاع والإضافات تمامًا مثل
الدليل القياسي `.opencode`، ويجب أن يتبع نفس البنية.

```bash
export OPENCODE_CONFIG_DIR=/path/to/my/config-directory
opencode run "Hello world"
```

يُحمَّل الدليل المخصص بعد الإعدادات العامة وأدلة `.opencode`، لذلك **يمكنه تجاوز** إعداداتها.

---

## المخطط

يحتوي ملف الإعدادات على مخطط مُعرَّف في [**`opencode.ai/config.json`**](https://opencode.ai/config.json).

يفترض أن يتمكن محررك من التحقق والإكمال التلقائي اعتمادًا على هذا المخطط.

---

### TUI

يمكنك ضبط الإعدادات الخاصة بـ TUI عبر الخيار `tui`.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "tui": {
    "scroll_speed": 3,
    "scroll_acceleration": {
      "enabled": true
    },
    "diff_style": "auto"
  }
}
```

الخيارات المتاحة:

- `scroll_acceleration.enabled` - تفعيل تسارع التمرير بأسلوب macOS. **له أولوية على `scroll_speed`.**
- `scroll_speed` - مُضاعِف سرعة تمرير مخصص (الافتراضي: `3`، الحد الأدنى: `1`). يتم تجاهله إذا كان `scroll_acceleration.enabled` مساويًا لـ `true`.
- `diff_style` - التحكم في عرض `diff`. القيمة `"auto"` تتكيف مع عرض terminal، و`"stacked"` تعرض عمودًا واحدًا دائمًا.

[تعرف على المزيد حول استخدام TUI هنا](/docs/tui).

---

### الخادم

يمكنك ضبط إعدادات الخادم لأوامر `opencode serve` و`opencode web` عبر الخيار `server`.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "server": {
    "port": 4096,
    "hostname": "0.0.0.0",
    "mdns": true,
    "mdnsDomain": "myproject.local",
    "cors": ["http://localhost:5173"]
  }
}
```

الخيارات المتاحة:

- `port` - المنفذ الذي سيتم الاستماع عليه.
- `hostname` - اسم المضيف الذي سيتم الاستماع عليه. عند تفعيل `mdns` وعدم ضبط اسم مضيف، تكون القيمة الافتراضية `0.0.0.0`.
- `mdns` - تفعيل اكتشاف الخدمة عبر mDNS. يتيح ذلك للأجهزة الأخرى على الشبكة اكتشاف خادم OpenCode.
- `mdnsDomain` - اسم نطاق مخصص لخدمة mDNS. القيمة الافتراضية هي `opencode.local`. مفيد لتشغيل عدة نُسخ على نفس الشبكة.
- `cors` - أصول إضافية مسموح بها لـ CORS عند استخدام خادم HTTP من عميل يعتمد على المتصفح. يجب أن تكون القيم أصولًا كاملة (البروتوكول + المضيف + منفذ اختياري)، مثل `https://app.example.com`.

[تعرف على المزيد حول الخادم هنا](/docs/server).

---

### الأدوات

يمكنك إدارة الأدوات التي يمكن لـ LLM استخدامها عبر الخيار `tools`.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "tools": {
    "write": false,
    "shell": false
  }
}
```

[تعرف على المزيد حول الأدوات هنا](/docs/tools).

---

### النماذج

يمكنك ضبط المزوّدين والنماذج التي تريد استخدامها في إعدادات OpenCode عبر الخيارات `provider` و`model` و`small_model`.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {},
  "model": "anthropic/claude-sonnet-4-5",
  "small_model": "anthropic/claude-haiku-4-5"
}
```

يضبط الخيار `small_model` نموذجًا منفصلًا للمهام الخفيفة مثل توليد العناوين. افتراضيًا يحاول OpenCode استخدام نموذج أقل تكلفة إذا كان متاحًا لدى مزوّدك، وإلا فسيعود إلى النموذج الرئيسي.

قد تتضمن خيارات المزوّد `timeout` و`setCacheKey`:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "anthropic": {
      "options": {
        "timeout": 600000,
        "setCacheKey": true
      }
    }
  }
}
```

- `timeout` - مهلة الطلب بالميلي ثانية (الافتراضي: 300000). اضبطه إلى `false` لتعطيله.
- `setCacheKey` - يضمن تعيين مفتاح التخزين المؤقت دائمًا للمزوّد المحدد.

يمكنك أيضًا ضبط [النماذج المحلية](/docs/models#local). [تعرف على المزيد](/docs/models).

---

#### خيارات خاصة بالمزوّد

يدعم بعض المزوّدين خيارات إعداد إضافية تتجاوز الإعدادات العامة مثل `timeout` و`apiKey`.

##### Amazon Bedrock

يدعم Amazon Bedrock إعدادات خاصة بـ AWS:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "amazon-bedrock": {
      "options": {
        "region": "us-east-1",
        "profile": "my-aws-profile",
        "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com"
      }
    }
  }
}
```

- `region` - منطقة AWS لـ Bedrock (الافتراضي: متغير البيئة `AWS_REGION` أو `us-east-1`)
- `profile` - ملف تعريف AWS المُسمّى من `~/.aws/credentials` (الافتراضي: متغير البيئة `AWS_PROFILE`)
- `endpoint` - عنوان URL لنقطة نهاية مخصصة لنقاط نهاية VPC. هذا اسم بديل للخيار العام `baseURL` باستخدام مصطلحات AWS. إذا تم تحديدهما معًا، تكون أولوية `endpoint` أعلى.

:::note
لرموز Bearer (`AWS_BEARER_TOKEN_BEDROCK` أو `/connect`) أولوية أعلى من المصادقة القائمة على ملف التعريف. راجع [أولوية المصادقة](/docs/providers#authentication-precedence) للتفاصيل.
:::

[تعرف على المزيد حول إعداد Amazon Bedrock](/docs/providers#amazon-bedrock).

---

### السمات

يمكنك ضبط السمة التي تريد استخدامها في إعدادات OpenCode عبر الخيار `theme`.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "theme": ""
}
```

[تعرف على المزيد هنا](/docs/themes).

---

### الوكلاء

يمكنك ضبط وكلاء متخصصين لمهام محددة عبر الخيار `agent`.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "agent": {
    "code-reviewer": {
      "description": "Reviews code for best practices and potential issues",
      "model": "anthropic/claude-sonnet-4-5",
      "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.",
      "tools": {
        // تعطيل أدوات تعديل الملفات لوكيل المراجعة فقط
        "write": false,
        "edit": false,
      },
    },
  },
}
```

يمكنك أيضًا تعريف الوكلاء باستخدام ملفات markdown في `~/.config/opencode/agents/` أو `.opencode/agents/`. [تعرف على المزيد هنا](/docs/agents).

---

### الوكيل الافتراضي

يمكنك تعيين الوكيل الافتراضي باستخدام الخيار `default_agent`. يحدد ذلك أي وكيل سيتم استخدامه عندما لا يتم تحديد وكيل صراحةً.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "default_agent": "plan"
}
```

يجب أن يكون الوكيل الافتراضي وكيلًا أساسيًا (وليس وكيلًا فرعيًا). يمكن أن يكون وكيلًا مدمجًا مثل `"build"` أو `"plan"`، أو [وكيلًا مخصصًا](/docs/agents) قمت بتعريفه. إذا لم يكن الوكيل المحدد موجودًا أو كان وكيلًا فرعيًا، فسيعود OpenCode إلى `"build"` مع تحذير.

ينطبق هذا الإعداد على جميع الواجهات: TUI وCLI (`opencode run`) وتطبيق سطح المكتب وGitHub Action.

---

### الأوامر

يمكنك ضبط أوامر مخصصة للمهام المتكررة عبر الخيار `command`.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "command": {
    "test": {
      "template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.",
      "description": "Run tests with coverage",
      "agent": "build",
      "model": "anthropic/claude-haiku-4-5",
    },
    "component": {
      "template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.",
      "description": "Create a new component",
    },
  },
}
```

يمكنك أيضًا تعريف الأوامر باستخدام ملفات markdown في `~/.config/opencode/commands/` أو `.opencode/commands/`. [تعرف على المزيد هنا](/docs/commands).

---

### اختصارات المفاتيح

يمكنك تخصيص اختصارات المفاتيح عبر الخيار `keybinds`.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "keybinds": {}
}
```

[تعرف على المزيد هنا](/docs/keybinds).

---

### التحديث التلقائي

سيقوم OpenCode بتنزيل أي تحديثات جديدة تلقائيًا عند بدء التشغيل. يمكنك تعطيل ذلك عبر الخيار `autoupdate`.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "autoupdate": false
}
```

إذا لم تكن تريد التحديثات لكنك تريد الإشعار عند توفر نسخة جديدة، فاضبط `autoupdate` على `"notify"`.
لاحظ أن هذا يعمل فقط إذا لم يتم تثبيته عبر مدير حزم مثل Homebrew.

---

### المنسّقات

يمكنك ضبط منسّقات الشفرة عبر الخيار `formatter`.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": {
    "prettier": {
      "disabled": true
    },
    "custom-prettier": {
      "command": ["npx", "prettier", "--write", "$FILE"],
      "environment": {
        "NODE_ENV": "development"
      },
      "extensions": [".js", ".ts", ".jsx", ".tsx"]
    }
  }
}
```

[تعرف على المزيد حول المنسّقات هنا](/docs/formatters).

---

### الأذونات

افتراضيًا يسمح opencode **بجميع العمليات** دون الحاجة إلى موافقة صريحة. يمكنك تغيير ذلك عبر الخيار `permission`.

على سبيل المثال، لضمان أن أداتي `edit` و`shell` تتطلبان موافقة المستخدم:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "edit": "ask",
    "shell": "ask"
  }
}
```

[تعرف على المزيد حول الأذونات هنا](/docs/permissions).

---

### ضغط السياق

يمكنك التحكم في سلوك ضغط السياق عبر الخيار `compaction`.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "compaction": {
    "auto": true,
    "prune": false
  }
}
```

- `auto` - ضغط الجلسة تلقائيًا عند امتلاء السياق (الافتراضي: `true`).
- `prune` - إزالة مخرجات الأدوات القديمة لتوفير الرموز (tokens) (الافتراضي: `false`).
- `reserved` - مخزن مؤقت للرموز (tokens) من أجل الضغط. يترك نافذة كافية لتجنب الفيضان أثناء الضغط.

---

### المراقِب

يمكنك ضبط أنماط التجاهل لمراقِب الملفات عبر الخيار `watcher`.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "watcher": {
    "ignore": ["node_modules/**", "dist/**", ".git/**"]
  }
}
```

تتبع الأنماط صياغة `glob`. استخدم ذلك لاستبعاد الأدلة المزدحمة من مراقبة الملفات.

---

### خوادم MCP

يمكنك ضبط خوادم MCP التي تريد استخدامها عبر الخيار `mcp`.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {}
}
```

[تعرف على المزيد هنا](/docs/mcp-servers).

---

### الإضافات

[الإضافات](/docs/plugins) توسّع OpenCode بأدوات وخُطافات وتكاملات مخصصة.

ضع ملفات الإضافات في `.opencode/plugins/` أو `~/.config/opencode/plugins/`. يمكنك أيضًا تحميل إضافات من npm عبر الخيار `plugin`.

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

[تعرف على المزيد هنا](/docs/plugins).

---

### التعليمات

يمكنك ضبط التعليمات الخاصة بالنموذج الذي تستخدمه عبر الخيار `instructions`.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"]
}
```

يقبل هذا مصفوفة من المسارات وأنماط `glob` لملفات التعليمات. [تعرف على المزيد
حول القواعد هنا](/docs/rules).

---

### المزوّدون المعطّلون

يمكنك تعطيل المزوّدين الذين يتم تحميلهم تلقائيًا عبر الخيار `disabled_providers`. هذا مفيد عندما تريد منع تحميل مزوّدين معينين حتى لو كانت بيانات الاعتماد الخاصة بهم متاحة.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "disabled_providers": ["openai", "gemini"]
}
```

:::note
الخيار `disabled_providers` له أولوية على `enabled_providers`.
:::

يقبل الخيار `disabled_providers` مصفوفة من معرفات المزوّدين. عند تعطيل مزوّد:

- لن يتم تحميله حتى لو كانت متغيرات البيئة مضبوطة.
- لن يتم تحميله حتى لو كانت مفاتيح API مضبوطة عبر الأمر `/connect`.
- لن تظهر نماذج هذا المزوّد في قائمة اختيار النموذج.

---

### المزوّدون المفعّلون

يمكنك تحديد قائمة سماح للمزوّدين عبر الخيار `enabled_providers`. عند ضبطه، سيتم تفعيل المزوّدين المحددين فقط وسيتم تجاهل البقية.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "enabled_providers": ["anthropic", "openai"]
}
```

هذا مفيد عندما تريد تقييد OpenCode لاستخدام مزوّدين محددين بدلًا من تعطيلهم واحدًا تلو الآخر.

:::note
الخيار `disabled_providers` له أولوية على `enabled_providers`.
:::

إذا ظهر مزوّد ضمن كل من `enabled_providers` و`disabled_providers`، تكون أولوية `disabled_providers` أعلى للتوافق مع الإصدارات السابقة.

---

### تجريبي

يحتوي المفتاح `experimental` على خيارات قيد التطوير النشط.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "experimental": {}
}
```

:::caution
الخيارات التجريبية غير مستقرة. قد تتغير أو تُزال دون إشعار.
:::

---

## المتغيرات

يمكنك استخدام استبدال المتغيرات في ملفات الإعدادات للإشارة إلى متغيرات البيئة ومحتويات الملفات.

---

### متغيرات البيئة

استخدم `{env:VARIABLE_NAME}` لاستبدال متغيرات البيئة:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "model": "{env:OPENCODE_MODEL}",
  "provider": {
    "anthropic": {
      "models": {},
      "options": {
        "apiKey": "{env:ANTHROPIC_API_KEY}"
      }
    }
  }
}
```

إذا لم يكن متغير البيئة مضبوطًا، فسيتم استبداله بسلسلة فارغة.

---

### الملفات

استخدم `{file:path/to/file}` لاستبدال محتويات ملف:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "instructions": ["./custom-instructions.md"],
  "provider": {
    "openai": {
      "options": {
        "apiKey": "{file:~/.secrets/openai-key}"
      }
    }
  }
}
```

يمكن أن تكون مسارات الملفات:

- نسبية إلى دليل ملف الإعدادات
- أو مسارات مطلقة تبدأ بـ `/` أو `~`

يُفيد ذلك في:

- الاحتفاظ بالبيانات الحساسة مثل مفاتيح API في ملفات منفصلة.
- تضمين ملفات تعليمات كبيرة دون تشويش ملف الإعدادات.
- مشاركة مقتطفات إعدادات مشتركة عبر عدة ملفات إعدادات.

---

### Packages Web Src Content Docs Ar Custom Tools (`packages/web/src/content/docs/ar/custom-tools.mdx`)

---
title: الأدوات المخصصة
description: أنشئ أدوات يمكن لـ LLM استدعاؤها في opencode.
---

الأدوات المخصصة هي دوال تنشئها يمكن لـ LLM استدعاؤها أثناء المحادثات. تعمل جنبا إلى جنب مع [الأدوات المدمجة](/docs/tools) في opencode مثل `read` و`write` و`shell`.

---

## إنشاء أداة

تُعرّف الأدوات كملفات **TypeScript** أو **JavaScript**. لكن تعريف الأداة يمكنه استدعاء سكربتات مكتوبة **بأي لغة** — إذ تُستخدم TypeScript أو JavaScript فقط لتعريف الأداة نفسه.

---

### الموقع

يمكن تعريفها:

- محليا بوضعها في مجلد `.opencode/tools/` داخل مشروعك.
- أو عالميا بوضعها في `~/.config/opencode/tools/`.

---

### البنية

أسهل طريقة لإنشاء أدوات هي استخدام المساعد `tool()` الذي يوفر أمان الأنواع والتحقق.

```ts title=".opencode/tools/database.ts" {1}
import { tool } from "@opencode-ai/plugin"

export default tool({
  description: "Query the project database",
  args: {
    query: tool.schema.string().describe("SQL query to execute"),
  },
  async execute(args) {
    // Your database logic here
    return `Executed query: ${args.query}`
  },
})
```

يصبح **اسم الملف** هو **اسم الأداة**. المثال أعلاه ينشئ أداة باسم `database`.

---

#### عدة أدوات في ملف واحد

يمكنك أيضا تصدير عدة أدوات من ملف واحد. يصبح كل تصدير **أداة مستقلة** باسم **`<filename>_<exportname>`**:

```ts title=".opencode/tools/math.ts"
import { tool } from "@opencode-ai/plugin"

export const add = tool({
  description: "Add two numbers",
  args: {
    a: tool.schema.number().describe("First number"),
    b: tool.schema.number().describe("Second number"),
  },
  async execute(args) {
    return args.a + args.b
  },
})

export const multiply = tool({
  description: "Multiply two numbers",
  args: {
    a: tool.schema.number().describe("First number"),
    b: tool.schema.number().describe("Second number"),
  },
  async execute(args) {
    return args.a * args.b
  },
})
```

ينشئ هذا أداتين: `math_add` و`math_multiply`.

---

#### تضارب الأسماء مع الأدوات المدمجة

تُصنّف الأدوات المخصصة حسب اسم الأداة. إذا استخدمت أداة مخصصة نفس اسم أداة مدمجة، فإن الأداة المخصصة تأخذ الأولوية.

على سبيل المثال، يستبدل هذا الملف أداة `shell` المدمجة:

```ts title=".opencode/tools/shell.ts"
import { tool } from "@opencode-ai/plugin"

export default tool({
  description: "Restricted shell wrapper",
  args: {
    command: tool.schema.string(),
  },
  async execute(args) {
    return `blocked: ${args.command}`
  },
})
```

:::note
فضّل استخدام أسماء فريدة ما لم تكن تريد استبدال أداة مدمجة عمدا. إذا كنت تريد تعطيل أداة مدمجة ولكن لا تريد استبدالها، استخدم [الأذونات](/docs/permissions).
:::

---

### الوسائط

يمكنك استخدام `tool.schema`، وهو في الأساس [Zod](https://zod.dev)، لتعريف أنواع الوسائط.

```ts "tool.schema"
args: {
  query: tool.schema.string().describe("SQL query to execute")
}
```

يمكنك أيضا استيراد [Zod](https://zod.dev) مباشرة وإرجاع كائن عادي:

```ts {6}
import { z } from "zod"

export default {
  description: "Tool description",
  args: {
    param: z.string().describe("Parameter description"),
  },
  async execute(args, context) {
    // Tool implementation
    return "result"
  },
}
```

---

### السياق

تستقبل الأدوات سياقا حول الجلسة الحالية:

```ts title=".opencode/tools/project.ts" {8}
import { tool } from "@opencode-ai/plugin"

export default tool({
  description: "Get project information",
  args: {},
  async execute(args, context) {
    // Access context information
    const { agent, sessionID, messageID, directory, worktree } = context
    return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}`
  },
})
```

استخدم `context.directory` لدليل العمل الخاص بالجلسة.
استخدم `context.worktree` لجذر شجرة العمل (worktree) في git.

---

## أمثلة

### كتابة أداة بلغة Python

يمكنك كتابة أدواتك بأي لغة تريدها. إليك مثالا يجمع رقمين باستخدام Python.

أولا، أنشئ الأداة كسكربت Python:

```python title=".opencode/tools/add.py"
import sys

a = int(sys.argv[1])
b = int(sys.argv[2])
print(a + b)
```

ثم أنشئ تعريف الأداة الذي يستدعيه:

```ts title=".opencode/tools/python-add.ts" {10}
import { tool } from "@opencode-ai/plugin"
import path from "path"

export default tool({
  description: "Add two numbers using Python",
  args: {
    a: tool.schema.number().describe("First number"),
    b: tool.schema.number().describe("Second number"),
  },
  async execute(args, context) {
    const script = path.join(context.worktree, ".opencode/tools/add.py")
    const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text()
    return result.trim()
  },
})
```

هنا نستخدم أداة [`Bun.$`](https://bun.com/docs/runtime/shell) لتشغيل سكربت Python.

---

### Packages Web Src Content Docs Ar Ecosystem (`packages/web/src/content/docs/ar/ecosystem.mdx`)

---
title: النظام البيئي
description: مشاريع وتكاملات مبنية باستخدام OpenCode.
---

مجموعة من مشاريع المجتمع المبنية على OpenCode.

:::note
هل تريد إضافة مشروعك المتعلق بـ OpenCode إلى هذه القائمة؟ أرسل طلب سحب (PR).
:::

يمكنك أيضًا الاطلاع على [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) و [opencode.cafe](https://opencode.cafe)، وهو مجتمع يجمع النظام البيئي والمجتمع.

---

## الإضافات

| الاسم                                                                                              | الوصف                                                                                                          |
| -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| [opencode-daytona](https://github.com/daytonaio/daytona/tree/main/libs/opencode-plugin)            | تشغيل جلسات OpenCode تلقائيًا في صناديق حماية Daytona معزولة مع مزامنة git ومعاينات حية                        |
| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session)                  | حقن ترويسات جلسة Helicone تلقائيًا لتجميع الطلبات                                                              |
| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject)                            | حقن أنواع TypeScript/Svelte تلقائيًا في عمليات قراءة الملفات باستخدام أدوات البحث                              |
| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth)             | استخدام اشتراك ChatGPT Plus/Pro الخاص بك بدلاً من أرصدة API                                                    |
| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth)                            | استخدام خطة Gemini الحالية الخاصة بك بدلاً من فوترة API                                                        |
| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth)                | استخدام نماذج Antigravity المجانية بدلاً من فوترة API                                                          |
| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers)                         | عزل devcontainer متعدد الفروع مع نسخ shallow ومنافذ معينة تلقائيًا                                             |
| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth)   | إضافة Google Antigravity OAuth، مع دعم بحث Google، ومعالجة API أكثر قوة                                        |
| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning)  | تحسين استخدام التوكنات عن طريق تقليم مخرجات الأدوات القديمة                                                    |
| [opencode-vibeguard](https://github.com/inkdust2021/opencode-vibeguard)                            | تنقيح الأسرار/بيانات التعريف الشخصي (PII) إلى نصوص بديلة بأسلوب VibeGuard قبل استدعاءات LLM؛ واستعادتها محليًا |
| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git)                 | إضافة دعم بحث الويب الأصلي للموفرين المدعومين بأسلوب Google grounded                                           |
| [opencode-pty](https://github.com/shekohex/opencode-pty.git)                                       | تمكين وكلاء الذكاء الاصطناعي من تشغيل عمليات الخلفية في PTY، وإرسال مدخلات تفاعلية إليها.                      |
| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy)                     | تعليمات لأوامر shell غير التفاعلية - تمنع التعليق الناتج عن العمليات المعتمدة على TTY                          |
| [opencode-wakatime](https://github.com/angristan/opencode-wakatime)                                | تتبع استخدام OpenCode باستخدام Wakatime                                                                        |
| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main)    | تنظيف جداول markdown التي تنتجها LLMs                                                                          |
| [opencode-morph-plugin](https://github.com/morphllm/opencode-morph-plugin)                         | تحرير Fast Apply وبحث WarpGrep في قاعدة الكود وضغط السياق عبر Morph                                            |
| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode)                                   | وكلاء الخلفية، وأدوات LSP/AST/MCP المعدة مسبقًا، ووكلاء مختارون، متوافق مع Claude Code                         |
| [opencode-notificator](https://github.com/panta82/opencode-notificator)                            | إشعارات سطح المكتب وتنبيهات صوتية لجلسات OpenCode                                                              |
| [opencode-notifier](https://github.com/mohak34/opencode-notifier)                                  | إشعارات سطح المكتب وتنبيهات صوتية لأحداث الإذن والاكتمال والخطأ                                                |
| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer)                            | تسمية جلسات Zellij تلقائيًا بدعم الذكاء الاصطناعي بناءً على سياق OpenCode                                      |
| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful)                                | السماح لوكلاء OpenCode بتحميل المطالبات (prompts) بشكل كسول عند الطلب مع اكتشاف المهارات وحقنها                |
| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory)                      | ذاكرة مستمرة عبر الجلسات باستخدام Supermemory                                                                  |
| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | مراجعة تفاعلية للخطة مع تعليقات توضيحية مرئية ومشاركة خاصة/بدون اتصال                                          |
| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2)                              | توسيع opencode /commands إلى نظام تنسيق قوي مع تحكم دقيق في التدفق                                             |
| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler)                           | جدولة الوظائف المتكررة باستخدام launchd (Mac) أو systemd (Linux) بصيغة cron                                    |
| [micode](https://github.com/vtemian/micode)                                                        | سير عمل منظم: عصف ذهني ← تخطيط ← تنفيذ مع استمرارية الجلسة                                                     |
| [octto](https://github.com/vtemian/octto)                                                          | واجهة مستخدم تفاعلية للمتصفح للعصف الذهني بالذكاء الاصطناعي مع نماذج متعددة الأسئلة                            |
| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents)              | وكلاء خلفية بأسلوب Claude Code مع تفويض غير متزامن واستمرارية السياق                                           |
| [opencode-notify](https://github.com/kdcokenny/opencode-notify)                                    | إشعارات نظام التشغيل الأصلية لـ OpenCode – اعرف متى تكتمل المهام                                               |
| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace)                              | حزمة تنسيق متعددة الوكلاء – 16 مكونًا، تثبيت واحد                                                              |
| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree)                                | أشجار عمل git (worktrees) خالية من الاحتكاك لـ OpenCode                                                        |
| [opencode-sentry-monitor](https://github.com/stolinski/opencode-sentry-monitor)                    | تتبع وتصحيح أخطاء وكلاء الذكاء الاصطناعي باستخدام Sentry AI Monitoring                                         |

---

## المشاريع

| الاسم                                                                                      | الوصف                                                                     |
| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------- |
| [kimaki](https://kimaki.dev)                                                               | بوت Discord للتحكم في جلسات OpenCode، مبني على SDK                        |
| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim)                              | إضافة Neovim للمطالبات المدركة للمحرر، مبنية على API                      |
| [portal](https://github.com/hosenur/portal)                                                | واجهة ويب مخصصة للجوال لـ OpenCode عبر Tailscale/VPN                      |
| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/)         | قالب لبناء إضافات OpenCode                                                |
| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim)                                 | واجهة Neovim لـ opencode - وكيل برمجة بالذكاء الاصطناعي يعتمد على الطرفية |
| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | موفر Vercel AI SDK لاستخدام OpenCode عبر @opencode-ai/sdk                 |
| [OpenChamber](https://github.com/btriapitsyn/openchamber)                                  | تطبيق ويب / سطح مكتب وامتداد VS Code لـ OpenCode                          |
| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian)                           | إضافة Obsidian تدمج OpenCode في واجهة مستخدم Obsidian                     |
| [OpenWork](https://github.com/different-ai/openwork)                                       | بديل مفتوح المصدر لـ Claude Cowork، مدعوم بواسطة OpenCode                 |
| [ocx](https://github.com/kdcokenny/ocx)                                                    | مدير امتدادات OpenCode مع ملفات تعريف محمولة ومعزولة.                     |
| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad)                                   | تطبيق عميل لسطح المكتب والويب والجوال وعن بعد لـ OpenCode                 |

---

## الوكلاء

| الاسم                                                             | الوصف                                            |
| ----------------------------------------------------------------- | ------------------------------------------------ |
| [Agentic](https://github.com/Cluster444/agentic)                  | وكلاء ذكاء اصطناعي وأوامر معيارية للتطوير المنظم |
| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | تكوينات، ومطالبات، ووكلاء، وإضافات لسير عمل محسن |

---

### Packages Web Src Content Docs Ar Enterprise (`packages/web/src/content/docs/ar/enterprise.mdx`)

---
title: المؤسسات
description: استخدام OpenCode بأمان داخل مؤسستك.
---

import config from "../../../../config.mjs"
export const email = `mailto:${config.email}`

OpenCode Enterprise مخصص للمؤسسات التي تريد التأكد من أن الشيفرة والبيانات لا تغادر بنيتها التحتية مطلقا. ويمكن تحقيق ذلك عبر استخدام إعدادات مركزية تتكامل مع SSO وبوابة AI الداخلية لديك.

:::note
لا يقوم OpenCode بتخزين أي من شيفرتك أو بيانات السياق.
:::

لبدء استخدام OpenCode Enterprise:

1. أجرِ تجربة داخلية مع فريقك.
2. **<a href={email}>اتصل بنا</a>** لمناقشة التسعير وخيارات التنفيذ.

---

## تجربة

OpenCode مفتوح المصدر ولا يخزن أي من شيفرتك أو بيانات السياق، لذا يمكن للمطورين لديك ببساطة [البدء](/docs/) وإجراء تجربة.

---

### التعامل مع البيانات

**لا يقوم OpenCode بتخزين شيفرتك أو بيانات السياق.** تتم جميع المعالجة محليا أو عبر استدعاءات API مباشرة إلى مزود AI لديك.

وهذا يعني أنه طالما أنك تستخدم مزودا تثق به، أو بوابة AI داخلية، يمكنك استخدام OpenCode بأمان.

---

### ملكية الشيفرة

**أنت تملك كل الشيفرة التي ينتجها OpenCode.** لا توجد قيود ترخيص أو مطالبات بالملكية.

---

## التسعير

نستخدم نموذج تسعير لكل مقعد في OpenCode Enterprise. إذا كانت لديك بوابة LLM خاصة بك، فلن نفرض رسوما على الرموز (tokens) المستخدمة. لمزيد من التفاصيل حول التسعير وخيارات التنفيذ، **<a href={email}>اتصل بنا</a>**.

---

## النشر

بعد إكمال التجربة وعندما تكون جاهزا لاستخدام OpenCode داخل مؤسستك، يمكنك **<a href={email}>الاتصال بنا</a>** لمناقشة التسعير وخيارات التنفيذ.

---

### الإعدادات المركزية

يمكننا إعداد OpenCode لاستخدام إعدادات مركزية واحدة لكامل مؤسستك.

يمكن لهذه الإعدادات المركزية أن تتكامل مع مزود SSO لديك، وتضمن أن جميع المستخدمين يصلون فقط إلى بوابة AI الداخلية لديك.

---

### تكامل SSO

عبر الإعدادات المركزية، يمكن لـ OpenCode التكامل مع مزود SSO في مؤسستك لأغراض المصادقة.

يتيح ذلك لـ OpenCode الحصول على بيانات الاعتماد لبوابة AI الداخلية لديك عبر نظام إدارة الهوية الحالي لديك.

---

### بوابة AI الداخلية

مع الإعدادات المركزية، يمكن أيضا تهيئة OpenCode لاستخدام بوابة AI الداخلية لديك فقط.

يمكنك أيضا تعطيل جميع مزودي AI الآخرين، لضمان مرور جميع الطلبات عبر البنية التحتية المعتمدة في مؤسستك.

---

### الاستضافة الذاتية

بينما نوصي بتعطيل صفحات المشاركة لضمان ألا تغادر بياناتك مؤسستك مطلقا، يمكننا أيضا مساعدتك على استضافتها ذاتيا على بنيتك التحتية.

هذا موجود حاليا على خارطة طريقنا. إذا كنت مهتما، **<a href={email}>أخبرنا</a>**.

---

## الأسئلة الشائعة

<details>
<summary>ما هو OpenCode Enterprise؟</summary>

OpenCode Enterprise مخصص للمؤسسات التي تريد التأكد من أن الشيفرة والبيانات لا تغادر بنيتها التحتية مطلقا. ويمكن تحقيق ذلك عبر استخدام إعدادات مركزية تتكامل مع SSO وبوابة AI الداخلية لديك.

</details>

<details>
<summary>كيف أبدأ باستخدام OpenCode Enterprise؟</summary>

ابدأ ببساطة بتجربة داخلية مع فريقك. لا يقوم OpenCode افتراضيا بتخزين شيفرتك أو بيانات السياق، مما يجعل البدء سهلا.

ثم **<a href={email}>اتصل بنا</a>** لمناقشة التسعير وخيارات التنفيذ.

</details>

<details>
<summary>كيف يعمل تسعير المؤسسات؟</summary>

نقدم تسعيرا للمؤسسات لكل مقعد. إذا كانت لديك بوابة LLM خاصة بك، فلن نفرض رسوما على الرموز (tokens) المستخدمة. لمزيد من التفاصيل، **<a href={email}>اتصل بنا</a>** للحصول على عرض سعر مخصص بناء على احتياجات مؤسستك.

</details>

<details>
<summary>هل بياناتي آمنة مع OpenCode Enterprise؟</summary>

نعم. لا يقوم OpenCode بتخزين شيفرتك أو بيانات السياق. تتم جميع المعالجة محليا أو عبر استدعاءات API مباشرة إلى مزود AI لديك. ومع الإعدادات المركزية وتكامل SSO، تظل بياناتك آمنة داخل البنية التحتية لمؤسستك.

</details>

<details>
<summary>هل يمكننا استخدام سجل NPM خاص بنا؟</summary>

يدعم OpenCode سجلات npm الخاصة عبر دعم Bun الأصلي لملف `.npmrc`. إذا كانت مؤسستك تستخدم سجلا خاصا مثل JFrog Artifactory أو Nexus أو ما شابه ذلك، فتأكد من مصادقة المطورين قبل تشغيل OpenCode.

لإعداد المصادقة مع السجل الخاص بك:

```bash
npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/
```

سيؤدي ذلك إلى إنشاء `~/.npmrc` مع تفاصيل المصادقة. سيلتقط OpenCode هذا تلقائيا.

:::caution
يجب أن تكون مسجلا الدخول إلى السجل الخاص قبل تشغيل OpenCode.
:::

بدلا من ذلك، يمكنك تهيئة ملف `.npmrc` يدويا:

```bash title="~/.npmrc"
registry=https://your-company.jfrog.io/api/npm/npm-virtual/
//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN}
```

يجب أن يكون المطورون مسجلين الدخول إلى السجل الخاص قبل تشغيل OpenCode لضمان إمكانية تثبيت الحزم من سجل مؤسستك.

</details>

---

### Packages Web Src Content Docs Ar Formatters (`packages/web/src/content/docs/ar/formatters.mdx`)

---
title: المُنسِّقات
description: يستخدم OpenCode مُنسِّقات خاصة بكل لغة.
---

يُنسِّق OpenCode الملفات تلقائيا بعد كتابتها أو تعديلها باستخدام مُنسِّقات خاصة بكل لغة. يضمن ذلك أن الشيفرة التي يتم توليدها تتبع أساليب التنسيق المعتمدة في مشروعك.

---

## مُضمَّنة

يأتي OpenCode مع عدة مُنسِّقات مُضمَّنة للغات وأطر العمل الشائعة. فيما يلي قائمة بالمُنسِّقات وامتدادات الملفات المدعومة والأوامر أو خيارات الإعداد التي تحتاجها.

| المُنسِّق            | الامتدادات                                                                                               | المتطلبات                                                                               |
| -------------------- | -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| gofmt                | .go                                                                                                      | يتوفر أمر `gofmt`                                                                       |
| mix                  | .ex, .exs, .eex, .heex, .leex, .neex, .sface                                                             | يتوفر أمر `mix`                                                                         |
| prettier             | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml، و[غير ذلك](https://prettier.io/docs/en/index.html) | وجود اعتماد `prettier` في `package.json`                                                |
| biome                | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml، و[غير ذلك](https://biomejs.dev/)                   | ملف إعداد `biome.json(c)`                                                               |
| zig                  | .zig, .zon                                                                                               | يتوفر أمر `zig`                                                                         |
| clang-format         | .c, .cpp, .h, .hpp, .ino، و[غير ذلك](https://clang.llvm.org/docs/ClangFormat.html)                       | ملف إعداد `.clang-format`                                                               |
| ktlint               | .kt, .kts                                                                                                | يتوفر أمر `ktlint`                                                                      |
| ruff                 | .py, .pyi                                                                                                | يتوفر أمر `ruff` مع إعداد                                                               |
| rustfmt              | .rs                                                                                                      | يتوفر أمر `rustfmt`                                                                     |
| cargofmt             | .rs                                                                                                      | يتوفر أمر `cargo fmt`                                                                   |
| uv                   | .py, .pyi                                                                                                | يتوفر أمر `uv`                                                                          |
| rubocop              | .rb, .rake, .gemspec, .ru                                                                                | يتوفر أمر `rubocop`                                                                     |
| standardrb           | .rb, .rake, .gemspec, .ru                                                                                | يتوفر أمر `standardrb`                                                                  |
| htmlbeautifier       | .erb, .html.erb                                                                                          | يتوفر أمر `htmlbeautifier`                                                              |
| air                  | .R                                                                                                       | يتوفر أمر `air`                                                                         |
| dart                 | .dart                                                                                                    | يتوفر أمر `dart`                                                                        |
| dfmt                 | .d                                                                                                       | يتوفر أمر `dfmt`                                                                        |
| ocamlformat          | .ml, .mli                                                                                                | يتوفر أمر `ocamlformat` وملف إعداد `.ocamlformat`                                       |
| terraform            | .tf, .tfvars                                                                                             | يتوفر أمر `terraform`                                                                   |
| gleam                | .gleam                                                                                                   | يتوفر أمر `gleam`                                                                       |
| nixfmt               | .nix                                                                                                     | يتوفر أمر `nixfmt`                                                                      |
| shfmt                | .sh, .bash                                                                                               | يتوفر أمر `shfmt`                                                                       |
| pint                 | .php                                                                                                     | وجود اعتماد `laravel/pint` في `composer.json`                                           |
| oxfmt (Experimental) | .js, .jsx, .ts, .tsx                                                                                     | وجود اعتماد `oxfmt` في `package.json` و[علم متغير بيئة تجريبي](/docs/cli/#experimental) |
| ormolu               | .hs                                                                                                      | يتوفر أمر `ormolu`                                                                      |

لذا إذا كان مشروعك يتضمن `prettier` ضمن `package.json`، فسيستخدمه OpenCode تلقائيا.

---

## كيف يعمل

عندما يكتب OpenCode ملفا أو يحرره، فإنه:

1. يتحقق من امتداد الملف مقابل جميع المُنسِّقات المفعّلة.
2. يشغّل أمر المُنسِّق المناسب على الملف.
3. يطبق تغييرات التنسيق تلقائيا.

تتم هذه العملية في الخلفية لضمان الحفاظ على أساليب تنسيق الشيفرة دون أي خطوات يدوية.

---

## الإعداد

يمكنك تخصيص المُنسِّقات عبر قسم `formatter` في إعدادات OpenCode.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": {}
}
```

يدعم إعداد كل مُنسِّق ما يلي:

| الخاصية       | النوع    | الوصف                                                  |
| ------------- | -------- | ------------------------------------------------------ |
| `disabled`    | boolean  | اضبطها على `true` لتعطيل المُنسِّق                     |
| `command`     | string[] | الأمر الذي سيتم تشغيله للتنسيق                         |
| `environment` | object   | متغيرات البيئة التي يتم ضبطها عند تشغيل المُنسِّق      |
| `extensions`  | string[] | امتدادات الملفات التي يجب أن يتعامل معها هذا المُنسِّق |

لنلقِ نظرة على بعض الأمثلة.

---

### تعطيل المُنسِّقات

لتعطيل **جميع** المُنسِّقات على مستوى عام، اضبط `formatter` على `false`:

```json title="opencode.json" {3}
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": false
}
```

لتعطيل مُنسِّق **محدد**، اضبط `disabled` على `true`:

```json title="opencode.json" {5}
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": {
    "prettier": {
      "disabled": true
    }
  }
}
```

---

### مُنسِّقات مخصّصة

يمكنك تجاوز المُنسِّقات المُضمَّنة أو إضافة مُنسِّقات جديدة عبر تحديد الأمر ومتغيرات البيئة وامتدادات الملفات:

```json title="opencode.json" {4-14}
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": {
    "prettier": {
      "command": ["npx", "prettier", "--write", "$FILE"],
      "environment": {
        "NODE_ENV": "development"
      },
      "extensions": [".js", ".ts", ".jsx", ".tsx"]
    },
    "custom-markdown-formatter": {
      "command": ["deno", "fmt", "$FILE"],
      "extensions": [".md"]
    }
  }
}
```

سيتم استبدال **العنصر النائب `$FILE`** في الأمر بمسار الملف الذي يجري تنسيقه.

---

### Packages Web Src Content Docs Ar Github (`packages/web/src/content/docs/ar/github.mdx`)

---
title: GitHub
description: استخدم OpenCode في GitHub Issues وPull Requests.
---

يتكامل OpenCode مع سير عمل GitHub لديك. اذكر `/opencode` أو `/oc` في تعليقك، وسيقوم OpenCode بتنفيذ المهام داخل GitHub Actions runner لديك.

---

## الميزات

- **فرز Issues**: اطلب من OpenCode الاطلاع على Issue وشرحها لك.
- **إصلاح وتنفيذ**: اطلب من OpenCode إصلاح Issue أو تنفيذ ميزة. وسيعمل على فرع جديد ويقدّم PR يضم كل التغييرات.
- **آمن**: يعمل OpenCode داخل GitHub runners لديك.

---

## التثبيت

شغّل الأمر التالي داخل مشروع موجود في مستودع GitHub:

```bash
opencode github install
```

سيأخذك هذا خلال تثبيت GitHub app، وإنشاء workflow، وإعداد secrets.

---

### الإعداد اليدوي

أو يمكنك إعداده يدويًا.

1. **تثبيت GitHub app**

   انتقل إلى [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent). تأكد من تثبيته على المستودع الهدف.

2. **إضافة الـworkflow**

   أضف ملف الـworkflow التالي إلى `.github/workflows/opencode.yml` في مستودعك. تأكد من ضبط `model` المناسب ومفاتيح API المطلوبة ضمن `env`.

   ```yml title=".github/workflows/opencode.yml" {24,26}
   name: opencode

   on:
     issue_comment:
       types: [created]
     pull_request_review_comment:
       types: [created]

   jobs:
     opencode:
       if: |
         contains(github.event.comment.body, '/oc') ||
         contains(github.event.comment.body, '/opencode')
       runs-on: ubuntu-latest
       permissions:
         id-token: write
       steps:
          - name: Checkout repository
            uses: actions/checkout@v6
            with:
              fetch-depth: 1
              persist-credentials: false

          - name: Run OpenCode
           uses: anomalyco/opencode/github@latest
           env:
             ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
           with:
             model: anthropic/claude-sonnet-4-20250514
             # github_token: xxxx
   ```

3. **تخزين مفاتيح API ضمن secrets**

   في **settings** الخاصة بالمؤسسة أو المشروع، وسّع **Secrets and variables** في الشريط الجانبي الأيسر ثم اختر **Actions**، وأضف مفاتيح API المطلوبة.

---

## الإعدادات

- `model`: النموذج الذي سيستخدمه OpenCode. يأخذ الصيغة `provider/model`. هذا **مطلوب**.
- `agent`: الـagent الذي سيتم استخدامه. يجب أن يكون agent أساسيًا. يعود افتراضيًا إلى `default_agent` من الإعدادات أو `"build"` إذا لم يُعثر عليه.
- `prompt`: موجه مخصص اختياري لتجاوز السلوك الافتراضي. استخدمه لتخصيص كيفية معالجة OpenCode للطلبات.
- `token`: GitHub access token اختياري لتنفيذ عمليات مثل إنشاء التعليقات، وcommit للتغييرات، وفتح Pull Requests. افتراضيًا يستخدم OpenCode installation access token الخاص بـOpenCode GitHub App، لذا تظهر commits والتعليقات وPull Requests وكأنها صادرة من التطبيق.

  بدلًا من ذلك، يمكنك استخدام [`GITHUB_TOKEN` المدمج](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token) في GitHub Action runner دون تثبيت OpenCode GitHub App. فقط تأكد من منح الأذونات المطلوبة في الـworkflow:

  ```yaml
  permissions:
    id-token: write
    contents: write
    pull-requests: write
    issues: write
  ```

  يمكنك أيضًا استخدام [رموز الوصول الشخصية](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT) إن فضّلت ذلك.

---

## الأحداث المدعومة

يمكن تشغيل OpenCode عبر أحداث GitHub التالية:

| نوع الحدث                     | يتم تشغيله عبر                 | التفاصيل                                                                                                |
| ----------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------- |
| `issue_comment`               | تعليق على Issue أو PR          | اذكر `/opencode` أو `/oc` في تعليقك. يقرأ OpenCode السياق ويمكنه إنشاء فروع، وفتح PRs، أو الرد.         |
| `pull_request_review_comment` | تعليق على أسطر كود محددة في PR | اذكر `/opencode` أو `/oc` أثناء مراجعة الكود. يستلم OpenCode مسار الملف وأرقام الأسطر وسياق الـdiff.    |
| `issues`                      | فتح Issue أو تعديلها           | تشغيل OpenCode تلقائيًا عند إنشاء Issues أو تعديلها. يتطلب إدخال `prompt`.                              |
| `pull_request`                | فتح PR أو تحديثه               | تشغيل OpenCode تلقائيًا عند فتح PRs أو مزامنتها أو إعادة فتحها. مفيد للمراجعات الآلية.                  |
| `schedule`                    | جدول يعتمد على Cron            | تشغيل OpenCode وفق جدول. يتطلب إدخال `prompt`. يذهب الناتج إلى logs وPRs (لا يوجد Issue للتعليق عليها). |
| `workflow_dispatch`           | تشغيل يدوي من واجهة GitHub     | تشغيل OpenCode عند الطلب عبر Actions tab. يتطلب إدخال `prompt`. يذهب الناتج إلى logs وPRs.              |

### مثال للجدولة

شغّل OpenCode وفق جدول لتنفيذ مهام آلية:

```yaml title=".github/workflows/opencode-scheduled.yml"
name: Scheduled OpenCode Task

on:
  schedule:
    - cron: "0 9 * * 1" # Every Monday at 9am UTC

jobs:
  opencode:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: write
      pull-requests: write
      issues: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
        with:
          persist-credentials: false

      - name: Run OpenCode
        uses: anomalyco/opencode/github@latest
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        with:
          model: anthropic/claude-sonnet-4-20250514
          prompt: |
            Review the codebase for any TODO comments and create a summary.
            If you find issues worth addressing, open an issue to track them.
```

بالنسبة لأحداث `schedule`، يكون إدخال `prompt` **مطلوبًا** لعدم وجود تعليق لاستخراج التعليمات منه. تعمل عمليات الـworkflow المجدولة دون سياق مستخدم للتحقق من الأذونات، لذا يجب أن يمنح الـworkflow صلاحيات `contents: write` و`pull-requests: write` إذا كنت تتوقع أن ينشئ OpenCode فروعًا أو PRs.

---

### مثال Pull Request

راجع PRs تلقائيًا عند فتحها أو تحديثها:

```yaml title=".github/workflows/opencode-review.yml"
name: opencode-review

on:
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]

jobs:
  review:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
      pull-requests: read
      issues: read
    steps:
      - uses: actions/checkout@v6
        with:
          persist-credentials: false
      - uses: anomalyco/opencode/github@latest
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          model: anthropic/claude-sonnet-4-20250514
          use_github_token: true
          prompt: |
            Review this pull request:
            - Check for code quality issues
            - Look for potential bugs
            - Suggest improvements
```

بالنسبة لأحداث `pull_request`، إذا لم يتم توفير `prompt`، فإن OpenCode يراجع Pull Request افتراضيًا.

---

### مثال فرز Issues

قم بفرز Issues الجديدة تلقائيًا. يقوم هذا المثال بتصفية الحسابات الأقدم من 30 يومًا لتقليل الرسائل المزعجة:

```yaml title=".github/workflows/opencode-triage.yml"
name: Issue Triage

on:
  issues:
    types: [opened]

jobs:
  triage:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: write
      pull-requests: write
      issues: write
    steps:
      - name: Check account age
        id: check
        uses: actions/github-script@v7
        with:
          script: |
            const user = await github.rest.users.getByUsername({
              username: context.payload.issue.user.login
            });
            const created = new Date(user.data.created_at);
            const days = (Date.now() - created) / (1000 * 60 * 60 * 24);
            return days >= 30;
          result-encoding: string

      - uses: actions/checkout@v6
        if: steps.check.outputs.result == 'true'
        with:
          persist-credentials: false

      - uses: anomalyco/opencode/github@latest
        if: steps.check.outputs.result == 'true'
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        with:
          model: anthropic/claude-sonnet-4-20250514
          prompt: |
            Review this issue. If there's a clear fix or relevant docs:
            - Provide documentation links
            - Add error handling guidance for code examples
            Otherwise, do not comment.
```

بالنسبة لأحداث `issues`، يكون إدخال `prompt` **مطلوبًا** لعدم وجود تعليق لاستخراج التعليمات منه.

---

## الموجهات المخصصة

قم بتجاوز الموجه الافتراضي لتخصيص سلوك OpenCode ضمن الـworkflow لديك.

```yaml title=".github/workflows/opencode.yml"
- uses: anomalyco/opencode/github@latest
  with:
    model: anthropic/claude-sonnet-4-5
    prompt: |
      Review this pull request:
      - Check for code quality issues
      - Look for potential bugs
      - Suggest improvements
```

يفيد ذلك في فرض معايير مراجعة محددة، أو معايير كتابة الكود، أو مجالات تركيز تناسب مشروعك.

---

## أمثلة

إليك بعض الأمثلة على كيفية استخدام OpenCode في GitHub.

- **شرح Issue**

  أضف هذا التعليق داخل GitHub Issue.

  ```
  /opencode explain this issue
  ```

  سيقرأ OpenCode كامل النقاش، بما في ذلك جميع التعليقات، ويرد بشرح واضح.

- **إصلاح Issue**

  داخل GitHub Issue، اكتب:

  ```
  /opencode fix this
  ```

  وسيُنشئ OpenCode فرعًا جديدًا، وينفّذ التغييرات، ويفتح PR يتضمنها.

- **مراجعة PRs وإجراء تغييرات**

  اترك التعليق التالي على GitHub PR.

  ```
  Delete the attachment from S3 when the note is removed /oc
  ```

  سينفّذ OpenCode التغيير المطلوب ويعمل له commit إلى نفس PR.

- **مراجعة أسطر كود محددة**

  اترك تعليقًا مباشرة على أسطر الكود في تبويب "Files" داخل PR. يكتشف OpenCode تلقائيًا الملف وأرقام الأسطر وسياق الـdiff لتقديم ردود دقيقة.

  ```
  [Comment on specific lines in Files tab]
  /oc add error handling here
  ```

  عند التعليق على أسطر محددة، يستلم OpenCode:
  - الملف الدقيق الذي تتم مراجعته
  - أسطر الكود المحددة
  - سياق الـdiff المحيط
  - معلومات أرقام الأسطر

  يسمح ذلك بطلبات أكثر تحديدًا دون الحاجة لذكر مسارات الملفات أو أرقام الأسطر يدويًا.

---

### Packages Web Src Content Docs Ar Gitlab (`packages/web/src/content/docs/ar/gitlab.mdx`)

---
title: GitLab
description: استخدم OpenCode في مشكلات GitLab وطلبات الدمج.
---

يتكامل OpenCode مع سير عمل GitLab لديك عبر خط أنابيب GitLab CI/CD أو عبر GitLab Duo.

في كلتا الحالتين، سيعمل OpenCode على مشغّلات GitLab لديك.

---

## GitLab CI

يعمل OpenCode ضمن خط أنابيب GitLab عادي. يمكنك دمجه في الخط كمكوّن [CI](https://docs.gitlab.com/ee/ci/components/).

هنا نستخدم مكوّن CI/CD أنشأه المجتمع لـ OpenCode — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode).

---

### الميزات

- **استخدام إعدادات مخصّصة لكل مهمة**: يمكنك إعداد OpenCode باستخدام دليل إعدادات مخصّص، مثل `./config/#custom-directory`، لتفعيل الوظائف أو تعطيلها في كل تشغيل لـ OpenCode.
- **إعداد بسيط**: يقوم مكوّن CI بإعداد OpenCode في الخلفية؛ كل ما عليك هو إنشاء إعدادات OpenCode والمطالبة (prompt) الأولية.
- **مرن**: يدعم مكوّن CI عدة مُدخلات لتخصيص سلوكه.

---

### الإعداد

1. احفظ JSON مصادقة OpenCode كمتغيرات بيئة CI من نوع File ضمن **Settings** > **CI/CD** > **Variables**. تأكد من تعيينها على "Masked and hidden".
2. أضف ما يلي إلى ملف `.gitlab-ci.yml`.

   ```yaml title=".gitlab-ci.yml"
   include:
     - component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2
       inputs:
         config_dir: ${CI_PROJECT_DIR}/opencode-config
         auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON
         command: optional-custom-command
         message: "Your prompt here"
   ```

لمزيد من المُدخلات وحالات الاستخدام، [اطّلع على الوثائق](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) الخاصة بهذا المكوّن.

---

## GitLab Duo

يتكامل OpenCode مع سير عمل GitLab لديك.
اذكر `@opencode` في تعليق، وسينفّذ OpenCode المهام ضمن خط أنابيب GitLab CI لديك.

---

### الميزات

- **فرز المشكلات**: اطلب من OpenCode النظر في مشكلة وشرحها لك.
- **الإصلاح والتنفيذ**: اطلب من OpenCode إصلاح مشكلة أو تنفيذ ميزة.
  سيُنشئ فرعًا جديدًا ويرفع طلب دمج بالتغييرات.
- **آمن**: يعمل OpenCode على مشغّلات GitLab لديك.

---

### الإعداد

يعمل OpenCode ضمن خط أنابيب GitLab CI/CD لديك، وإليك ما ستحتاجه لإعداده:

:::tip
اطّلع على [**وثائق GitLab**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) للحصول على تعليمات محدّثة.
:::

1.  قم بتهيئة بيئة GitLab لديك
2.  أعد إعداد CI/CD
3.  احصل على مفتاح API من مزوّد نموذج ذكاء اصطناعي
4.  أنشئ حساب خدمة
5.  اضبط متغيرات CI/CD
6.  أنشئ ملف إعداد للتدفق، وإليك مثالًا:

        <details>

    <summary>إعدادات التدفق</summary>

    ```
/* Detailed source-code truncated for AI context efficiency. */
```

        </details>

يمكنك الرجوع إلى [وثائق GitLab CLI agents](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) للحصول على تعليمات مفصلة.

---

### أمثلة

فيما يلي بعض الأمثلة على كيفية استخدام OpenCode في GitLab.

:::tip
يمكنك ضبطه لاستخدام عبارة تشغيل مختلفة عن `@opencode`.
:::

- **شرح مشكلة**

  أضف هذا التعليق في مشكلة على GitLab.

  ```
  @opencode explain this issue
  ```

  سيقرأ OpenCode المشكلة ويرد بشرح واضح.

- **إصلاح مشكلة**

  في مشكلة على GitLab، قل:

  ```
  @opencode fix this
  ```

  سيُنشئ OpenCode فرعًا جديدًا، وينفّذ التغييرات، ويفتح طلب دمج بالتغييرات.

- **مراجعة طلبات الدمج**

  اترك التعليق التالي على طلب دمج في GitLab.

  ```
  @opencode review this merge request
  ```

  سيُراجع OpenCode طلب الدمج ويقدّم ملاحظات.

---

### Packages Web Src Content Docs Ar Ide (`packages/web/src/content/docs/ar/ide.mdx`)

---
title: IDE
description: امتداد OpenCode لـ VS Code و Cursor وغيرها من بيئات التطوير
---

يتكامل OpenCode مع VS Code و Cursor أو أي IDE يدعم terminal. ما عليك سوى تشغيل `opencode` في terminal للبدء.

---

## الاستخدام

- **تشغيل سريع**: استخدم `Cmd+Esc` (Mac) أو `Ctrl+Esc` (Windows/Linux) لفتح OpenCode في عرض terminal مقسّم، أو للتركيز على جلسة terminal موجودة إذا كانت قيد التشغيل بالفعل.
- **جلسة جديدة**: استخدم `Cmd+Shift+Esc` (Mac) أو `Ctrl+Shift+Esc` (Windows/Linux) لبدء جلسة terminal جديدة لـ OpenCode حتى لو كانت هناك جلسة مفتوحة. يمكنك أيضا النقر على زر OpenCode في واجهة المستخدم.
- **وعي بالسياق**: شارك تلقائيا تحديدك الحالي أو تبويبك مع OpenCode.
- **اختصارات الإشارة إلى الملفات**: استخدم `Cmd+Option+K` (Mac) أو `Alt+Ctrl+K` (Linux/Windows) لإدراج مراجع الملفات. مثلا: `@File#L37-42`.

---

## التثبيت

لتثبيت OpenCode على VS Code والتفرعات الشائعة مثل Cursor و Windsurf و VSCodium:

1. افتح VS Code
2. افتح terminal المدمجة
3. شغّل `opencode` - سيتم تثبيت الامتداد تلقائيا

أما إذا كنت تريد استخدام IDE الخاص بك عند تشغيل `/editor` أو `/export` من واجهة TUI، فستحتاج إلى ضبط `export EDITOR="code --wait"`. [اعرف المزيد](/docs/tui/#editor-setup).

---

### التثبيت اليدوي

ابحث عن **OpenCode** في Extension Marketplace وانقر **Install**.

---

### استكشاف الأخطاء وإصلاحها

إذا فشل تثبيت الامتداد تلقائيا:

- تأكد من أنك تشغّل `opencode` داخل terminal المدمجة.
- تأكد من تثبيت CLI الخاصة بـ IDE لديك:
  - لـ VS Code: أمر `code`
  - لـ Cursor: أمر `cursor`
  - لـ Windsurf: أمر `windsurf`
  - لـ VSCodium: أمر `codium`
  - إذا لم تكن مثبتة، شغّل `Cmd+Shift+P` (Mac) أو `Ctrl+Shift+P` (Windows/Linux) وابحث عن "Shell Command: Install 'code' command in PATH" (أو ما يعادله في IDE لديك)
- تأكد من أن VS Code لديه الصلاحية لتثبيت الامتدادات

---

### Packages Web Src Content Docs Ar Keybinds (`packages/web/src/content/docs/ar/keybinds.mdx`)

---
title: اختصارات لوحة المفاتيح
description: خصّص اختصارات لوحة المفاتيح.
---

يوفّر OpenCode قائمة باختصارات لوحة المفاتيح يمكنك تخصيصها عبر إعدادات OpenCode.

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

## مفتاح القائد

يستخدم OpenCode مفتاح `leader` لمعظم اختصارات لوحة المفاتيح. يساعد ذلك على تجنّب التعارضات في terminal لديك.

افتراضيا، يكون `ctrl+x` هو مفتاح القائد، وتتطلّب معظم الإجراءات أن تضغط أولا مفتاح القائد ثم الاختصار. على سبيل المثال، لبدء جلسة جديدة اضغط `ctrl+x` أولا ثم اضغط `n`.

لا يلزم استخدام مفتاح قائد لاختصاراتك، لكننا نوصي بذلك.

---

## تعطيل اختصار

يمكنك تعطيل أي اختصار بإضافة معرّف الاختصار إلى ملف الإعدادات بقيمة "none".

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "keybinds": {
    "session_compact": "none"
  }
}
```

---

## اختصارات موجّه سطح المكتب

يدعم حقل إدخال الموجّه في تطبيق OpenCode لسطح المكتب اختصارات شائعة لتحرير النص على نمط Readline/Emacs. هذه الاختصارات مدمجة حاليا ولا يمكن تخصيصها عبر `opencode.json`.

| الاختصار | الإجراء                                    |
| -------- | ------------------------------------------ |
| `ctrl+a` | الانتقال إلى بداية السطر الحالي            |
| `ctrl+e` | الانتقال إلى نهاية السطر الحالي            |
| `ctrl+b` | تحريك المؤشر للخلف حرفا واحدا              |
| `ctrl+f` | تحريك المؤشر للأمام حرفا واحدا             |
| `alt+b`  | تحريك المؤشر للخلف كلمة واحدة              |
| `alt+f`  | تحريك المؤشر للأمام كلمة واحدة             |
| `ctrl+d` | حذف الحرف الموجود تحت المؤشر               |
| `ctrl+k` | حذف حتى نهاية السطر                        |
| `ctrl+u` | حذف حتى بداية السطر                        |
| `ctrl+w` | حذف الكلمة السابقة                         |
| `alt+d`  | حذف الكلمة التالية                         |
| `ctrl+t` | تبديل موضعي حرفين                          |
| `ctrl+g` | إلغاء النوافذ المنبثقة / إيقاف الرد الجاري |

---

## مفتاح Shift+Enter

بعض تطبيقات terminal لا ترسل مفاتيح التعديل مع Enter افتراضيا. قد تحتاج إلى ضبط terminal لإرسال `Shift+Enter` كسلسلة هروب.

### Windows Terminal

افتح ملف `settings.json` الموجود في:

```
%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json
```

أضف هذا إلى مصفوفة `actions` على مستوى الجذر:

```json
"actions": [
  {
    "command": {
      "action": "sendInput",
      "input": "\u001b[13;2u"
    },
    "id": "User.sendInput.ShiftEnterCustom"
  }
]
```

أضف هذا إلى مصفوفة `keybindings` على مستوى الجذر:

```json
"keybindings": [
  {
    "keys": "shift+enter",
    "id": "User.sendInput.ShiftEnterCustom"
  }
]
```

احفظ الملف ثم أعد تشغيل Windows Terminal أو افتح علامة تبويب جديدة.

---

### Packages Web Src Content Docs Ar Lsp (`packages/web/src/content/docs/ar/lsp.mdx`)

---
title: خوادم LSP
description: يتكامل OpenCode مع خوادم LSP لديك.
---

يمكن أن يتكامل OpenCode مع خوادم Language Server Protocol (LSP) لاستخدام التشخيصات كملاحظات للوكيل.

---

## المدمجة

يأتي OpenCode مع عدة خوادم LSP مدمجة للغات الشائعة:

| خادم LSP           | الامتدادات                                                          | المتطلبات                                            |
| ------------------ | ------------------------------------------------------------------- | ---------------------------------------------------- |
| astro              | .astro                                                              | يثبت تلقائيا لمشاريع Astro                           |
| bash               | .sh, .bash, .zsh, .ksh                                              | يثبت `bash-language-server` تلقائيا                  |
| clangd             | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++                | يثبت تلقائيا لمشاريع C/C++                           |
| csharp             | .cs                                                                 | تثبيت `.NET SDK`                                     |
| clojure-lsp        | .clj, .cljs, .cljc, .edn                                            | توفر أمر `clojure-lsp`                               |
| dart               | .dart                                                               | توفر أمر `dart`                                      |
| deno               | .ts, .tsx, .js, .jsx, .mjs                                          | توفر أمر `deno` (يكتشف تلقائيا deno.json/deno.jsonc) |
| elixir-ls          | .ex, .exs                                                           | توفر أمر `elixir`                                    |
| eslint             | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue                  | وجود تبعية `eslint` في المشروع                       |
| fsharp             | .fs, .fsi, .fsx, .fsscript                                          | تثبيت `.NET SDK`                                     |
| gleam              | .gleam                                                              | توفر أمر `gleam`                                     |
| gopls              | .go                                                                 | توفر أمر `go`                                        |
| hls                | .hs, .lhs                                                           | توفر أمر `haskell-language-server-wrapper`           |
| jdtls              | .java                                                               | تثبيت `Java SDK (version 21+)`                       |
| kotlin-ls          | .kt, .kts                                                           | يثبت تلقائيا لمشاريع Kotlin                          |
| lua-ls             | .lua                                                                | يثبت تلقائيا لمشاريع Lua                             |
| nixd               | .nix                                                                | توفر أمر `nixd`                                      |
| ocaml-lsp          | .ml, .mli                                                           | توفر أمر `ocamllsp`                                  |
| oxlint             | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | وجود تبعية `oxlint` في المشروع                       |
| php intelephense   | .php                                                                | يثبت تلقائيا لمشاريع PHP                             |
| prisma             | .prisma                                                             | توفر أمر `prisma`                                    |
| pyright            | .py, .pyi                                                           | تثبيت تبعية `pyright`                                |
| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru                                           | توفر أمري `ruby` و `gem`                             |
| rust               | .rs                                                                 | توفر أمر `rust-analyzer`                             |
| sourcekit-lsp      | .swift, .objc, .objcpp                                              | تثبيت `swift` (على macOS عبر `xcode`)                |
| svelte             | .svelte                                                             | يثبت تلقائيا لمشاريع Svelte                          |
| terraform          | .tf, .tfvars                                                        | يثبت تلقائيا من إصدارات GitHub                       |
| tinymist           | .typ, .typc                                                         | يثبت تلقائيا من إصدارات GitHub                       |
| typescript         | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts                        | وجود تبعية `typescript` في المشروع                   |
| vue                | .vue                                                                | يثبت تلقائيا لمشاريع Vue                             |
| yaml-ls            | .yaml, .yml                                                         | يثبت `yaml-language-server` من Red Hat تلقائيا       |
| zls                | .zig, .zon                                                          | توفر أمر `zig`                                       |

تكون ميزة LSP معطلة افتراضيا. عند تفعيلها، تبدأ الخوادم عند اكتشاف أحد امتدادات الملفات المذكورة أعلاه واستيفاء المتطلبات.

:::note
يمكنك تعطيل تنزيلات خوادم LSP التلقائية عبر ضبط متغير البيئة `OPENCODE_DISABLE_LSP_DOWNLOAD` على `true`.
:::

---

## كيف يعمل

عند تفعيل LSP وفتح opencode لملف، فإنه:

1. يفحص امتداد الملف مقابل جميع خوادم LSP المفعّلة.
2. يشغّل خادم LSP المناسب إذا لم يكن قيد التشغيل بالفعل.

---

## أفضل الممارسات

يمكن أن تساعد LSP الوكيل على العثور على المشاكل وإصلاحها عبر توفير التشخيصات من خوادم اللغة. هذا مفيد في بعض المشاريع، لكنه ليس دائما مكسبا صافيا.

قد تخرج خوادم اللغة عن المزامنة، وتستهلك ذاكرة كبيرة، وتختلف حسب الإصدار أو المشروع، وتبطئ سير عمل الوكيل. في كثير من المشاريع، يكون من الأفضل أن يشغّل الوكيل lint أو typecheck أو أدوات CLI التشخيصية الأخرى مباشرة، بحيث تعود الأخطاء إلى حلقة الوكيل دون هذه المفاضلات. وثّق هذه الأوامر في ملفات التعليمات مثل `AGENTS.md` أو المهارات حتى يعرف الوكيل ما يجب تشغيله. فعّل LSP عندما يستفيد مشروعك من ملاحظات إضافية من خادم اللغة.

---

## الإعداد

يمكنك تفعيل خوادم LSP وتخصيصها عبر قسم `lsp` في إعدادات opencode.

لتفعيل جميع خوادم LSP المدمجة، اضبط `lsp` على `true`.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "lsp": true
}
```

استخدم كائنا لإبقاء الخوادم المدمجة مفعلة أثناء إعداد التجاوزات أو الخوادم المخصصة.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "lsp": {}
}
```

يدعم كل خادم LSP ما يلي:

| الخاصية          | النوع    | الوصف                                             |
| ---------------- | -------- | ------------------------------------------------- |
| `disabled`       | boolean  | اضبطها على `true` لتعطيل خادم LSP                 |
| `command`        | string[] | الأمر المستخدم لتشغيل خادم LSP                    |
| `extensions`     | string[] | امتدادات الملفات التي يجب أن يعالجها خادم LSP هذا |
| `env`            | object   | متغيرات البيئة التي تُضبط عند تشغيل الخادم        |
| `initialization` | object   | خيارات التهيئة التي تُرسل إلى خادم LSP            |

لنلق نظرة على بعض الأمثلة.

---

### متغيرات البيئة

استخدم الخاصية `env` لضبط متغيرات البيئة عند تشغيل خادم LSP:

```json title="opencode.json" {5-7}
{
  "$schema": "https://opencode.ai/config.json",
  "lsp": {
    "rust": {
      "env": {
        "RUST_LOG": "debug"
      }
    }
  }
}
```

---

### خيارات التهيئة

استخدم الخاصية `initialization` لتمرير خيارات التهيئة إلى خادم LSP. هذه إعدادات خاصة بالخادم تُرسل أثناء طلب LSP `initialize`:

```json title="opencode.json" {5-9}
{
  "$schema": "https://opencode.ai/config.json",
  "lsp": {
    "typescript": {
      "initialization": {
        "preferences": {
          "importModuleSpecifierPreference": "relative"
        }
      }
    }
  }
}
```

:::note
تختلف خيارات التهيئة بحسب خادم LSP. راجع توثيق خادم LSP لديك لمعرفة الخيارات المتاحة.
:::

---

### تعطيل خوادم LSP

إذا تم حذف `lsp`، فستكون جميع خوادم LSP معطلة. لتعطيل جميع خوادم LSP بعد أن فعّلها إعداد آخر، اضبط `lsp` على `false`:

```json title="opencode.json" {3}
{
  "$schema": "https://opencode.ai/config.json",
  "lsp": false
}
```

لتعطيل خادم LSP **بعينه**، اضبط `disabled` على `true`:

```json title="opencode.json" {5}
{
  "$schema": "https://opencode.ai/config.json",
  "lsp": {
    "typescript": {
      "disabled": true
    }
  }
}
```

---

### خوادم LSP مخصصة

يمكنك إضافة خوادم LSP مخصصة عبر تحديد الأمر وامتدادات الملفات:

```json title="opencode.json" {4-7}
{
  "$schema": "https://opencode.ai/config.json",
  "lsp": {
    "custom-lsp": {
      "command": ["custom-lsp-server", "--stdio"],
      "extensions": [".custom"]
    }
  }
}
```

---

## معلومات إضافية

### PHP Intelephense

يوفر PHP Intelephense ميزات مدفوعة عبر مفتاح ترخيص. يمكنك تزويده بمفتاح الترخيص عبر وضع (فقط) المفتاح داخل ملف نصي في:

- على macOS/Linux: `$HOME/intelephense/license.txt`
- على Windows: `%USERPROFILE%/intelephense/license.txt`

يجب أن يحتوي الملف على مفتاح الترخيص فقط دون أي محتوى إضافي.

---

### Packages Web Src Content Docs Ar Mcp Servers (`packages/web/src/content/docs/ar/mcp-servers.mdx`)

---
title: خوادم MCP
description: أضف أدوات MCP محلية وبعيدة.
---

يمكنك إضافة أدوات خارجية إلى OpenCode باستخدام _Model Context Protocol_، أو MCP. يدعم OpenCode خوادم محلية وبعيدة.

بعد إضافتها، تصبح أدوات MCP متاحة تلقائيا للـ LLM إلى جانب الأدوات المضمنة.

---

#### تنبيهات

عند استخدام خادم MCP فإنه يضيف إلى السياق. وقد يتراكم ذلك بسرعة إذا كان لديك الكثير من الأدوات. لذلك نوصي بالتحلّي بالحذر عند اختيار خوادم MCP التي تستخدمها.

:::tip
تضيف خوادم MCP إلى سياقك، لذا احرص على اختيار ما تفعّله منها بعناية.
:::

تميل بعض خوادم MCP، مثل خادم GitHub MCP، إلى إضافة الكثير من الرموز (tokens) وقد تتجاوز حد السياق بسهولة.

---

## التمكين

يمكنك تعريف خوادم MCP في [إعدادات OpenCode](https://opencode.ai/docs/config/) ضمن `mcp`. أضف كل خادم MCP باسم فريد. ويمكنك الإشارة إلى ذلك الخادم بالاسم عند توجيه الطلب إلى الـ LLM.

```jsonc title="opencode.jsonc" {6}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "name-of-mcp-server": {
      // ...
      "enabled": true,
    },
    "name-of-other-mcp-server": {
      // ...
    },
  },
}
```

يمكنك أيضا تعطيل خادم عبر ضبط `enabled` على `false`. يفيد ذلك إذا أردت تعطيله مؤقتا دون إزالته من إعداداتك.

---

### تجاوز القيم الافتراضية البعيدة

يمكن للمنظمات توفير خوادم MCP الافتراضية عبر نقطة النهاية `.well-known/opencode` الخاصة بها. قد تكون هذه الخوادم معطّلة افتراضيا، مما يتيح للمستخدمين تفعيل ما يحتاجونه فقط.

لتفعيل خادم معيّن من الإعدادات البعيدة الخاصة بمؤسستك، أضفه إلى إعداداتك المحلية مع `enabled: true`:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "jira": {
      "type": "remote",
      "url": "https://jira.example.com/mcp",
      "enabled": true
    }
  }
}
```

تتغلب قيم إعداداتك المحلية على القيم الافتراضية البعيدة. راجع [أولوية الإعدادات](/docs/config#precedence-order) لمزيد من التفاصيل.

---

## محلي

أضف خوادم MCP المحلية عبر ضبط `type` على `"local"` ضمن كائن `mcp`.

```jsonc title="opencode.jsonc" {15}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "my-local-mcp-server": {
      "type": "local",
      // Or ["bun", "x", "my-mcp-command"]
      "command": ["npx", "-y", "my-mcp-command"],
      "enabled": true,
      "environment": {
        "MY_ENV_VAR": "my_env_var_value",
      },
    },
  },
}
```

الأمر `command` هو الطريقة التي يتم بها تشغيل خادم MCP المحلي. ويمكنك أيضا تمرير قائمة بمتغيرات البيئة.

على سبيل المثال، إليك كيفية إضافة خادم MCP التجريبي [`@modelcontextprotocol/server-everything`](https://www.npmjs.com/package/@modelcontextprotocol/server-everything).

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "mcp_everything": {
      "type": "local",
      "command": ["npx", "-y", "@modelcontextprotocol/server-everything"],
    },
  },
}
```

ولاستخدامه يمكنني إضافة `use the mcp_everything tool` إلى طلباتي.

```txt "mcp_everything"
use the mcp_everything tool to add the number 3 and 4
```

---

#### الخيارات

فيما يلي جميع الخيارات المتاحة لتهيئة خادم MCP محلي.

| الخيار        | النوع   | مطلوب | الوصف                                                                            |
| ------------- | ------- | ----- | -------------------------------------------------------------------------------- |
| `type`        | String  | Y     | نوع اتصال خادم MCP، ويجب أن يكون `"local"`.                                      |
| `command`     | Array   | Y     | الأمر والوسائط اللازمة لتشغيل خادم MCP.                                          |
| `environment` | Object  |       | متغيرات البيئة التي يتم تعيينها عند تشغيل الخادم.                                |
| `enabled`     | Boolean |       | تفعيل خادم MCP أو تعطيله عند بدء التشغيل.                                        |
| `timeout`     | Number  |       | المهلة بالمللي ثانية لجلب الأدوات من خادم MCP. القيمة الافتراضية 5000 (5 ثوانٍ). |

---

## بعيد

أضف خوادم MCP البعيدة عبر ضبط `type` على `"remote"`.

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "my-remote-mcp": {
      "type": "remote",
      "url": "https://my-mcp-server.com",
      "enabled": true,
      "headers": {
        "Authorization": "Bearer MY_API_KEY"
      }
    }
  }
}
```

يمثل `url` عنوان URL لخادم MCP البعيد، وباستخدام خيار `headers` يمكنك تمرير قائمة من الرؤوس (headers).

---

#### الخيارات

| الخيار    | النوع   | مطلوب | الوصف                                                                            |
| --------- | ------- | ----- | -------------------------------------------------------------------------------- |
| `type`    | String  | Y     | نوع اتصال خادم MCP، ويجب أن يكون `"remote"`.                                     |
| `url`     | String  | Y     | عنوان URL لخادم MCP البعيد.                                                      |
| `enabled` | Boolean |       | تفعيل خادم MCP أو تعطيله عند بدء التشغيل.                                        |
| `headers` | Object  |       | الرؤوس التي يتم إرسالها مع الطلب.                                                |
| `oauth`   | Object  |       | إعدادات مصادقة OAuth. راجع قسم [OAuth](#oauth) أدناه.                            |
| `timeout` | Number  |       | المهلة بالمللي ثانية لجلب الأدوات من خادم MCP. القيمة الافتراضية 5000 (5 ثوانٍ). |

---

## OAuth

يتولى OpenCode تلقائيا معالجة مصادقة OAuth لخوادم MCP البعيدة. عندما يتطلب خادم ما المصادقة، سيقوم OpenCode بما يلي:

1. اكتشاف استجابة 401 وبدء تدفق OAuth
2. استخدام **Dynamic Client Registration (RFC 7591)** إذا كان الخادم يدعمه
3. تخزين الرموز (tokens) بشكل آمن للطلبات المستقبلية

---

### تلقائي

بالنسبة لمعظم خوادم MCP التي تدعم OAuth، لا تحتاج إلى إعدادات خاصة. ما عليك سوى تهيئة الخادم البعيد:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "my-oauth-server": {
      "type": "remote",
      "url": "https://mcp.example.com/mcp"
    }
  }
}
```

إذا كان الخادم يتطلب المصادقة، فسيطلب منك OpenCode المصادقة عند أول محاولة لاستخدامه. وإذا لم يحدث ذلك، يمكنك [تشغيل التدفق يدويا](#authenticating) باستخدام `opencode mcp auth <server-name>`.

---

### مُسجَّل مسبقا

إذا كانت لديك بيانات اعتماد العميل من موفّر خادم MCP، يمكنك تهيئتها:

```json title="opencode.json" {7-11}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "my-oauth-server": {
      "type": "remote",
      "url": "https://mcp.example.com/mcp",
      "oauth": {
        "clientId": "{env:MY_MCP_CLIENT_ID}",
        "clientSecret": "{env:MY_MCP_CLIENT_SECRET}",
        "scope": "tools:read tools:execute"
      }
    }
  }
}
```

---

### المصادقة

يمكنك تشغيل المصادقة يدويا أو إدارة بيانات الاعتماد.

صادِق مع خادم MCP معيّن:

```bash
opencode mcp auth my-oauth-server
```

اعرض جميع خوادم MCP وحالة المصادقة الخاصة بها:

```bash
opencode mcp list
```

احذف بيانات الاعتماد المخزنة:

```bash
opencode mcp logout my-oauth-server
```

سيفتح أمر `mcp auth` متصفحك للتفويض. بعد إكمال التفويض، سيخزّن OpenCode الرموز بشكل آمن في `~/.local/share/opencode/mcp-auth.json`.

---

#### تعطيل OAuth

إذا أردت تعطيل OAuth التلقائي لخادم ما (على سبيل المثال، للخوادم التي تستخدم مفاتيح API بدلا من ذلك)، فاضبط `oauth` على `false`:

```json title="opencode.json" {7}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "my-api-key-server": {
      "type": "remote",
      "url": "https://mcp.example.com/mcp",
      "oauth": false,
      "headers": {
        "Authorization": "Bearer {env:MY_API_KEY}"
      }
    }
  }
}
```

---

#### خيارات OAuth

| الخيار         | النوع           | الوصف                                                                    |
| -------------- | --------------- | ------------------------------------------------------------------------ |
| `oauth`        | Object \| false | كائن إعدادات OAuth، أو `false` لتعطيل الاكتشاف التلقائي لـ OAuth.        |
| `clientId`     | String          | معرّف عميل OAuth. إذا لم يُحدَّد، ستتم محاولة التسجيل الديناميكي للعميل. |
| `clientSecret` | String          | سرّ عميل OAuth، إذا كان مطلوبا من خادم التفويض.                          |
| `scope`        | String          | نطاقات OAuth المطلوبة أثناء التفويض.                                     |

#### تصحيح الأخطاء

إذا فشل خادم MCP بعيد في المصادقة، يمكنك تشخيص المشكلة باستخدام:

```bash
# عرض حالة المصادقة لجميع الخوادم القادرة على OAuth
opencode mcp auth list

# تصحيح الاتصال وتدفق OAuth لخادم محدد
opencode mcp debug my-oauth-server
```

يعرض أمر `mcp debug` حالة المصادقة الحالية، ويختبر اتصال HTTP، ويحاول تنفيذ تدفق اكتشاف OAuth.

---

## الإدارة

تتوفر خوادم MCP لديك كأدوات داخل OpenCode إلى جانب الأدوات المضمنة. لذا يمكنك إدارتها عبر إعدادات OpenCode مثل أي أداة أخرى.

---

### عام

هذا يعني أنه يمكنك تفعيلها أو تعطيلها على مستوى عام.

```json title="opencode.json" {14}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "my-mcp-foo": {
      "type": "local",
      "command": ["bun", "x", "my-mcp-command-foo"]
    },
    "my-mcp-bar": {
      "type": "local",
      "command": ["bun", "x", "my-mcp-command-bar"]
    }
  },
  "tools": {
    "my-mcp-foo": false
  }
}
```

يمكننا أيضا استخدام نمط glob لتعطيل جميع خوادم MCP المطابقة.

```json title="opencode.json" {14}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "my-mcp-foo": {
      "type": "local",
      "command": ["bun", "x", "my-mcp-command-foo"]
    },
    "my-mcp-bar": {
      "type": "local",
      "command": ["bun", "x", "my-mcp-command-bar"]
    }
  },
  "tools": {
    "my-mcp*": false
  }
}
```

هنا نستخدم نمط glob `my-mcp*` لتعطيل جميع خوادم MCP.

---

### لكل وكيل

إذا كان لديك عدد كبير من خوادم MCP فقد ترغب في تفعيلها لكل وكيل على حدة وتعطيلها على المستوى العام. للقيام بذلك:

1. عطّلها كأداة على المستوى العام.
2. في [إعدادات الوكيل](/docs/agents#tools)، فعّل خادم MCP كأداة.

```json title="opencode.json" {11, 14-18}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "my-mcp": {
      "type": "local",
      "command": ["bun", "x", "my-mcp-command"],
      "enabled": true
    }
  },
  "tools": {
    "my-mcp*": false
  },
  "agent": {
    "my-agent": {
      "tools": {
        "my-mcp*": true
      }
    }
  }
}
```

---

#### أنماط Glob

يستخدم نمط glob أنماطا بسيطة من مطابقة glob:

- `*` يطابق صفرا أو أكثر من أي محرف (على سبيل المثال، `"my-mcp*"` يطابق `my-mcp_search` و`my-mcp_list` وغيرها.)
- `?` يطابق محرفا واحدا بالضبط
- جميع المحارف الأخرى تُطابق حرفيا

:::note
تُسجَّل أدوات خادم MCP مع اسم الخادم كبادئة، لذا لتعطيل جميع أدوات خادم ما استخدم ببساطة:

```
"mymcpservername_*": false
```

:::

---

## أمثلة

فيما يلي أمثلة لبعض خوادم MCP الشائعة. يمكنك إرسال PR إذا أردت توثيق خوادم أخرى.

---

### Sentry

أضف [خادم MCP الخاص بـ Sentry](https://mcp.sentry.dev) للتفاعل مع مشاريع Sentry والقضايا (issues) الخاصة بك.

```json title="opencode.json" {4-8}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "sentry": {
      "type": "remote",
      "url": "https://mcp.sentry.dev/mcp",
      "oauth": {}
    }
  }
}
```

بعد إضافة الإعدادات، قم بالمصادقة مع Sentry:

```bash
opencode mcp auth sentry
```

سيؤدي ذلك إلى فتح نافذة متصفح لإكمال تدفق OAuth وربط OpenCode بحساب Sentry الخاص بك.

بعد المصادقة، يمكنك استخدام أدوات Sentry في طلباتك للاستعلام عن القضايا والمشاريع وبيانات الأخطاء.

```txt "use sentry"
Show me the latest unresolved issues in my project. use sentry
```

---

### Context7

أضف [خادم MCP الخاص بـ Context7](https://github.com/upstash/context7) للبحث في المستندات.

```json title="opencode.json" {4-7}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "context7": {
      "type": "remote",
      "url": "https://mcp.context7.com/mcp"
    }
  }
}
```

إذا كنت قد سجلت للحصول على حساب مجاني، يمكنك استخدام مفتاح API للحصول على حدود أعلى لمعدل الطلبات.

```json title="opencode.json" {7-9}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "context7": {
      "type": "remote",
      "url": "https://mcp.context7.com/mcp",
      "headers": {
        "CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}"
      }
    }
  }
}
```

هنا نفترض أنك عيّنت متغير البيئة `CONTEXT7_API_KEY`.

أضف `use context7` إلى طلباتك لاستخدام خادم MCP الخاص بـ Context7.

```txt "use context7"
Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7
```

بدلا من ذلك، يمكنك إضافة شيء مثل هذا إلى [AGENTS.md](/docs/rules/).

```md title="AGENTS.md"
When you need to search docs, use `context7` tools.
```

---

### Grep by Vercel

أضف خادم MCP الخاص بـ [Grep by Vercel](https://grep.app) للبحث في مقتطفات الشيفرة على GitHub.

```json title="opencode.json" {4-7}
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "gh_grep": {
      "type": "remote",
      "url": "https://mcp.grep.app"
    }
  }
}
```

وبما أننا سمّينا خادم MCP الخاص بنا `gh_grep`، يمكنك إضافة `use the gh_grep tool` إلى طلباتك لجعل الوكيل يستخدمه.

```txt "use the gh_grep tool"
What's the right way to set a custom domain in an SST Astro component? use the gh_grep tool
```

بدلا من ذلك، يمكنك إضافة شيء مثل هذا إلى [AGENTS.md](/docs/rules/).

```md title="AGENTS.md"
If you are unsure how to do something, use `gh_grep` to search code examples from GitHub.
```

---

### Packages Web Src Content Docs Ar Models (`packages/web/src/content/docs/ar/models.mdx`)

---
title: النماذج
description: تهيئة مزوّد LLM والنموذج.
---

يستخدم OpenCode كلاً من [AI SDK](https://ai-sdk.dev/) و[Models.dev](https://models.dev) لدعم **أكثر من 75 مزوّداً لنماذج LLM**، كما يدعم تشغيل النماذج محلياً.

---

## المزوّدون

أكثر المزوّدين شيوعاً مُحمَّلون مسبقاً افتراضياً. إذا أضفت بيانات اعتماد أحد المزوّدين عبر الأمر `/connect` فستكون متاحة عند تشغيل OpenCode.

تعرّف على المزيد حول [المزوّدين](/docs/providers).

---

## اختر نموذجاً

بعد تهيئة المزوّد يمكنك اختيار النموذج الذي تريده بكتابة:

```bash frame="none"
/models
```

---

## النماذج الموصى بها

هناك الكثير من النماذج المتاحة، وتظهر نماذج جديدة كل أسبوع.

:::tip
ننصح باستخدام أحد النماذج التي نوصي بها.
:::

لكن القليل منها فقط يكون جيداً في كلٍ من توليد الشيفرة واستدعاء الأدوات.

فيما يلي عدة نماذج تعمل جيداً مع OpenCode، دون ترتيب معيّن. (هذه ليست قائمة شاملة وقد لا تكون محدَّثة دائماً):

- GPT 5.2
- GPT 5.1 Codex
- Claude Opus 4.5
- Claude Sonnet 4.5
- Minimax M2.1
- Gemini 3 Pro

---

## تعيين الافتراضي

لتعيين أحد هذه النماذج كنموذج افتراضي، يمكنك ضبط المفتاح `model` في ملف إعدادات OpenCode.

```json title="opencode.json" {3}
{
  "$schema": "https://opencode.ai/config.json",
  "model": "lmstudio/google/gemma-3n-e4b"
}
```

المعرّف الكامل هنا يكون بالشكل `provider_id/model_id`. على سبيل المثال، إذا كنت تستخدم [OpenCode Zen](https://opencode.ai/v2/docs/console/) فستستخدم `opencode/gpt-5.1-codex` لنموذج GPT 5.1 Codex.

إذا كنت قد هيّأت [مزوّداً مخصّصاً](/docs/providers#custom)، فإن `provider_id` هو المفتاح الموجود ضمن قسم `provider` في إعداداتك، و`model_id` هو المفتاح الموجود ضمن `provider.models`.

---

## إعداد النماذج

يمكنك ضبط خيارات النموذج على مستوى عام عبر ملف الإعدادات.

```jsonc title="opencode.jsonc" {7-12,19-24}
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "openai": {
      "models": {
        "gpt-5": {
          "options": {
            "reasoningEffort": "high",
            "textVerbosity": "low",
            "reasoningSummary": "auto",
            "include": ["reasoning.encrypted_content"],
          },
        },
      },
    },
    "anthropic": {
      "models": {
        "claude-sonnet-4-5-20250929": {
          "options": {
            "thinking": {
              "type": "enabled",
              "budgetTokens": 16000,
            },
          },
        },
      },
    },
  },
}
```

هنا نقوم بضبط إعدادات عامة لنموذجين مدمجين: `gpt-5` عند الوصول إليه عبر مزوّد `openai`، و`claude-sonnet-4-20250514` عند الوصول إليه عبر مزوّد `anthropic`.
يمكن العثور على أسماء المزوّدين والنماذج المدمجة على [Models.dev](https://models.dev).

يمكنك أيضاً ضبط هذه الخيارات لأي وكلاء تستخدمهم. تتجاوز إعدادات الوكيل أي خيارات عامة هنا. [اعرف المزيد](/docs/agents/#additional).

كما يمكنك تعريف متغيّرات مخصّصة تُوسّع المتغيّرات المدمجة. تتيح لك المتغيّرات ضبط إعدادات مختلفة للنموذج نفسه دون إنشاء إدخالات مكرّرة:

```jsonc title="opencode.jsonc" {6-21}
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "opencode": {
      "models": {
        "gpt-5": {
          "variants": {
            "high": {
              "reasoningEffort": "high",
              "textVerbosity": "low",
              "reasoningSummary": "auto",
            },
            "low": {
              "reasoningEffort": "low",
              "textVerbosity": "low",
              "reasoningSummary": "auto",
            },
          },
        },
      },
    },
  },
}
```

---

## المتغيّرات

تدعم العديد من النماذج عدة متغيّرات بإعدادات مختلفة. يأتي OpenCode مع متغيّرات افتراضية مدمجة للمزوّدين الشائعين.

### المتغيّرات المدمجة

يأتي OpenCode مع متغيّرات افتراضية لعدد كبير من المزوّدين:

**Anthropic**:

- `high` - ميزانية تفكير مرتفعة (الافتراضي)
- `max` - أقصى ميزانية تفكير

**OpenAI**:

تختلف حسب النموذج، لكن بشكل عام:

- `none` - بدون استدلال
- `minimal` - أقل جهد للاستدلال
- `low` - جهد استدلال منخفض
- `medium` - جهد استدلال متوسط
- `high` - جهد استدلال مرتفع
- `xhigh` - جهد استدلال مرتفع جداً

**Google**:

- `low` - جهد/ميزانية رموز أقل
- `high` - جهد/ميزانية رموز أعلى

:::tip
هذه القائمة ليست شاملة. لدى العديد من المزوّدين الآخرين إعدادات افتراضية مدمجة أيضاً.
:::

### متغيّرات مخصّصة

يمكنك تجاوز المتغيّرات الموجودة أو إضافة متغيّراتك الخاصة:

```jsonc title="opencode.jsonc" {7-18}
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "openai": {
      "models": {
        "gpt-5": {
          "variants": {
            "thinking": {
              "reasoningEffort": "high",
              "textVerbosity": "low",
            },
            "fast": {
              "disabled": true,
            },
          },
        },
      },
    },
  },
}
```

### التبديل بين المتغيّرات

استخدم اختصار لوحة المفاتيح `variant_cycle` للتبديل بسرعة بين المتغيّرات. [اعرف المزيد](/docs/keybinds).

---

## تحميل النماذج

عند بدء تشغيل OpenCode، يتحقق من النماذج وفق ترتيب الأولوية التالي:

1. خيار CLI `--model` أو `-m`. الصيغة هي نفسها الموجودة في ملف الإعدادات: `provider_id/model_id`.

2. قائمة النماذج في إعدادات OpenCode.

   ```json title="opencode.json"
   {
     "$schema": "https://opencode.ai/config.json",
     "model": "anthropic/claude-sonnet-4-20250514"
   }
   ```

   الصيغة هنا هي `provider/model`.

3. آخر نموذج تم استخدامه.

4. أول نموذج وفق أولوية داخلية.

---

--- METRICS ---
- Files Extracted: 101
- Estimated Token Budget: ~236570 tokens
- Canonical Reference: https://codewiki.google/github.com/anomalyco/opencode
