Skip to content

拡張エントリ: activate 起動フロー

源码版本v4.0.10

役割

activate() は VSCode 拡張がユーザーに初めて拡張機能をトリガーされた時に呼ばれるエントリで、apps/vscode/src/extension.ts に書かれている。Cline は起動全体をここで五つのステップに分ける。まずプラットフォーム依存の HostProvider を組み、次に前バージョンが残したストレージ形式を整理し、VSCode 自身のストレージを共有ファイルストレージにエクスポートし、クロスプラットフォーム初期化 (initialize) を走らせ、最後に VSCode 専用のコマンド、ビュー、URI handler、CodeAction Provider を登録する。関数全体は createClineAPI で締めくくり、外部利用者が直接呼べるミニマムな API オブジェクトを返す。

これが存在する意義は、「拡張がどう VSCode に立ち上げられるか」というプラットフォーム依存の事柄と、「Cline 自身がどう初期化されるか」というクロスプラットフォームの事柄を分離することにある。common.tsinitialize() は VSCode、CLI、JetBrains の三つの host で共通利用され (initialize:34)、extension.ts は VSCode 固有の context、コマンド、URI などを接ぐことだけを担う。そのため extension.ts を読むと vscode.commands.registerCommand(...) といった登録動作がほとんどで、本当のサービス組み立ては initialize()Controller のコンストラクタにある。

設計動機

  • プラットフォーム抽象を最優先:setupHostProvider が先に走る必要がある (setupHostProvider:73)。後続のすべてのサービスは HostProvider.get() で webview、ターミナル、コールバック URL を取得するから。VSCode 固有の実装 (VscodeWebviewProvider、VscodeTerminalManager 等) はここで注入される。
  • マイグレーションをエクスポートより先に:cleanupLegacyVSCodeStorageexportVSCodeStorageToSharedFiles の前に走る (cleanupLegacyVSCodeStorage:78)。workspace→global、task history→ファイル、custom instructions→rules といった過去の汚れたデータを先に掃除してから、きれいな state を ~/.cline/data/ にエクスポートし、他プラットフォームが一貫した状態を読めるようにする。
  • 共通初期化を common.ts に切り出し:クロスプラットフォームサービス (StateManager、ErrorService、PostHog、ClineTempManager、FileContextTracker 等) はすべて initialize() の中で立ち上がる (external services:56)。VSCode はこれを再実装しない。これにより CLI と JetBrains が同じ起動ロジックを再利用できる。
  • webview は retainContextWhenHidden を使用:registerWebviewViewProviderretainContextWhenHidden: true を渡す (webview retain:124)。サイドバーが閉じても React の状態が失われず、次回オープン時に再レンダリング不要となる。代償はメモリ常駐だが、Cline の会話コンテキストはこのオーバーヘッドに見合う価値がある。
  • コマンドを二段階で登録:VSCode コマンドはまず ExtensionRegistryInfo.commands から ID 定数を取得し (ExtensionRegistryInfo:130)、package.json とコード上の command ID の一致を保証する。Dev モードでは追加で dev/commands/tasks のデバッグコマンドを読み込む (dev commands:193)。
  • URI handler のリトライで競合を吸収:handleUri がディープリンクを処理する際、サイドバーがまだ初期化されていなければ openClineSidebarForTaskUri を呼んでから再度処理する (task uri retry:178)。初回インストール時にサイドバー初期化とディープリンク到着が竞合するのを防ぐためである。

主要ファイル

  • activate:68 — 拡張のエントリ全体。五段階の起動フローがここに集まる。
  • setupHostProvider call:73 — 第一ステップ。VSCode 版 HostProvider (webview、diff、comment review、terminal、callback URL) を組み立てる。
  • cleanupLegacyVSCodeStorage:78 — 第二ステップ。workspace→global、task history→file、custom instructions→rules などの過去形式を整理する。
  • exportVSCodeStorageToSharedFiles:84 — 第三ステップ。VSCode ネイティブストレージを ~/.cline/data/ の共有ファイルストレージにエクスポートし、他プラットフォームが読めるようにする。
  • initialize call:88 — 第四ステップ。common.ts のクロスプラットフォーム初期化を走らせ、VscodeWebviewProvider を返す。
  • registerWebviewViewProvider:124 — サイドバー webview を VSCode に登録し、retainContextWhenHidden を有効化する。
  • registerUriHandler:187 — URI handler を登録し、vscode://extension.id/cline/task/... といったディープリンクを処理する。
  • registerCodeActionsProvider:248 — CodeAction Provider を登録し、エディタのエラーランプに「Add to Cline / Explain / Improve / Fix with Cline」の四つのアクションを取り付ける。
  • setupHostProvider:602 — HostProvider を組み立てる実際の関数。VscodeWebviewProvider、VscodeDiffViewProvider、VscodeTerminalManager などのファクトリ関数を渡す。
  • createClineAPI:553 — 外部 API を返す。startNewTasksendMessagepressPrimaryButtonpressSecondaryButton の四つのメソッドを提供する。
  • initialize:34 — クロスプラットフォーム初期化の本体。StateManager、PostHog、ErrorService、syncWorker をここで立ち上げる。
  • deactivate:699 — 非アクティブ化時に tearDown() を呼び、comment review controller を dispose する。

データフロー

起動順序は activate の先頭で一目で分かる。核心は「マイグレーションを先に、初期化を後に。共有を先に、プラットフォームを後に」である:

typescript
// apps/vscode/src/extension.ts
// 1. Set up HostProvider for VSCode
setupHostProvider(context)

// 2. Clean up legacy data patterns within VSCode's native storage.
await cleanupLegacyVSCodeStorage(context)

// 3. One-time export of VSCode's native storage to shared file-backed stores.
const workspacePath = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath
const storageContext = createStorageContext({ workspacePath })
await exportVSCodeStorageToSharedFiles(context, storageContext)

// 4. Register services and perform common initialization
const webview = (await initialize(storageContext)) as VscodeWebviewProvider

この部分は activation sequence:73 の付近にある。initialize() の内部 (createWebviewProvider:63) で HostProvider.get().createWebviewProvider() を呼ぶと、ファクトリメソッドが VscodeWebviewProvider インスタンスを返す。このインスタンスは構築時に同期的に new Controller(context) を呼び、Controller のコンストラクタで StateManager、AuthService、McpHub、BannerService などの一連の依存が立ち上がる。したがって initialize() が返る時点で Controller は既に webview メッセージを受け取る準備が整っている。activate() の後半に戻ってからコマンド、URI handler、CodeAction Provider を登録するが、これらの登録动作は最終的にリクエストを webview.controllerWebviewProvider.getInstance() に転送する。

境界と失敗

  • StateManager 初期化失敗は致命的ではない:initialize()StateManager.initialize を try/catch で囲み、失敗すると ERROR メッセージを出すが処理は続行する (stateManager try:45)。ストレージはメモリ上でも使えるため、永続化できないだけですむ。
  • task URI とサイドバー初期化の競合:URI handler は最初に task ディープリンクの処理を試み、失敗したら openClineSidebarForTaskUri でサイドバーが可視になるのを待って再試行する (task uri retry:178)。最大 3 秒待つ。
  • dev モードの追加コマンドは非同期読み込み:IS_DEV 分岐では動的 import("./dev/commands/tasks") でデバッグコマンドを読み込む (dev import:193)。失敗はログに記録するだけでメインフローには影響しない。
  • secrets のウィンドウ間同期:storageContext.secrets.onDidChange を監視し、cline:clineAccountId が変化した時、新値は別ウィンドウでのログインを、空値は別ウィンドウでのログアウトを意味する (secrets listener:533)。これにより複数ウィンドウ間でログイン状態を一貫させる。
  • ripgrep のパスプローブ:VSCode 1.122 で ripgrep が @vscode/ripgrep から @vscode/ripgrep-universal に移行した。getBinaryLocation は新しい配置を先に探し、失敗したら古いパスにフォールバックする (ripgrep path probe:685)。
  • deactivate は tearDown を呼ぶ:deactivate()common.tstearDown() を呼び (tearDown:153)、PostHog、telemetry、ErrorService、featureFlags、WebviewProvider、syncWorker、HookProcessRegistry、ClineTempManager の順に dispose しゾンビプロセスを残さない。

まとめ

activate() は VSCode 固有の機能と Cline のビジネスロジックをきれいに分けている。VSCode 側はコマンド、ビュー、URI handler、CodeAction の登録だけを担い、本当のサービス組み立ては common.tsinitialize() と Controller のコンストラクタに委ねられる。このレイヤ分けにより CLI と JetBrains は同じ初期化コードを再利用できる。初期化後に Controller がどう依存を組み立て、webview と Task をどう繋ぐかは /startup/controller に、webview と拡張の間で gRPC-over-postMessage でどう通信するかは /startup/webview-bridge に続く。

公式資料: Cline ドキュメント · README