# OpenCode コードリーディングガイドライン

## はじめに

このガイドラインは、OpenCodeプロジェクトのコードベースを効率的に理解するための手引きです。
TypeScriptに精通していないエンジニアでも、段階的に学習できるよう構成されています。

**対象読者:**
- プロジェクトに新規参画するエンジニア
- 他言語からの経験者
- コードレビューを行う担当者

**プロジェクト概要:**
OpenCodeは、オープンソースのAIコーディングエージェントです。ターミナルUI(TUI)、Web UI、デスクトップアプリケーションを通じて、AIによるコード生成・編集支援を提供します。

---

## 1. 言語基礎

> このセクションでは、TypeScriptの基本構文と概念を解説します。

### 1.1 プログラム構造

OpenCodeはTypeScriptで記述され、Bunランタイムで実行されます。ESモジュール形式を採用しています。

```typescript
// ファイル: packages/opencode/src/index.ts:1-11
import yargs from "yargs"
import { hideBin } from "yargs/helpers"
import { RunCommand } from "./cli/cmd/run"
import { GenerateCommand } from "./cli/cmd/generate"
import { Log } from "./util/log"
import { AuthCommand } from "./cli/cmd/auth"
import { AgentCommand } from "./cli/cmd/agent"
import { UpgradeCommand } from "./cli/cmd/upgrade"
import { UninstallCommand } from "./cli/cmd/uninstall"
import { ModelsCommand } from "./cli/cmd/models"
import { UI } from "./cli/ui"
```

TypeScriptファイルは通常、以下の順序で構成されます:
1. インポート文
2. 型定義
3. 定数・変数宣言
4. 関数・クラス定義
5. エクスポート文

### 1.2 データ型と変数

TypeScriptは静的型付け言語です。OpenCodeでは主にZodを使用してスキーマ定義と型推論を行います。

```typescript
// ファイル: packages/opencode/src/agent/agent.ts:23-49
export const Info = z
  .object({
    name: z.string(),
    description: z.string().optional(),
    mode: z.enum(["subagent", "primary", "all"]),
    native: z.boolean().optional(),
    hidden: z.boolean().optional(),
    topP: z.number().optional(),
    temperature: z.number().optional(),
    color: z.string().optional(),
    permission: PermissionNext.Ruleset,
    model: z
      .object({
        modelID: z.string(),
        providerID: z.string(),
      })
      .optional(),
    // ... 省略
  })
  .meta({
    ref: "Agent",
  })
export type Info = z.infer<typeof Info>
```

**ポイント:**
- `z.object({})`: オブジェクト型のスキーマ定義
- `.optional()`: オプショナルなフィールド
- `z.infer<typeof Schema>`: スキーマからTypeScript型を推論

### 1.3 制御構造

TypeScriptの制御構造はJavaScriptと同様ですが、OpenCodeでは関数型プログラミングのパターンを多用します。

```typescript
// ファイル: packages/opencode/src/provider/provider.ts:1278-1286
const priority = ["gpt-5", "claude-sonnet-4", "big-pickle", "gemini-3-pro"]
export function sort(models: Model[]) {
  return sortBy(
    models,
    [(model) => priority.findIndex((filter) => model.id.includes(filter)), "desc"],
    [(model) => (model.id.includes("latest") ? 0 : 1), "asc"],
    [(model) => model.id, "desc"],
  )
}
```

**よく使われるパターン:**
- `for...of`: イテレーション
- `map`, `filter`, `reduce`: 配列操作
- `sortBy` (remeda): ソート処理
- 三項演算子: 条件分岐

### 1.4 関数/メソッド定義

OpenCodeでは、名前空間(namespace)パターンと`fn`ヘルパーを使用した関数定義が特徴的です。

```typescript
// ファイル: packages/opencode/src/session/index.ts:212-228
export const create = fn(
  z
    .object({
      parentID: Identifier.schema("session").optional(),
      title: z.string().optional(),
      permission: Info.shape.permission,
    })
    .optional(),
  async (input) => {
    return createNext({
      parentID: input?.parentID,
      directory: Instance.directory,
      title: input?.title,
      permission: input?.permission,
    })
  },
)
```

**`fn`ヘルパーの特徴:**
- 第一引数: Zodスキーマ(入力バリデーション)
- 第二引数: 実際の処理関数
- 自動的な入力検証と型安全性を提供

### 1.5 モジュール/インポート

OpenCodeはパスエイリアスを使用しています。

```typescript
// パスエイリアス例
import { Bus } from "@/bus"        // @/ は packages/opencode/src/ を指す
import { Config } from "../config/config"  // 相対パス
import z from "zod"                // npm パッケージ
```

**インポートパターン:**
- `@/`: `packages/opencode/src/` のエイリアス
- `workspace:*`: モノレポ内の他パッケージ参照
- `catalog:`: 共有依存関係のバージョン管理

---

## 2. プロジェクト固有の概念

> このセクションでは、当プロジェクト特有の概念を解説します。

### 2.1 フレームワーク固有の概念

#### HonoによるAPIサーバー

```typescript
// ファイル: packages/opencode/src/server/server.ts:57-79
const app = new Hono()
export const App: () => Hono = lazy(
  () =>
    app
      .onError((err, c) => {
        log.error("failed", { error: err })
        if (err instanceof NamedError) {
          let status: ContentfulStatusCode
          if (err instanceof NotFoundError) status = 404
          else status = 500
          return c.json(err.toObject(), { status })
        }
        // ...
      })
      .use((c, next) => {
        // ミドルウェア処理
      })
)
```

**Honoの主要概念:**
- `Hono()`: アプリケーションインスタンス
- `.use()`: ミドルウェア登録
- `.get()`, `.post()`, `.put()`, `.delete()`: ルート定義
- `.route()`: サブルートのマウント

#### SolidJSによるUI

```typescript
// ファイル: packages/opencode/src/cli/cmd/tui/app.tsx:130-177
render(
  () => {
    return (
      <ErrorBoundary fallback={(error, reset) => <ErrorComponent />}>
        <ArgsProvider {...input.args}>
          <ExitProvider onExit={onExit}>
            <KVProvider>
              <ToastProvider>
                <RouteProvider>
                  <SDKProvider url={input.url} directory={input.directory}>
                    <SyncProvider>
                      <ThemeProvider mode={mode}>
                        <LocalProvider>
                          <App />
                        </LocalProvider>
                      </ThemeProvider>
                    </SyncProvider>
                  </SDKProvider>
                </RouteProvider>
              </ToastProvider>
            </KVProvider>
          </ExitProvider>
        </ArgsProvider>
      </ErrorBoundary>
    )
  }
)
```

**SolidJSの主要概念:**
- `createSignal`: リアクティブな状態管理
- `createEffect`: 副作用の実行
- `Provider/Context`: 依存性注入
- `Show`, `Switch`, `Match`: 条件付きレンダリング

#### AI SDKとLLM統合

```typescript
// ファイル: packages/opencode/src/provider/provider.ts:87-110
const BUNDLED_PROVIDERS: Record<string, (options: any) => SDK> = {
  "@ai-sdk/amazon-bedrock": createAmazonBedrock,
  "@ai-sdk/anthropic": createAnthropic,
  "@ai-sdk/azure": createAzure,
  "@ai-sdk/google": createGoogleGenerativeAI,
  "@ai-sdk/openai": createOpenAI,
  // ... その他のプロバイダー
}
```

**AI SDK統合の特徴:**
- 複数のLLMプロバイダーをサポート
- 統一されたインターフェースで切り替え可能
- `generateObject`, `streamObject`: 構造化出力の生成

### 2.2 プロジェクト独自のパターン

#### Namespaceパターン

OpenCodeでは、関連する機能をnamespaceでグループ化します。

```typescript
// ファイル: packages/opencode/src/session/index.ts:32-211
export namespace Session {
  const log = Log.create({ service: "session" })

  export const Info = z.object({ /* ... */ })
  export type Info = z.output<typeof Info>

  export const Event = {
    Created: BusEvent.define("session.created", z.object({ info: Info })),
    Updated: BusEvent.define("session.updated", z.object({ info: Info })),
    // ...
  }

  export const create = fn(/* ... */)
  export const get = fn(/* ... */)
  // ...
}
```

**利点:**
- 関連する型、関数、定数の論理的グループ化
- 名前衝突の回避
- ツリーシェイキングの効率化

#### Instance.stateパターン

状態管理とライフサイクル管理のためのパターンです。

```typescript
// ファイル: packages/opencode/src/agent/agent.ts:51-55
const state = Instance.state(async () => {
  const cfg = await Config.get()
  // 初期化処理
  return result
})
```

**特徴:**
- 遅延初期化(lazy initialization)
- インスタンスごとの状態隔離
- 自動的なクリーンアップ

#### Tool定義パターン

```typescript
// ファイル: packages/opencode/src/tool/bash.ts:55-77
export const BashTool = Tool.define("bash", async () => {
  const shell = Shell.acceptable()

  return {
    description: DESCRIPTION,
    parameters: z.object({
      command: z.string().describe("The command to execute"),
      timeout: z.number().describe("Optional timeout").optional(),
      workdir: z.string().describe("Working directory").optional(),
      description: z.string().describe("Description of the command"),
    }),
    async execute(params, ctx) {
      // 実行ロジック
      return { title, metadata, output }
    },
  }
})
```

**ツール定義の構造:**
- `id`: ツールの識別子
- `description`: AIモデルへの説明
- `parameters`: Zodスキーマによる入力定義
- `execute`: 実際の処理ロジック

---

## 3. 命名規則

> このセクションでは、プロジェクト全体で使用される命名規則を解説します。

### 3.1 ファイル・ディレクトリ命名

| パターン | 意味 | 例 |
|---------|------|-----|
| `*.ts` | TypeScriptソースファイル | `session.ts`, `agent.ts` |
| `*.tsx` | TypeScript + JSX (UI) | `app.tsx`, `dialog.tsx` |
| `*.sql.ts` | Drizzle ORM スキーマ | `session.sql.ts` |
| `*.txt` | テキストリソース(プロンプト等) | `bash.txt` |
| `index.ts` | モジュールエントリーポイント | `src/session/index.ts` |
| `kebab-case/` | ディレクトリ名 | `cli/cmd/tui/` |

### 3.2 クラス・関数・変数命名

| プレフィックス/サフィックス | 意味 | 例 |
|---------------------------|------|-----|
| `*Tool` | AIツール定義 | `BashTool`, `ReadTool` |
| `*Command` | CLIコマンド | `RunCommand`, `AuthCommand` |
| `*Provider` | コンテキストプロバイダー | `SDKProvider`, `ThemeProvider` |
| `*Routes` | Honoルート定義 | `SessionRoutes`, `ProjectRoutes` |
| `use*` | SolidJSフック | `useDialog`, `useTheme` |
| `create*` | ファクトリ関数 | `createAnthropic`, `createOpenAI` |
| `*Error` | エラークラス | `NotFoundError`, `BusyError` |
| `*Info` | データ型定義 | `Session.Info`, `Agent.Info` |
| `*Event` | イベント定義 | `Session.Event`, `Bus.Event` |

### 3.3 プログラム分類一覧

| カテゴリ | ディレクトリ | 説明 |
|---------|-------------|------|
| CLI | `src/cli/` | コマンドラインインターフェース |
| Server | `src/server/` | APIサーバー |
| Session | `src/session/` | セッション管理 |
| Agent | `src/agent/` | AIエージェント |
| Provider | `src/provider/` | LLMプロバイダー統合 |
| Tool | `src/tool/` | AIツール実装 |
| MCP | `src/mcp/` | Model Context Protocol |

---

## 4. ディレクトリ構造

> このセクションでは、プロジェクトのディレクトリ構造を解説します。

```
opencode-dev/
├── packages/               # モノレポのパッケージ群
│   ├── opencode/          # コアパッケージ(メイン)
│   │   ├── src/
│   │   │   ├── index.ts   # エントリーポイント
│   │   │   ├── cli/       # CLIコマンド
│   │   │   ├── server/    # APIサーバー
│   │   │   ├── session/   # セッション管理
│   │   │   ├── agent/     # AIエージェント
│   │   │   ├── provider/  # LLMプロバイダー
│   │   │   ├── tool/      # AIツール
│   │   │   ├── mcp/       # MCP統合
│   │   │   ├── config/    # 設定管理
│   │   │   ├── util/      # ユーティリティ
│   │   │   └── storage/   # データストレージ
│   │   └── package.json
│   ├── app/               # Web UI (SolidJS)
│   ├── desktop/           # デスクトップアプリ (Tauri)
│   ├── ui/                # 共有UIコンポーネント
│   ├── console/           # 管理コンソール
│   ├── plugin/            # プラグインSDK
│   ├── sdk/               # クライアントSDK
│   └── util/              # 共有ユーティリティ
├── infra/                 # インフラ設定 (SST)
├── script/                # ビルド・リリーススクリプト
├── sdks/                  # IDE拡張機能
│   └── vscode/            # VS Code拡張
└── .opencode/             # OpenCode設定
    ├── agent/             # カスタムエージェント
    ├── command/           # カスタムコマンド
    └── tool/              # カスタムツール
```

### 各ディレクトリの役割

| ディレクトリ | 役割 | 主要ファイル |
|-------------|------|-------------|
| `packages/opencode/src/cli/` | CLIコマンド実装 | `cmd/run.ts`, `cmd/serve.ts` |
| `packages/opencode/src/server/` | HTTPサーバー・API | `server.ts`, `routes/` |
| `packages/opencode/src/session/` | セッション・メッセージ管理 | `index.ts`, `llm.ts` |
| `packages/opencode/src/agent/` | AIエージェント定義 | `agent.ts` |
| `packages/opencode/src/provider/` | LLMプロバイダー統合 | `provider.ts`, `models.ts` |
| `packages/opencode/src/tool/` | ビルトインツール | `bash.ts`, `read.ts`, `edit.ts` |
| `packages/opencode/src/mcp/` | MCP (Model Context Protocol) | `index.ts` |
| `packages/opencode/src/config/` | 設定ファイル読み込み | `config.ts` |
| `packages/app/` | Web UI (SolidJS) | `src/routes/`, `src/components/` |
| `packages/desktop/` | デスクトップアプリ | `src-tauri/` |
| `packages/ui/` | 共有UIコンポーネント | `src/components/` |

---

## 5. アーキテクチャ

> このセクションでは、プロジェクトのアーキテクチャパターンを解説します。

### 5.1 全体アーキテクチャ

OpenCodeはクライアント/サーバーアーキテクチャを採用しています。

```
┌─────────────────────────────────────────────────────────────┐
│                       Clients                                │
├─────────────────┬─────────────────┬─────────────────────────┤
│   TUI (CLI)     │    Web App      │    Desktop App          │
│   (SolidJS +    │   (SolidJS)     │   (Tauri + SolidJS)     │
│    opentui)     │                 │                          │
└────────┬────────┴────────┬────────┴──────────┬──────────────┘
         │                 │                    │
         │    HTTP/SSE     │                    │
         └────────────────►├◄───────────────────┘
                           │
┌──────────────────────────┴──────────────────────────────────┐
│                    OpenCode Server                           │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                  Hono HTTP Server                       ││
│  │  /session  /provider  /config  /mcp  /event (SSE)       ││
│  └───────────────────────────┬─────────────────────────────┘│
│                              │                               │
│  ┌───────────────────────────┴─────────────────────────────┐│
│  │                    Core Services                         ││
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐ ││
│  │  │ Session  │  │  Agent   │  │ Provider │  │   MCP    │ ││
│  │  │ Manager  │  │  Runner  │  │  Manager │  │ Manager  │ ││
│  │  └──────────┘  └──────────┘  └──────────┘  └──────────┘ ││
│  └─────────────────────────────────────────────────────────┘│
│                              │                               │
│  ┌───────────────────────────┴─────────────────────────────┐│
│  │                      AI Layer                            ││
│  │  ┌──────────────────────────────────────────────────────┐││
│  │  │              AI SDK (Vercel)                         │││
│  │  │  streamText / generateObject / Tool Execution        │││
│  │  └──────────────────────────────────────────────────────┘││
│  │  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────────────┐ ││
│  │  │Anthropic│ │ OpenAI  │ │  Google │ │  Other Providers│ ││
│  │  └─────────┘ └─────────┘ └─────────┘ └─────────────────┘ ││
│  └─────────────────────────────────────────────────────────┘│
│                              │                               │
│  ┌───────────────────────────┴─────────────────────────────┐│
│  │                    Storage Layer                         ││
│  │        SQLite (Drizzle ORM)  │  File System              ││
│  └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
```

### 5.2 レイヤー構成

| レイヤー | 責務 | 代表的なファイル |
|---------|------|-----------------|
| Presentation | UI/CLI表示、ユーザー入力 | `cli/cmd/tui/app.tsx`, `packages/app/` |
| API | HTTPルーティング、リクエスト処理 | `server/server.ts`, `server/routes/` |
| Application | ビジネスロジック、ワークフロー | `session/index.ts`, `agent/agent.ts` |
| Domain | ドメインモデル、型定義 | `provider/provider.ts`, `tool/tool.ts` |
| Infrastructure | DB、外部API、ファイルシステム | `storage/db.ts`, `provider/sdk/` |

### 5.3 データフロー

**ユーザーメッセージの処理フロー:**

```
1. ユーザー入力 (TUI/Web)
       │
       ▼
2. HTTP POST /session/{id}/message
       │
       ▼
3. Session.prompt() - メッセージをセッションに追加
       │
       ▼
4. LLM.stream() - AIモデルへストリーミングリクエスト
       │
       ▼
5. Tool実行 (必要に応じて)
   ├── BashTool: コマンド実行
   ├── ReadTool: ファイル読み込み
   ├── EditTool: ファイル編集
   └── その他ツール
       │
       ▼
6. SSE経由でクライアントにストリーミング
       │
       ▼
7. UI更新 (リアルタイム表示)
```

---

## 6. 主要コンポーネント

> このセクションでは、主要なコンポーネントとその連携を解説します。

### 6.1 エントリーポイント

```typescript
// ファイル: packages/opencode/src/index.ts:48-156
const cli = yargs(hideBin(process.argv))
  .scriptName("opencode")
  .command(RunCommand)      // bun dev (TUI起動)
  .command(ServeCommand)    // opencode serve (APIサーバー)
  .command(WebCommand)      // opencode web (Web UI)
  .command(AuthCommand)     // opencode auth (認証)
  .command(ModelsCommand)   // opencode models (モデル一覧)
  // ... その他コマンド
```

**主要なエントリーポイント:**
- `opencode` または `bun dev`: TUIの起動
- `opencode serve`: ヘッドレスサーバーモード
- `opencode web`: Webブラウザでの起動

### 6.2 ビジネスロジック

#### セッション管理

```typescript
// ファイル: packages/opencode/src/session/index.ts:287-326
export async function createNext(input: {
  id?: string
  title?: string
  parentID?: string
  directory: string
  permission?: PermissionNext.Ruleset
}) {
  const result: Info = {
    id: Identifier.descending("session", input.id),
    slug: Slug.create(),
    version: Installation.VERSION,
    projectID: Instance.project.id,
    directory: input.directory,
    parentID: input.parentID,
    title: input.title ?? createDefaultTitle(!!input.parentID),
    permission: input.permission,
    time: {
      created: Date.now(),
      updated: Date.now(),
    },
  }
  Database.use((db) => {
    db.insert(SessionTable).values(toRow(result)).run()
    Database.effect(() => Bus.publish(Event.Created, { info: result }))
  })
  return result
}
```

#### エージェント実行

```typescript
// ファイル: packages/opencode/src/agent/agent.ts:76-130
const result: Record<string, Info> = {
  build: {
    name: "build",
    description: "The default agent. Executes tools based on configured permissions.",
    options: {},
    permission: PermissionNext.merge(
      defaults,
      PermissionNext.fromConfig({
        question: "allow",
        plan_enter: "allow",
      }),
      user,
    ),
    mode: "primary",
    native: true,
  },
  plan: {
    name: "plan",
    description: "Plan mode. Disallows all edit tools.",
    options: {},
    permission: PermissionNext.merge(
      defaults,
      PermissionNext.fromConfig({
        question: "allow",
        plan_exit: "allow",
        edit: { "*": "deny" },
      }),
      user,
    ),
    mode: "primary",
    native: true,
  },
  // ...
}
```

### 6.3 データアクセス

```typescript
// ファイル: packages/opencode/src/session/index.ts:335-339
export const get = fn(Identifier.schema("session"), async (id) => {
  const row = Database.use((db) =>
    db.select().from(SessionTable).where(eq(SessionTable.id, id)).get()
  )
  if (!row) throw new NotFoundError({ message: `Session not found: ${id}` })
  return fromRow(row)
})
```

**Drizzle ORMの使用パターン:**
- `Database.use()`: トランザクションコンテキスト
- `db.select()`, `db.insert()`, `db.update()`, `db.delete()`: CRUD操作
- `eq()`, `and()`, `or()`: 条件句

### 6.4 ユーティリティ/共通機能

```typescript
// ファイル: packages/opencode/src/util/log.ts
export namespace Log {
  export function create(opts: { service: string }) {
    return {
      info: (msg: string, data?: object) => { /* ... */ },
      error: (msg: string, data?: object) => { /* ... */ },
      debug: (msg: string, data?: object) => { /* ... */ },
      time: (label: string, data?: object) => { /* ... */ },
    }
  }
}

// 使用例
const log = Log.create({ service: "session" })
log.info("session created", { id: session.id })
```

---

## 7. よく使われるパターン

> このセクションでは、コード内で頻出するパターンを解説します。

### パターン一覧

| パターン | 説明 | 出現頻度 | 代表的なファイル |
|---------|------|---------|-----------------|
| Namespace Module | 関連機能のグループ化 | 高 | `session/index.ts`, `agent/agent.ts` |
| Zod Schema + Type | スキーマ定義と型推論 | 高 | 全ファイル |
| fn() Helper | 型安全な関数定義 | 高 | `session/index.ts` |
| Instance.state | 状態管理 | 中 | `config/config.ts`, `provider/provider.ts` |
| BusEvent | イベント駆動 | 中 | `bus/bus-event.ts` |
| lazy() | 遅延初期化 | 中 | `server/server.ts` |

### 各パターンの詳細

#### パターン1: Namespace Module

**目的:** 関連する型、関数、定数を論理的にグループ化

```typescript
// ファイル: packages/opencode/src/session/index.ts:32-211
export namespace Session {
  // プライベートな状態
  const log = Log.create({ service: "session" })

  // 公開型定義
  export const Info = z.object({ /* ... */ })
  export type Info = z.output<typeof Info>

  // イベント定義
  export const Event = {
    Created: BusEvent.define("session.created", z.object({ info: Info })),
  }

  // 公開関数
  export const create = fn(/* ... */)
  export const get = fn(/* ... */)
}
```

**解説:** Namespaceを使用することで、`Session.create()`, `Session.Info`のように明確なAPIを提供できます。

#### パターン2: Zod Schema + Type Inference

**目的:** ランタイムバリデーションと型安全性の両立

```typescript
// ファイル: packages/opencode/src/provider/provider.ts:593-662
export const Model = z
  .object({
    id: z.string(),
    providerID: z.string(),
    api: z.object({
      id: z.string(),
      url: z.string(),
      npm: z.string(),
    }),
    name: z.string(),
    capabilities: z.object({
      temperature: z.boolean(),
      reasoning: z.boolean(),
      // ...
    }),
  })
  .meta({ ref: "Model" })

export type Model = z.infer<typeof Model>
```

**解説:** Zodスキーマから自動的にTypeScript型が生成されるため、定義の重複を避けられます。

#### パターン3: Tool定義

**目的:** AIモデルが使用できるツールの標準化された定義

```typescript
// ファイル: packages/opencode/src/tool/tool.ts:48-88
export function define<Parameters extends z.ZodType, Result extends Metadata>(
  id: string,
  init: Info<Parameters, Result>["init"] | Awaited<ReturnType<Info<Parameters, Result>["init"]>>,
): Info<Parameters, Result> {
  return {
    id,
    init: async (initCtx) => {
      const toolInfo = init instanceof Function ? await init(initCtx) : init
      const execute = toolInfo.execute
      toolInfo.execute = async (args, ctx) => {
        try {
          toolInfo.parameters.parse(args)
        } catch (error) {
          throw new Error(`Invalid arguments: ${error}`)
        }
        const result = await execute(args, ctx)
        const truncated = await Truncate.output(result.output, {}, initCtx?.agent)
        return { ...result, output: truncated.content }
      }
      return toolInfo
    },
  }
}
```

**解説:** ツール定義時に自動的な入力バリデーションと出力の切り詰め処理が適用されます。

---

## 8. 業務フロー追跡の実践例

> このセクションでは、実際の業務フローをコードで追跡する方法を解説します。

### 8.1 フロー追跡の基本手順

1. エントリーポイントを特定
2. 処理の流れを追跡（呼び出し関係を追う）
3. データの変換を確認
4. 最終的な出力を確認

### 8.2 フロー追跡の実例

#### 例1: ユーザーメッセージの送信からAI応答まで

**概要:** ユーザーがメッセージを送信し、AIが応答を生成するまでの流れ

**処理フロー:**
```
ユーザー入力 → HTTP POST → Session.prompt() → LLM.stream() → Tool実行 → SSE応答
```

**詳細な追跡:**

1. **HTTPリクエスト受信** (`packages/opencode/src/server/routes/session.ts`)
   ```typescript
   .post(
     "/:sessionID/prompt",
     validator("param", z.object({ sessionID: z.string() })),
     validator("json", SessionPrompt.Payload),
     async (c) => {
       const { sessionID } = c.req.valid("param")
       const payload = c.req.valid("json")
       await SessionPrompt.prompt({ sessionID, ...payload })
       return c.json(true)
     },
   )
   ```

2. **セッションプロンプト処理** (`packages/opencode/src/session/prompt.ts`)
   ```typescript
   export async function prompt(input: {
     sessionID: string
     parts: Part[]
     model: string
     agent: string
   }) {
     // メッセージをDBに保存
     await Session.updateMessage({
       id: messageID,
       sessionID: input.sessionID,
       role: "user",
       parts: input.parts,
     })

     // LLMストリーミング開始
     await LLM.stream({
       sessionID: input.sessionID,
       model: input.model,
       agent: input.agent,
     })
   }
   ```

3. **LLMストリーミング** (`packages/opencode/src/session/llm.ts`)
   ```typescript
   export async function stream(input: StreamInput) {
     const language = await Provider.getLanguage(model)

     for await (const chunk of streamText({
       model: language,
       messages: await buildMessages(input.sessionID),
       tools: await Registry.tools(agent),
     })) {
       // ツール呼び出しの処理
       if (chunk.toolCall) {
         const result = await executeTool(chunk.toolCall)
         Bus.publish(MessageV2.Event.PartUpdated, { part: result })
       }

       // テキスト応答のストリーミング
       Bus.publish(MessageV2.Event.PartDelta, {
         delta: chunk.text,
       })
     }
   }
   ```

4. **SSE経由でクライアントに配信** (`packages/opencode/src/server/server.ts`)
   ```typescript
   .get("/event", async (c) => {
     return streamSSE(c, async (stream) => {
       const unsub = Bus.subscribeAll(async (event) => {
         await stream.writeSSE({ data: JSON.stringify(event) })
       })
       // ...
     })
   })
   ```

### 8.3 フロー追跡チェックリスト

- [ ] エントリーポイントを特定したか
- [ ] 呼び出し関係を把握したか
- [ ] データの変換ポイントを確認したか
- [ ] エラーハンドリングを確認したか
- [ ] 最終的な出力を確認したか

---

## 9. 設計書の参照順序

> このセクションでは、プロジェクト理解のための設計書参照順序を案内します。

### 9.1 目的別ロードマップ

#### 全体像を把握したい場合
1. `README.md` - プロジェクト概要
2. `CONTRIBUTING.md` - 開発環境セットアップ
3. `packages/opencode/src/index.ts` - エントリーポイント
4. `packages/opencode/src/server/server.ts` - APIサーバー構造

#### 特定機能を理解したい場合
1. 対象機能のnamespace定義ファイル（例: `session/index.ts`）
2. 関連するツール実装（例: `tool/bash.ts`）
3. APIルート定義（例: `server/routes/session.ts`）

#### 改修作業を行う場合
1. `AGENTS.md` - スタイルガイド
2. 対象機能のテストファイル（`*.test.ts`）
3. 関連する設定スキーマ（`config/config.ts`）

### 9.2 ドキュメント一覧

| ドキュメント | 概要 | 参照タイミング |
|-------------|------|---------------|
| `README.md` | インストール方法、基本的な使い方 | 最初に読む |
| `CONTRIBUTING.md` | 開発環境構築、PRルール | 開発開始時 |
| `AGENTS.md` | コーディングスタイルガイド | コード記述時 |
| `SECURITY.md` | セキュリティポリシー | セキュリティ関連作業時 |
| `packages/docs/` | 詳細ドキュメント | 特定機能の深堀り時 |

---

## 10. トラブルシューティング

> このセクションでは、コードリーディング時によくある問題と解決法を解説します。

### よくある疑問と回答

#### Q: `@/` から始まるインポートパスの解決方法は？
A: `@/`は`packages/opencode/src/`へのエイリアスです。`tsconfig.json`で定義されています。

#### Q: `fn()`ヘルパーの役割は？
A: Zodスキーマによる入力バリデーションと型推論を自動化するヘルパー関数です。`packages/opencode/src/util/fn.ts`で定義されています。

#### Q: `Instance.state()`と`lazy()`の違いは？
A: `Instance.state()`はプロジェクトインスタンスごとの状態管理、`lazy()`はグローバルな遅延初期化に使用します。

#### Q: イベントシステムの仕組みは？
A: `Bus`モジュールによるPub/Subパターンを採用しています。`BusEvent.define()`でイベント型を定義し、`Bus.publish()`で発行、`Bus.subscribe()`で購読します。

#### Q: MCPとは何か？
A: Model Context Protocol の略で、外部ツールやサービスをAIモデルに接続するための標準プロトコルです。`packages/opencode/src/mcp/`で実装されています。

### デバッグのヒント

1. **ログの確認**: `Log.create()`でサービスごとのロガーを作成し、`~/.opencode/logs/`に出力されます

2. **VSCode デバッグ**: `.vscode/launch.example.json`を参考にデバッグ設定を行います
   ```bash
   bun run --inspect=ws://localhost:6499/ --cwd packages/opencode ./src/index.ts serve
   ```

3. **型エラーの解決**: Zodスキーマと型定義の整合性を確認します

4. **データベース確認**: SQLiteファイルは`~/.opencode/data/opencode.db`にあります

---

## 付録

### A. 用語集

| 用語 | 説明 |
|-----|------|
| Agent | AIの振る舞いを定義するモード（build, plan など） |
| Session | ユーザーとAIの対話セッション |
| Tool | AIが実行できる機能（bash, read, edit など） |
| Provider | LLMサービスプロバイダー（Anthropic, OpenAI など） |
| MCP | Model Context Protocol - 外部ツール統合プロトコル |
| TUI | Terminal User Interface - ターミナルUI |
| Skill | スラッシュコマンドで呼び出せる再利用可能な機能 |
| Part | メッセージの構成要素（テキスト、ツール呼び出し結果など） |

### B. ファイル一覧

| ファイル/ディレクトリ | 説明 | 主な内容 |
|---------------------|------|---------|
| `packages/opencode/src/index.ts` | CLIエントリーポイント | yargsコマンド登録 |
| `packages/opencode/src/server/server.ts` | APIサーバー | Honoルート定義 |
| `packages/opencode/src/session/index.ts` | セッション管理 | CRUD操作、イベント |
| `packages/opencode/src/agent/agent.ts` | エージェント定義 | build, plan, general |
| `packages/opencode/src/provider/provider.ts` | LLMプロバイダー | モデル管理、SDK統合 |
| `packages/opencode/src/tool/` | ビルトインツール | bash, read, edit, grep |
| `packages/opencode/src/config/config.ts` | 設定読み込み | opencode.json解析 |
| `packages/opencode/src/mcp/index.ts` | MCP統合 | 外部ツール接続 |

### C. 参考資料

- [TypeScript公式ドキュメント](https://www.typescriptlang.org/docs/)
- [Zod公式ドキュメント](https://zod.dev/)
- [Hono公式ドキュメント](https://hono.dev/)
- [SolidJS公式ドキュメント](https://www.solidjs.com/docs/)
- [AI SDK (Vercel)](https://sdk.vercel.ai/docs/)
- [Drizzle ORM](https://orm.drizzle.team/docs/overview)
- [Bun公式ドキュメント](https://bun.sh/docs)
- [Model Context Protocol](https://modelcontextprotocol.io/)
