Browse Source

Make background orchestration the default

alvinreal 2 months ago
parent
commit
6ea8956130

+ 14 - 14
README.ja-JP.md

@@ -1,9 +1,6 @@
 <div align="center">
-  <a href="https://github.com/alvinunreal/oh-my-opencode-slim/stargazers">
-    <img src="img/v2beta.webp" alt="V2 Beta Release" style="border-radius: 10px;">
-  </a>
-  <h3>✨ V2 ベータリリース:バックグラウンドオーケストレーションが登場 ✨</h3>
-  <p><i>オーケストレーターがバックグラウンドで専門エージェントをスケジューリングし、<br><code>/deepwork</code> が大きなゴールをファイルに紐づいた計画へと変換します。<br>ベータテスターの皆様:フィードバックは Telegram でお寄せください。</i></p>
+  <h3>✨ デフォルトのバックグラウンドオーケストレーションが登場 ✨</h3>
+  <p><i>オーケストレーターはワークフローマネージャーとしてバックグラウンドで専門エージェントをスケジューリングし、<br><code>/deepwork</code> が大きなゴールをファイルに紐づいた計画へと変換します。<br>フィードバックは Telegram でお寄せください。</i></p>
 
   <p><b>オープン・マルチエージェント・スイート</b> · あらゆるモデルを組み合わせ · タスクを自動委譲</p>
 
@@ -45,19 +42,21 @@ Install and configure oh-my-opencode-slim: https://raw.githubusercontent.com/alv
 bunx oh-my-opencode-slim@latest install
 ```
 
-### V2 バックグラウンドオーケストレーション・ベータ
+> **翻訳ステータス:** 英語版 README が最新です。この日本語訳には古い表現が一部残っている可能性があります。
 
-V2 では、オーケストレーターがデフォルトの実行ワーカーからスケジューラーへと役割を変えます。
+### デフォルトのバックグラウンドオーケストレーション
+
+現在のデフォルトでは、オーケストレーターが実行ワーカーではなくスケジューラーとして動作します。
 作業を計画し、専門エージェントをバックグラウンドタスクとしてディスパッチし、ステータスをポーリングし、
 結果を整合させてから処理を続行します。これには OpenCode のネイティブな
-バックグラウンドサブエージェントサポートが必要であり、ベータユーザーは実験的なフラグを
-有効にして OpenCode を起動する必要があります。
+バックグラウンドサブエージェントサポートが必要です。下記の環境変数を有効にして OpenCode を起動してください。
 
 ```bash
-bunx oh-my-opencode-slim@beta install
-OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=1 opencode
+bunx oh-my-opencode-slim@latest install --background-subagents=yes
 ```
 
+インストール後はターミナルを再起動するか、更新された shell ファイルを source してから `opencode` を実行してください。一回限りなら `OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true opencode` でも起動できます。
+
 ### はじめに
 
 インストーラーは OpenAI と OpenCode Go の両方のプリセットを生成し、デフォルトで OpenAI が有効になっています。OpenAI プリセットでは、判断力の高いエージェントに `openai/gpt-5.5` を、より高速でスコープの限定されたエージェントに `openai/gpt-5.4-mini` を使用します。インストール時に OpenCode Go をアクティブにするには `bunx oh-my-opencode-slim@latest install --preset=opencode-go` を実行するか、インストール後に `~/.config/opencode/oh-my-opencode-slim.json` のデフォルトプリセット名を変更してください。
@@ -79,7 +78,7 @@ OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=1 opencode
 4. **各エージェントに使用したいモデルを更新します**
 
 > [!TIP]
-> 自動委譲の仕組みを理解しておくことを**推奨**します。**[Orchestrator のプロンプト](https://github.com/alvinunreal/oh-my-opencode-slim/blob/master/src/agents/orchestrator.ts#L28)** には、委譲ルール、専門エージェントへのルーティングロジック、メインエージェントがサブエージェントに作業を引き継ぐべきしきい値が記述されています。`@agentName <task>` のようにサブエージェントを呼び出すことで、いつでも手動で委譲できます。
+> バックグラウンドオーケストレーションの仕組みを理解しておくことを**推奨**します。**[Orchestrator のプロンプト](https://github.com/alvinunreal/oh-my-opencode-slim/blob/master/src/agents/orchestrator.ts#L28)** には、スケジューラーのルール、専門エージェントへのルーティングロジック、作業をバックグラウンドエージェントへ割り当てるしきい値が記述されています。`@agentName <task>` のようにサブエージェントを呼び出すことで、いつでも手動で委譲できます。
 
 デフォルトで生成される設定には `openai` と `opencode-go` の両方のプリセットが含まれます。
 
@@ -122,8 +121,10 @@ OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=1 opencode
 
 インストールと認証を済ませた後、すべてのエージェントが設定済みで応答することを確認してください:
 
+先にターミナルを再起動するか、更新された shell ファイルを source してください。環境変数が有効なら `opencode` を実行できます。現在の shell で未設定の場合は次を使います:
+
 ```bash
-opencode
+OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true opencode
 ```
 
 次に以下を実行します:
@@ -503,7 +504,6 @@ ping all agents
 | **[Session Management](docs/session-management.md)** | 短いエイリアスで最近の子エージェントセッションを再利用し、最初からやり直さずに済みます |
 | **[Preset Switching](docs/preset-switching.md)** | `/preset` で実行時にエージェントモデルのプリセットを切り替えます |
 | **[Custom Agents](docs/configuration.md#custom-agents)** | カスタムプロンプト、モデル、MCP アクセス、Orchestrator の委譲ルールを備えた独自の専門エージェントを定義します |
-| **[Subtask](docs/subtask.md)** | `/subtask` で境界が明確な子ワーカーを実行し、構造化された要約をメインセッションに返します |
 | **[Codemap](docs/codemap.md)** | 階層的なコードマップを生成し、大規模コードベースを迅速に理解します |
 | **[Clonedeps](docs/clonedeps.md)** | 選択した依存関係のソースを ignore 済みのローカルワークスペースにクローンし、調査できるようにします |
 | **[Interview](docs/interview.md)** | ブラウザベースの Q&A フローで、ざっくりとしたアイデアを構造化された Markdown 仕様に変換します |

+ 29 - 14
README.md

@@ -2,8 +2,8 @@
   <a href="https://github.com/alvinunreal/oh-my-opencode-slim/stargazers">
     <img src="img/4k.png" alt="4K GitHub Stars Milestone" style="border-radius: 10px;">
   </a>
-  <h3>✨ V2 Beta Release: Background Orchestration Has Arrived ✨</h3>
-  <p><i>The orchestrator now schedules specialist agents in the background,<br>while <code>/deepwork</code> turns big goals into file-backed plans.<br>Beta testers: share your feedback with us on Telegram.</i></p>
+  <h3>✨ Default Background Orchestration Has Arrived ✨</h3>
+  <p><i>The orchestrator now manages the workflow and schedules specialist agents in the background,<br>while <code>/deepwork</code> turns big goals into file-backed plans.<br>Share feedback and questions with us on Telegram.</i></p>
 
   <p><b>Open Multi Agent Suite</b> · Mix any models · Auto delegate tasks</p>
 
@@ -45,22 +45,31 @@ Install and configure oh-my-opencode-slim: https://raw.githubusercontent.com/alv
 bunx oh-my-opencode-slim@latest install
 ```
 
-### V2 Background-Orchestration Beta
+### Default Background Orchestration
 
-V2 changes the orchestrator from the default execution worker into a scheduler:
-it plans work, dispatches specialists as background tasks, receives completion
-events from OpenCode or checks status only when needed, then reconciles results
-before continuing. This requires OpenCode's native background subagent support,
-so beta users must start OpenCode with the experimental flag enabled.
+The orchestrator is now a workflow manager and scheduler, not the main coding
+worker: it plans work, dispatches specialists as background tasks, receives
+completion events from OpenCode or checks status only when needed, then
+reconciles results before continuing. This uses OpenCode's native background
+subagent support, so OpenCode must run with the background-subagents environment
+variable enabled.
 
 ```bash
-bunx oh-my-opencode-slim@beta install
-OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=1 opencode
+bunx oh-my-opencode-slim@latest install --background-subagents=yes
 ```
 
+The installer can set this up for you with
+`--background-subagents=ask|yes|no`. In an interactive TTY, the default is
+`ask`; in non-interactive mode, the default is `no`. Use
+`--background-subagents=yes` to opt in immediately or `--background-subagents=no`
+to skip. If you want the installer to write to a specific shell/profile file,
+add `--background-subagents-target=<path>`. After shell setup, restart your
+terminal or source the updated file before starting `opencode`; for a one-shot
+launch, run `OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true opencode`.
+
 ### Getting Started
 
-The installer generates both OpenAI and OpenCode Go presets, with OpenAI active by default. OpenAI uses `openai/gpt-5.5` for the higher-judgment agents and `openai/gpt-5.4-mini` for the faster scoped agents. To make OpenCode Go active during install, run `bunx oh-my-opencode-slim@latest install --preset=opencode-go` or change the default preset name in `~/.config/opencode/oh-my-opencode-slim.json` after installation.
+The installer generates both OpenAI and OpenCode Go presets, with OpenAI active by default. OpenAI uses `openai/gpt-5.5` for the workflow manager/scheduler and higher-judgment agents, and `openai/gpt-5.4-mini` for faster scoped specialists. To make OpenCode Go active during install, run `bunx oh-my-opencode-slim@latest install --preset=opencode-go` or change the default preset name in `~/.config/opencode/oh-my-opencode-slim.json` after installation.
 
 Then:
 
@@ -79,7 +88,13 @@ Then:
 4. **Update the models you want for each agent**
 
 > [!TIP]
-> It's **recommended** to understand how automatic delegation works. The **[Orchestrator prompt](https://github.com/alvinunreal/oh-my-opencode-slim/blob/master/src/agents/orchestrator.ts#L28)** contains the delegation rules, specialist routing logic, and the thresholds for when the main agent should hand work off to subagents. You can alway delegate manually by calling a subagent via: `@agentName <task>`
+> It's **recommended** to understand how background orchestration works. The **[Orchestrator prompt](https://github.com/alvinunreal/oh-my-opencode-slim/blob/master/src/agents/orchestrator.ts#L28)** contains the scheduler rules, specialist routing logic, and thresholds for when work should be assigned to background agents. You can always delegate manually by calling a subagent via: `@agentName <task>`
+
+### Legacy V1 note
+
+The current `@latest` package is the background-orchestration release. If a
+maintained V1 branch or tag is created later, it will be documented separately as
+historical compatibility guidance rather than part of the default install path.
 
 The default generated configuration includes both `openai` and `opencode-go` presets.
 
@@ -180,7 +195,7 @@ If any agent fails to respond, check your provider authentication and config fil
   </tr>
   <tr>
     <td colspan="2">
-      <b>Model Guidance:</b> Choose your default, strongest all-around coding model. Orchestrator is both the main coding agent and the delegator, so it needs strong implementation ability, good judgment, and reliable instruction-following.
+      <b>Model Guidance:</b> Choose your strongest planning and judgment model. Orchestrator is the workflow manager: it plans, schedules background specialists, reconciles results, and verifies outcomes, so it needs reliable instruction-following and high-level technical judgment more than raw worker throughput.
     </td>
   </tr>
 </table>
@@ -500,7 +515,7 @@ Use this section as a map: start with installation, then jump to features, confi
 | Doc | What it covers |
 |-----|----------------|
 | **[Council](docs/council.md)** | Run multiple models in parallel and synthesize a single answer with `@council` |
-| **[V2 Background Orchestration](docs/v2-background-orchestration.md)** | Scheduler-first orchestrator model built around native background subagents |
+| **[Background Orchestration](docs/v2-background-orchestration.md)** | Scheduler-first orchestrator model built around native background subagents |
 | **[Multiplexer Integration](docs/multiplexer-integration.md)** | Watch agents work live in Tmux or Zellij panes |
 | **[Session Management](docs/session-management.md)** | Reuse recent child-agent sessions with short aliases instead of starting over |
 | **[Preset Switching](docs/preset-switching.md)** | Switch agent model presets at runtime with `/preset` |

+ 14 - 13
README.zh-CN.md

@@ -1,9 +1,6 @@
 <div align="center">
-  <a href="https://github.com/alvinunreal/oh-my-opencode-slim/stargazers">
-    <img src="img/v2beta.webp" alt="V2 Beta Release" style="border-radius: 10px;">
-  </a>
-  <h3>✨ V2 Beta 版本:后台编排已上线 ✨</h3>
-  <p><i>编排者(Orchestrator)现在可在后台调度专家智能体,<br>同时 <code>/deepwork</code> 可以将宏大目标转化为基于文件的具体计划。<br>Beta 测试人员:请在 Telegram 上与我们分享您的反馈。</i></p>
+  <h3>✨ 默认后台编排已上线 ✨</h3>
+  <p><i>编排者(Orchestrator)现在作为工作流管理器在后台调度专家智能体,<br>同时 <code>/deepwork</code> 可以将宏大目标转化为基于文件的具体计划。<br>欢迎在 Telegram 上与我们分享反馈。</i></p>
 
   <p><b>开放式多智能体套件</b> · 混合任意模型 · 自动委派任务</p>
 
@@ -43,16 +40,19 @@ Install and configure oh-my-opencode-slim: https://raw.githubusercontent.com/alv
 bunx oh-my-opencode-slim@latest install
 ```
 
-### V2 后台编排 Beta 版
+> **翻译状态说明:** 英文 README 是最新版本;此中文翻译可能仍有少量旧表述。
 
-V2 将编排者(Orchestrator)从默认的执行工作器转变为调度器:
-它规划工作、将专家作为后台任务分发、轮询其状态,并在继续执行之前核对结果。这需要 OpenCode 原生的后台子智能体支持,因此 Beta 版用户必须在启用实验性标志的情况下启动 OpenCode。
+### 默认后台编排
+
+当前版本将编排者(Orchestrator)从默认的执行工作器转变为调度器:
+它规划工作、将专家作为后台任务分发、按需检查状态,并在继续执行之前核对结果。这需要 OpenCode 原生的后台子智能体支持,因此请使用下方环境变量启动 OpenCode。
 
 ```bash
-bunx oh-my-opencode-slim@beta install
-OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=1 opencode
+bunx oh-my-opencode-slim@latest install --background-subagents=yes
 ```
 
+安装后请重启终端或 source 更新过的 shell 文件,然后再运行 `opencode`;也可以一次性使用 `OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true opencode` 启动。
+
 ### 入门指南
 
 安装程序会同时生成 OpenAI 和 OpenCode Go 的预设(Preset),默认启用 OpenAI 预设。OpenAI 使用 `openai/gpt-5.5` 作为具备高级判断力智能体的模型,并使用 `openai/gpt-5.4-mini` 作为响应更快速、针对具体任务智能体的模型。若要在安装过程中激活 OpenCode Go 预设,请运行 `bunx oh-my-opencode-slim@latest install --preset=opencode-go` 或在安装后修改 `~/.config/opencode/oh-my-opencode-slim.json` 文件中的默认预设名称。
@@ -74,7 +74,7 @@ OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=1 opencode
 4. **为您要分配的每个智能体更新模型配置**
 
 > [!TIP]
-> **强烈建议**了解自动委派(Automatic Delegation)的工作原理。**[编排者提示词 (Orchestrator prompt)](https://github.com/alvinunreal/oh-my-opencode-slim/blob/master/src/agents/orchestrator.ts#L28)** 包含了委派规则、专家路由逻辑,以及主智能体何时将工作转交给子智能体的阈值。您始终可以通过以下方式手动委派任务:`@智能体名称 <任务内容>`
+> **建议**了解后台编排的工作原理。**[编排者提示词 (Orchestrator prompt)](https://github.com/alvinunreal/oh-my-opencode-slim/blob/master/src/agents/orchestrator.ts#L28)** 包含调度规则、专家路由逻辑,以及何时应把工作分配给后台智能体的阈值。您始终可以通过以下方式手动委派任务:`@智能体名称 <任务内容>`
 
 默认生成的配置包含 `openai` 和 `opencode-go` 两个预设:
 
@@ -116,8 +116,10 @@ OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=1 opencode
 
 在完成安装与认证后,请验证所有智能体是否已正确配置并能够响应:
 
+请先确保已重启终端或 source 更新过的 shell 文件。环境变量生效后可运行 `opencode`;如果尚未更新当前 shell,请使用:
+
 ```bash
-opencode
+OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true opencode
 ```
 
 然后运行:
@@ -497,7 +499,6 @@ ping all agents
 | **[会话管理 (docs/session-management.md)](docs/session-management.md)** | 使用短别名复用最近的子智能体会话,而不是重新开始 |
 | **[运行时预设切换 (docs/preset-switching.md)](docs/preset-switching.md)** | 在运行时使用 `/preset` 切换智能体模型预设 |
 | **[自定义智能体 (docs/configuration.md#custom-agents)](docs/configuration.md#custom-agents)** | 自定义专家智能体:配置独特的提示词、模型、MCP 权限和编排者委派规则 |
-| **[子任务 (docs/subtask.md)](docs/subtask.md)** | 使用 `/subtask` 运行受限的子工作器,并将结构化总结返回到主会话 |
 | **[代码地图 (Codemap) (docs/codemap.md)](docs/codemap.md)** | 生成层级代码地图,快速理解大型代码库 |
 | **[克隆依赖 (Clonedeps) (docs/clonedeps.md)](docs/clonedeps.md)** | 将选定的依赖源码克隆到被忽略的本地工作区中以供检查 |
 | **[访谈式生成 (Interview) (docs/interview.md)](docs/interview.md)** | 通过基于浏览器的问答流,将粗糙的想法转变为结构化的 Markdown 规范文档 |

+ 2 - 1
docs/configuration.md

@@ -148,7 +148,8 @@ Presets can also be switched at runtime without restarting using the `/preset` c
   `presets.<name>.council.model`.
 - The **councillor models** are configured separately under
   `council.presets.<name>.<councillor>.model`.
-- Deprecated `council.master*` fields should not be used in new configs.
+- Deprecated `council.master*` fields are legacy compatibility aliases only;
+  do not use them in new configs.
 
 ### Manual Update Mode
 

+ 83 - 4
docs/installation.md

@@ -24,7 +24,7 @@ bunx oh-my-opencode-slim@latest install
 Or use non-interactive mode:
 
 ```bash
-bunx oh-my-opencode-slim@latest install --no-tui --skills=yes
+bunx oh-my-opencode-slim@latest install --no-tui --skills=yes --background-subagents=yes
 ```
 
 ### Configuration Options
@@ -38,6 +38,50 @@ The installer supports the following options:
 | `--no-tui` | Non-interactive mode |
 | `--dry-run` | Simulate install without writing files |
 | `--reset` | Force overwrite of existing configuration |
+| `--background-subagents=ask\|yes\|no` | Configure `OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true` in your shell startup file (`ask` by default only in an interactive TTY; otherwise `no`) |
+| `--background-subagents-target=<path>` | Write the background-subagents export to a specific shell/profile file |
+
+### Background Subagents Environment Setup
+
+Background orchestration is the default workflow. It depends on OpenCode's native
+background subagents, which are enabled by this environment variable:
+
+```bash
+OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true
+```
+
+The installer can add that export to your shell startup file. Use one of:
+
+```bash
+# Ask before editing a shell startup file (default in interactive TTY only)
+bunx oh-my-opencode-slim@latest install --background-subagents=ask
+
+# Always configure the export when possible
+bunx oh-my-opencode-slim@latest install --background-subagents=yes
+
+# Do not modify shell startup files
+bunx oh-my-opencode-slim@latest install --background-subagents=no
+
+# Write to an explicit target file
+bunx oh-my-opencode-slim@latest install \
+  --background-subagents=yes \
+  --background-subagents-target="$HOME/.zshrc"
+```
+
+After the installer updates a shell startup file, restart your terminal or source
+the file before launching OpenCode. Examples:
+
+```bash
+source ~/.zshrc
+# or
+source ~/.bashrc
+```
+
+For a one-shot manual launch without changing shell files:
+
+```bash
+OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true opencode
+```
 
 ### Non-Destructive Behavior
 
@@ -109,7 +153,7 @@ If not installed, direct the user to https://opencode.ai/docs first.
 The installer generates OpenAI and OpenCode Go presets, with OpenAI active by default:
 
 ```bash
-bunx oh-my-opencode-slim@latest install --no-tui --skills=yes
+bunx oh-my-opencode-slim@latest install --no-tui --skills=yes --background-subagents=yes
 ```
 
 **Examples:**
@@ -118,7 +162,10 @@ bunx oh-my-opencode-slim@latest install --no-tui --skills=yes
 bunx oh-my-opencode-slim@latest install
 
 # Non-interactive with bundled skills
-bunx oh-my-opencode-slim@latest install --no-tui --skills=yes
+bunx oh-my-opencode-slim@latest install --no-tui --skills=yes --background-subagents=yes
+
+# Non-interactive and configure background subagents env setup
+bunx oh-my-opencode-slim@latest install --no-tui --background-subagents=yes
 
 # Make the generated OpenCode Go preset active
 bunx oh-my-opencode-slim@latest install --preset=opencode-go
@@ -134,6 +181,7 @@ The installer automatically:
 - Adds the plugin to `~/.config/opencode/opencode.json`
 - Disables default OpenCode agents
 - Enables OpenCode LSP integration when no explicit `lsp` setting exists
+- Configures `OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true` when approved
 - Generates agent model mappings in `~/.config/opencode/oh-my-opencode-slim.json` (or `.jsonc`)
 
 ### Step 3: Authenticate with Providers
@@ -151,7 +199,9 @@ Ask the user to:
 
 1. Authenticate: `opencode auth login`
 2. Refresh models: `opencode models --refresh`
-3. Start OpenCode: `opencode`
+3. Restart the terminal or source the shell file updated by the installer
+   (`source ~/.zshrc` or `source ~/.bashrc`), then start OpenCode: `opencode`
+   - One-shot alternative: `OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true opencode`
 4. Run: `ping all agents`
 
 Verify all agents respond successfully.
@@ -201,6 +251,35 @@ If the installer reports that the configuration already exists, you have two opt
 
 3. Check that your provider is configured in `~/.config/opencode/opencode.json`
 
+### Missing `task_status` or Background Task Tools
+
+If the orchestrator says `task_status` is unavailable, background tasks never
+return task IDs, or delegation behaves like a blocking foreground call:
+
+1. Confirm OpenCode was launched with the environment variable:
+   ```bash
+   env | grep OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS
+   ```
+   It should show `OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true`.
+
+   Also use an OpenCode release that includes native background
+   subagents/task_status; run `opencode --version` and update OpenCode if
+   `task_status` is missing.
+
+2. Restart your terminal or source the shell file the installer updated, then
+   start OpenCode again. Plain `opencode` is only sufficient after that
+   environment is active.
+
+3. For a quick manual test, launch OpenCode with a one-shot export:
+   ```bash
+   OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true opencode
+   ```
+
+4. If you intentionally skipped shell setup, rerun the installer with:
+   ```bash
+   bunx oh-my-opencode-slim@latest install --background-subagents=yes
+   ```
+
 ### Authentication Issues
 
 If providers are not working:

+ 1 - 1
docs/quick-reference.md

@@ -13,7 +13,7 @@
 | Doc | Contents |
 |-----|----------|
 | [Council Agent](council.md) | Multi-LLM consensus, presets, role prompts, timeouts |
-| [V2 Background Orchestration](v2-background-orchestration.md) | Scheduler-first orchestrator model for native background subagents |
+| [Background Orchestration](v2-background-orchestration.md) | Default scheduler-first orchestrator model for native background subagents |
 | [Interview](interview.md) | `/interview` command, browser UI, dashboard mode, multi-session coordination |
 | [Multiplexer Integration](multiplexer-integration.md) | Real-time pane monitoring, layouts, troubleshooting |
 | [Preset Switching](preset-switching.md) | `/preset` command for runtime agent model switching |

+ 33 - 38
docs/v2-background-orchestration.md

@@ -1,8 +1,8 @@
-# V2 Background Orchestration
+# Background Orchestration
 
-V2 is the next orchestration model for oh-my-opencode-slim. It assumes native
-OpenCode background subagents are available and changes the orchestrator from a
-primary worker into a scheduler.
+Background orchestration is the default orchestration model for
+oh-my-opencode-slim. It assumes native OpenCode background subagents are
+available and changes the orchestrator from a primary worker into a scheduler.
 
 The old model was:
 
@@ -10,7 +10,7 @@ The old model was:
 orchestrator works directly → delegates when useful → waits for result
 ```
 
-The V2 model is:
+The default background-orchestration model is:
 
 ```text
 orchestrator plans → dispatches background specialists → monitors → reconciles → verifies
@@ -22,7 +22,9 @@ This is a clean rebuild, not a compatibility layer over the old blocking model.
 
 ## Runtime Requirement
 
-V2 requires OpenCode with native background subagents enabled:
+Background orchestration requires an OpenCode release that includes native
+background subagents and `task_status`, launched with background subagents
+enabled:
 
 ```bash
 OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true opencode
@@ -36,8 +38,12 @@ The required native/background-control tools are:
 | `task_status` | Poll or wait for a background task result when needed |
 | `cancel_task` | Plugin-provided tool to cancel a tracked background task by task ID or Background Job Board alias |
 
-If these are not available, V2 should fail loudly instead of falling back to the
-legacy blocking orchestration model.
+If these are not available, the scheduler cannot use the default background
+workflow. Configure the environment variable through the installer or use the
+one-shot export above before starting OpenCode.
+
+Use an OpenCode release that includes native background subagents/task_status;
+run `opencode --version` and update if `task_status` is missing.
 
 ---
 
@@ -180,7 +186,7 @@ and reconciled.
 
 ---
 
-## Specialist Roles In V2
+## Specialist Roles
 
 ### Explorer
 
@@ -220,7 +226,7 @@ Visual/media analysis isolated from the orchestrator context.
 
 ## Direct Work Boundary
 
-V2 removes the orchestrator-as-worker default.
+Background orchestration removes the orchestrator-as-worker default.
 
 The orchestrator may directly:
 
@@ -282,7 +288,7 @@ Look into background tasks.
 
 ## State The Orchestrator Must Track
 
-V2 prompt/runtime should treat background tasks as a small job board:
+The prompt/runtime treats background tasks as a small job board:
 
 | Field | Meaning |
 |-------|---------|
@@ -299,45 +305,34 @@ ownership need to be explicit in the orchestrator's working context.
 
 ---
 
-## Plugin Changes Needed
-
-V2 is more than a prompt rewrite. The plugin should become aware that a task
-tool return can mean "background job launched" rather than "work complete".
+## Runtime Integration
 
-Important areas:
-
-- `src/agents/orchestrator.ts` — replace blocking delegation language with the
-  scheduler contract.
-- `src/config/constants.ts` — update phase reminders so they reinforce scheduler
-  behavior instead of old delegation behavior.
-- `src/hooks/task-session-manager/` — track running background task IDs and
-  update aliases from `task_status` results.
-- `src/index.ts` task hooks — separate "task launched" from "task finished" for
-  notifications, Divoom, multiplexer, and cleanup behavior.
-- `src/multiplexer/` — verify panes stay attached to running background child
-  sessions while the parent continues.
+The plugin is aware that a `task` return can mean "background job launched"
+rather than "work complete". It tracks running task IDs, exposes recent work in
+the background job board, updates aliases from `task_status` results, and keeps
+multiplexer panes attached while the parent orchestrator continues scheduling.
 
 ---
 
-## V2 Startup Behavior
-
-V2 should be strict.
+## Startup Behavior
 
-If background subagents are unavailable, the plugin should not silently behave
-like V1. It should tell the user exactly what is missing:
+The installer and docs configure background subagents as a requirement for the
+default scheduler workflow. If background subagents or `task_status` are
+unavailable, treat it as an environment or OpenCode-version issue rather than an
+intentional V1 fallback:
 
 ```text
-V2 orchestration requires OpenCode background subagents.
+Background orchestration requires OpenCode background subagents.
 Start OpenCode with:
 
 OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true opencode
 ```
 
-No legacy fallback keeps the mental model clean.
+No automatic legacy fallback keeps the mental model clean.
 
 ---
 
-## Example V2 Flow
+## Example Flow
 
 User asks:
 
@@ -365,7 +360,7 @@ At no point does the orchestrator become the main implementer.
 
 ## Success Criteria
 
-V2 is working when:
+Background orchestration is working when:
 
 - the orchestrator launches independent specialists in background by default,
 - task IDs are tracked until terminal state,
@@ -375,5 +370,5 @@ V2 is working when:
 - users see faster progress on multi-step work,
 - the orchestrator context stays focused on decisions instead of worker detail.
 
-V2 is not just "parallel agents." It is a scheduler-centered operating model for
-OpenCode's native background subagents.
+Background orchestration is not just "parallel agents." It is a
+scheduler-centered operating model for OpenCode's native background subagents.

+ 10 - 5
docs/v2-workstreams.md

@@ -1,12 +1,17 @@
-# V2 Workstreams
+# Internal: V2 Workstreams Archive
 
-Track focused V2 branches and local worktrees here. `v2-beta` is the central
-integration branch: merge reviewed V2 work there, test the combined V2 state
-there, and publish npm `beta` releases from there.
+> **Internal historical planning doc.** This file tracked V2 feature branches
+> and beta integration while background orchestration was being built. It is not
+> current user-facing install or release guidance. For the default release, see
+> [Installation](installation.md) and
+> [Background Orchestration](v2-background-orchestration.md).
+
+This archive tracked focused V2 branches and local worktrees while background
+orchestration was being built. It is not current release guidance.
 
 | Branch | Worktree | Purpose | Status | Notes |
 |---|---|---|---|---|
-| `v2-beta` | repo root | V2 integration/release | Active | Source of truth for combined V2 testing and `@beta` publishes. |
+| `v2-beta` | repo root | V2 integration/release | Historical | Former source of truth for combined V2 pre-release validation. |
 | `v2/misc` | `.slim/worktrees/v2-misc` | Misc V2 cleanup | Merged | Removed custom subtask feature; can continue misc follow-ups here if desired. |
 | `v2/tui` | `.slim/worktrees/v2-tui` | TUI integration | Planned | No feature work merged yet. |
 

+ 9 - 2
docs/v2_core.md

@@ -1,6 +1,13 @@
-# V2 Core Refactor Plan
+# Internal: V2 Core Refactor Plan
 
-This document is the implementation plan for the V2 orchestration core.
+> **Internal historical planning doc.** This file records the V2 implementation
+> plan that led to the current default background-orchestration release. It is
+> not the beta user guide and may mention branch or rollout details that are now
+> historical. For user-facing setup, see [Installation](installation.md) and
+> [Background Orchestration](v2-background-orchestration.md).
+
+This archival document records the implementation plan for the V2 orchestration
+core. It is retained for maintainers who need the design history.
 
 Scope for this pass:
 

+ 235 - 0
src/cli/background-subagents.test.ts

@@ -0,0 +1,235 @@
+/// <reference types="bun-types" />
+
+import { afterEach, describe, expect, spyOn, test } from 'bun:test';
+import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
+import { tmpdir } from 'node:os';
+import { join } from 'node:path';
+import {
+  detectBackgroundSubagentsTarget,
+  detectShellKind,
+  expandHomePath,
+  getBackgroundSubagentsBlock,
+  isBackgroundSubagentsEnabled,
+  manualBackgroundSubagentsInstructions,
+  upsertBackgroundSubagentsBlock,
+  writeBackgroundSubagentsBlock,
+} from './background-subagents';
+import { parseArgs } from './index';
+import {
+  configureBackgroundSubagents,
+  shouldPromptForBackgroundSubagents,
+} from './install';
+
+describe('background subagents helpers', () => {
+  test('detects true-like environment values', () => {
+    expect(isBackgroundSubagentsEnabled('true')).toBe(true);
+    expect(isBackgroundSubagentsEnabled('1')).toBe(true);
+    expect(isBackgroundSubagentsEnabled('yes')).toBe(true);
+    expect(isBackgroundSubagentsEnabled('false')).toBe(false);
+    expect(isBackgroundSubagentsEnabled('0')).toBe(false);
+    expect(isBackgroundSubagentsEnabled(undefined)).toBe(false);
+  });
+
+  test('detects supported shell kinds', () => {
+    expect(detectShellKind('/bin/zsh')).toBe('zsh');
+    expect(detectShellKind('/usr/local/bin/bash')).toBe('bash');
+    expect(detectShellKind('/opt/homebrew/bin/fish')).toBe('fish');
+    expect(detectShellKind('/bin/sh')).toBeUndefined();
+  });
+
+  test('detects shell startup targets including fish XDG config', () => {
+    expect(
+      detectBackgroundSubagentsTarget({ SHELL: '/bin/zsh' })?.endsWith(
+        '/.zshrc',
+      ),
+    ).toBe(true);
+    expect(
+      detectBackgroundSubagentsTarget({ SHELL: '/bin/bash' })?.endsWith(
+        '/.bashrc',
+      ),
+    ).toBe(true);
+    expect(
+      detectBackgroundSubagentsTarget({
+        SHELL: '/usr/bin/fish',
+        XDG_CONFIG_HOME: '/tmp/xdg',
+      }),
+    ).toBe('/tmp/xdg/fish/conf.d/opencode-background-subagents.fish');
+  });
+
+  test('builds shell-specific managed blocks with true', () => {
+    expect(getBackgroundSubagentsBlock('/tmp/.bashrc')).toContain(
+      'export OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true',
+    );
+    expect(getBackgroundSubagentsBlock('/tmp/config.fish')).toContain(
+      'set -gx OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS true',
+    );
+  });
+
+  test('prints fish manual instructions for fish targets', () => {
+    const instructions = manualBackgroundSubagentsInstructions({
+      targetPath: '/tmp/config.fish',
+    });
+
+    expect(instructions).toContain(
+      'set -gx OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS true',
+    );
+    expect(instructions).toContain(
+      'env OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true opencode',
+    );
+  });
+
+  test('expands tilde target paths', () => {
+    expect(expandHomePath('~')).not.toBe('~');
+    expect(expandHomePath('~/profile')).not.toContain('~');
+    expect(expandHomePath('/tmp/profile')).toBe('/tmp/profile');
+  });
+
+  test('upserts the managed block idempotently', () => {
+    const first = upsertBackgroundSubagentsBlock('before\n', 'BLOCK');
+    const second = upsertBackgroundSubagentsBlock(
+      first,
+      getBackgroundSubagentsBlock('/tmp/.zshrc'),
+    );
+    const third = upsertBackgroundSubagentsBlock(
+      second,
+      getBackgroundSubagentsBlock('/tmp/.zshrc'),
+    );
+
+    expect(third).toBe(second);
+    expect(
+      third.match(/OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS/g),
+    ).toHaveLength(1);
+  });
+});
+
+describe('background subagents writing', () => {
+  let tempDir: string | undefined;
+
+  afterEach(() => {
+    if (tempDir) rmSync(tempDir, { recursive: true, force: true });
+    tempDir = undefined;
+  });
+
+  test('writes managed block without duplicates', () => {
+    tempDir = mkdtempSync(join(tmpdir(), 'omoo-bg-'));
+    const target = join(tempDir, '.bashrc');
+    writeFileSync(target, 'existing=true\n');
+
+    writeBackgroundSubagentsBlock(target);
+    writeBackgroundSubagentsBlock(target);
+
+    const content = readFileSync(target, 'utf8');
+    expect(content).toContain('existing=true');
+    expect(
+      content.match(/OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS/g),
+    ).toHaveLength(1);
+  });
+});
+
+describe('parseArgs background subagents', () => {
+  test('parses mode and target override', () => {
+    expect(
+      parseArgs([
+        '--background-subagents=yes',
+        '--background-subagents-target=/tmp/profile',
+      ]),
+    ).toMatchObject({
+      backgroundSubagents: 'yes',
+      backgroundSubagentsTarget: '/tmp/profile',
+    });
+  });
+
+  test('--no-tui defaults background subagents to no', () => {
+    expect(parseArgs(['--no-tui']).backgroundSubagents).toBe('no');
+  });
+});
+
+describe('configureBackgroundSubagents', () => {
+  let tempDir: string | undefined;
+  const originalBackgroundEnv =
+    process.env.OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS;
+
+  afterEach(() => {
+    if (tempDir) rmSync(tempDir, { recursive: true, force: true });
+    tempDir = undefined;
+    if (originalBackgroundEnv === undefined) {
+      delete process.env.OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS;
+    } else {
+      process.env.OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS =
+        originalBackgroundEnv;
+    }
+  });
+
+  test('does not prompt for ask mode when noninteractive', async () => {
+    tempDir = mkdtempSync(join(tmpdir(), 'omoo-bg-'));
+    delete process.env.OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS;
+    const target = join(tempDir, '.bashrc');
+    const log = spyOn(console, 'log').mockImplementation(() => undefined);
+    const originalIsTty = process.stdin.isTTY;
+    Object.defineProperty(process.stdin, 'isTTY', {
+      configurable: true,
+      value: false,
+    });
+
+    try {
+      expect(
+        shouldPromptForBackgroundSubagents({
+          hasTmux: false,
+          installCustomSkills: false,
+          promptForStar: false,
+          reset: false,
+          backgroundSubagents: 'ask',
+          backgroundSubagentsTarget: target,
+        }),
+      ).toBe(false);
+
+      const result = await configureBackgroundSubagents({
+        hasTmux: false,
+        installCustomSkills: false,
+        promptForStar: false,
+        reset: false,
+        backgroundSubagents: 'ask',
+        backgroundSubagentsTarget: target,
+      });
+
+      expect(result).toEqual({ enabledNow: false });
+      expect(log.mock.calls.join('\n')).toContain(
+        'Skipped background subagents shell configuration.',
+      );
+    } finally {
+      Object.defineProperty(process.stdin, 'isTTY', {
+        configurable: true,
+        value: originalIsTty,
+      });
+      log.mockRestore();
+    }
+  });
+
+  test('returns no configured target when writing shell config fails', async () => {
+    tempDir = mkdtempSync(join(tmpdir(), 'omoo-bg-'));
+    delete process.env.OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS;
+    const blockingFile = join(tempDir, 'not-a-directory');
+    writeFileSync(blockingFile, 'already a file');
+    const target = join(blockingFile, '.bashrc');
+    const log = spyOn(console, 'log').mockImplementation(() => undefined);
+
+    try {
+      const result = await configureBackgroundSubagents({
+        hasTmux: false,
+        installCustomSkills: false,
+        promptForStar: false,
+        reset: false,
+        backgroundSubagents: 'yes',
+        backgroundSubagentsTarget: target,
+      });
+
+      expect(result).toEqual({ enabledNow: false });
+      expect(log.mock.calls.join('\n')).toContain(
+        'Could not write background subagents shell config:',
+      );
+      expect(log.mock.calls.join('\n')).toContain('Add the setting manually');
+    } finally {
+      log.mockRestore();
+    }
+  });
+});

+ 109 - 0
src/cli/background-subagents.ts

@@ -0,0 +1,109 @@
+import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
+import { homedir } from 'node:os';
+import { dirname, join } from 'node:path';
+
+export type BackgroundSubagentsMode = 'ask' | 'yes' | 'no';
+export type ShellKind = 'bash' | 'fish' | 'zsh';
+
+const ENV_NAME = 'OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS';
+const START_MARKER = '# >>> oh-my-opencode-slim background subagents >>>';
+const END_MARKER = '# <<< oh-my-opencode-slim background subagents <<<';
+
+export function isBackgroundSubagentsEnabled(
+  value: string | undefined,
+): boolean {
+  if (!value) return false;
+  const normalized = value.trim().toLowerCase();
+  return normalized !== '' && !['0', 'false', 'no', 'off'].includes(normalized);
+}
+
+export function detectShellKind(
+  shell: string | undefined,
+): ShellKind | undefined {
+  const name = shell?.split('/').at(-1);
+  if (name === 'zsh' || name === 'bash' || name === 'fish') return name;
+  return undefined;
+}
+
+export function detectBackgroundSubagentsTarget(
+  env: NodeJS.ProcessEnv = process.env,
+): string | undefined {
+  const shell = detectShellKind(env.SHELL);
+  if (shell === 'zsh') return join(homedir(), '.zshrc');
+  if (shell === 'bash') return join(homedir(), '.bashrc');
+  if (shell === 'fish') {
+    const configHome = env.XDG_CONFIG_HOME || join(homedir(), '.config');
+    return join(
+      configHome,
+      'fish',
+      'conf.d',
+      'opencode-background-subagents.fish',
+    );
+  }
+  return undefined;
+}
+
+export function getBackgroundSubagentsBlock(targetPath: string): string {
+  const isFish = targetPath.endsWith('.fish');
+  const command = isFish
+    ? `set -gx ${ENV_NAME} true`
+    : `export ${ENV_NAME}=true`;
+
+  return `${START_MARKER}\n${command}\n${END_MARKER}`;
+}
+
+export function manualBackgroundSubagentsInstructions(options?: {
+  targetPath?: string;
+  shell?: ShellKind;
+}): string {
+  const shell =
+    options?.shell ??
+    (options?.targetPath?.endsWith('.fish') ? 'fish' : undefined) ??
+    detectShellKind(options?.targetPath);
+  const bashZshSnippet = `export ${ENV_NAME}=true`;
+  const fishSnippet = `set -gx ${ENV_NAME} true`;
+
+  if (shell === 'fish') {
+    return `Start OpenCode with background subagents enabled:\n  env ${ENV_NAME}=true opencode\n\nOr add this to your fish startup file:\n  ${fishSnippet}`;
+  }
+
+  if (shell === 'bash' || shell === 'zsh') {
+    return `Start OpenCode with background subagents enabled:\n  ${ENV_NAME}=true opencode\n\nOr add this to your shell startup file:\n  ${bashZshSnippet}`;
+  }
+
+  return `Start OpenCode with background subagents enabled:\n  ${ENV_NAME}=true opencode\n\nOr add one of these to your shell startup file:\n  bash/zsh: ${bashZshSnippet}\n  fish: ${fishSnippet}`;
+}
+
+export function expandHomePath(targetPath: string): string {
+  if (targetPath === '~') return homedir();
+  if (targetPath.startsWith('~/')) return join(homedir(), targetPath.slice(2));
+  return targetPath;
+}
+
+export function upsertBackgroundSubagentsBlock(
+  content: string,
+  block: string,
+): string {
+  const start = content.indexOf(START_MARKER);
+  const end = content.indexOf(END_MARKER);
+
+  if (start !== -1 && end !== -1 && end > start) {
+    const afterEnd = end + END_MARKER.length;
+    return `${content.slice(0, start)}${block}${content.slice(afterEnd)}`;
+  }
+
+  const separator = content.length > 0 && !content.endsWith('\n') ? '\n\n' : '';
+  const prefix =
+    content.length > 0 && content.endsWith('\n') ? '\n' : separator;
+  return `${content}${prefix}${block}\n`;
+}
+
+export function writeBackgroundSubagentsBlock(targetPath: string): void {
+  const block = getBackgroundSubagentsBlock(targetPath);
+  const content = existsSync(targetPath)
+    ? readFileSync(targetPath, 'utf8')
+    : '';
+  const nextContent = upsertBackgroundSubagentsBlock(content, block);
+  mkdirSync(dirname(targetPath), { recursive: true });
+  writeFileSync(targetPath, nextContent);
+}

+ 28 - 6
src/cli/index.ts

@@ -2,9 +2,9 @@
 import { doctor, parseDoctorArgs } from './doctor';
 import { install } from './install';
 import { getGeneratedPresetNames, isGeneratedPresetName } from './providers';
-import type { BooleanArg, InstallArgs } from './types';
+import type { BackgroundSubagentsArg, BooleanArg, InstallArgs } from './types';
 
-function parseArgs(args: string[]): InstallArgs {
+export function parseArgs(args: string[]): InstallArgs {
   const result: InstallArgs = {
     tui: true,
     skills: 'yes',
@@ -24,6 +24,17 @@ function parseArgs(args: string[]): InstallArgs {
         process.exit(1);
       }
       result.preset = preset;
+    } else if (arg.startsWith('--background-subagents=')) {
+      const mode = arg.split('=')[1] as BackgroundSubagentsArg;
+      if (!['ask', 'yes', 'no'].includes(mode)) {
+        console.error(
+          'Unsupported --background-subagents value: use ask, yes, or no',
+        );
+        process.exit(1);
+      }
+      result.backgroundSubagents = mode;
+    } else if (arg.startsWith('--background-subagents-target=')) {
+      result.backgroundSubagentsTarget = arg.split('=')[1];
     } else if (arg === '--dry-run') {
       result.dryRun = true;
     } else if (arg === '--reset') {
@@ -34,6 +45,9 @@ function parseArgs(args: string[]): InstallArgs {
     }
   }
 
+  result.backgroundSubagents ??=
+    result.tui && process.stdin.isTTY ? 'ask' : 'no';
+
   return result;
 }
 
@@ -48,6 +62,11 @@ Usage:
 Options:
   --skills=yes|no        Install bundled skills (default: yes)
   --preset=<name>        Active generated config preset (default: openai)
+  --background-subagents=ask|yes|no
+                         Persist required OpenCode background subagent env
+                         (default: ask in interactive TTY, otherwise no)
+  --background-subagents-target=<path>
+                         Shell startup file to update
   --no-tui               Non-interactive mode
   --dry-run              Simulate install without writing files
   --reset                Force overwrite of existing configuration
@@ -65,6 +84,7 @@ For the full config reference, see docs/configuration.md.
 Examples:
   bunx oh-my-opencode-slim install
   bunx oh-my-opencode-slim install --no-tui --skills=yes
+  bunx oh-my-opencode-slim install --background-subagents=yes
   bunx oh-my-opencode-slim install --preset=opencode-go
   bunx oh-my-opencode-slim install --reset
   bunx oh-my-opencode-slim doctor
@@ -93,7 +113,9 @@ async function main(): Promise<void> {
   }
 }
 
-main().catch((err) => {
-  console.error('Fatal error:', err);
-  process.exit(1);
-});
+if (import.meta.main) {
+  main().catch((err) => {
+    console.error('Fatal error:', err);
+    process.exit(1);
+  });
+}

+ 115 - 2
src/cli/install.ts

@@ -1,5 +1,13 @@
 import { existsSync } from 'node:fs';
 import { createInterface } from 'node:readline/promises';
+import {
+  detectBackgroundSubagentsTarget,
+  expandHomePath,
+  getBackgroundSubagentsBlock,
+  isBackgroundSubagentsEnabled,
+  manualBackgroundSubagentsInstructions,
+  writeBackgroundSubagentsBlock,
+} from './background-subagents';
 import {
   addPluginToOpenCodeConfig,
   addPluginToOpenCodeTuiConfig,
@@ -130,6 +138,92 @@ async function checkOpenCodeInstalled(): Promise<{
   return { ok: true, version: version ?? undefined, path: path ?? undefined };
 }
 
+export function shouldPromptForBackgroundSubagents(
+  config: InstallConfig,
+): boolean {
+  return Boolean(config.promptForStar && process.stdin.isTTY);
+}
+
+export async function configureBackgroundSubagents(
+  config: InstallConfig,
+): Promise<{ enabledNow: boolean; configuredTarget?: string }> {
+  if (
+    isBackgroundSubagentsEnabled(
+      process.env.OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS,
+    )
+  ) {
+    printSuccess(
+      'OpenCode background subagents already enabled in environment',
+    );
+    return { enabledNow: true };
+  }
+
+  const target =
+    config.backgroundSubagentsTarget !== undefined
+      ? expandHomePath(config.backgroundSubagentsTarget)
+      : detectBackgroundSubagentsTarget();
+
+  if (config.backgroundSubagents === 'no') {
+    printInfo('OpenCode background subagents are not enabled.');
+    console.log(manualBackgroundSubagentsInstructions({ targetPath: target }));
+    return { enabledNow: false };
+  }
+
+  if (!target) {
+    printInfo('No safe shell startup file detected.');
+    console.log(manualBackgroundSubagentsInstructions());
+    return { enabledNow: false };
+  }
+
+  const block = getBackgroundSubagentsBlock(target);
+
+  if (config.dryRun) {
+    printInfo(
+      'Dry run mode - background subagents block that would be written:',
+    );
+    console.log(`Target: ${target}`);
+    console.log(`\n${block}\n`);
+    return { enabledNow: false, configuredTarget: target };
+  }
+
+  if (config.backgroundSubagents === 'ask') {
+    if (!shouldPromptForBackgroundSubagents(config)) {
+      printInfo('Skipped background subagents shell configuration.');
+      console.log(
+        manualBackgroundSubagentsInstructions({ targetPath: target }),
+      );
+      return { enabledNow: false };
+    }
+
+    const shouldWrite = await confirm(
+      `Enable OpenCode background subagents in ${target}?`,
+      true,
+    );
+    if (!shouldWrite) {
+      printInfo('Skipped background subagents shell configuration.');
+      console.log(
+        manualBackgroundSubagentsInstructions({ targetPath: target }),
+      );
+      return { enabledNow: false };
+    }
+  }
+
+  try {
+    writeBackgroundSubagentsBlock(target);
+  } catch (error) {
+    const message = error instanceof Error ? error.message : String(error);
+    printError(`Could not write background subagents shell config: ${message}`);
+    printInfo('Add the setting manually instead:');
+    console.log(manualBackgroundSubagentsInstructions({ targetPath: target }));
+    return { enabledNow: false };
+  }
+
+  printSuccess(
+    `Background subagents enabled ${SYMBOLS.arrow} ${DIM}${target}${RESET}`,
+  );
+  return { enabledNow: false, configuredTarget: target };
+}
+
 function handleStepResult(
   result: ConfigMergeResult,
   successMsg: string,
@@ -150,7 +244,7 @@ async function runInstall(config: InstallConfig): Promise<number> {
 
   printHeader(isUpdate);
 
-  let totalSteps = 6;
+  let totalSteps = 7;
   if (config.installCustomSkills) totalSteps += 1;
   totalSteps += 1;
 
@@ -213,6 +307,9 @@ async function runInstall(config: InstallConfig): Promise<number> {
     if (!handleStepResult(lspResult, 'LSP enabled')) return 1;
   }
 
+  printStep(step++, totalSteps, 'Configuring OpenCode background subagents...');
+  const backgroundSubagents = await configureBackgroundSubagents(config);
+
   printStep(step++, totalSteps, 'Writing oh-my-opencode-slim configuration...');
   if (config.dryRun) {
     const liteConfig = generateLiteConfig(config);
@@ -288,7 +385,21 @@ async function runInstall(config: InstallConfig): Promise<number> {
   console.log(`     ${BLUE}${configPath}${RESET}`);
   console.log();
   console.log('  4. Start OpenCode:');
-  console.log(`     ${BLUE}$ opencode${RESET}`);
+  if (backgroundSubagents.enabledNow) {
+    console.log(`     ${BLUE}$ opencode${RESET}`);
+  } else if (backgroundSubagents.configuredTarget) {
+    console.log(
+      `     ${BLUE}$ source ${backgroundSubagents.configuredTarget}${RESET}`,
+    );
+    console.log(`     ${BLUE}$ opencode${RESET}`);
+    console.log(
+      `     ${DIM}Or restart your terminal before running opencode.${RESET}`,
+    );
+  } else {
+    console.log(
+      `     ${BLUE}$ OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true opencode${RESET}`,
+    );
+  }
   console.log();
   console.log('  5. Verify the agents are responding:');
   console.log(`     ${BLUE}> ping all agents${RESET}`);
@@ -320,6 +431,8 @@ export async function install(args: InstallArgs): Promise<number> {
     promptForStar: args.tui,
     dryRun: args.dryRun,
     reset: args.reset ?? false,
+    backgroundSubagents: args.backgroundSubagents ?? 'no',
+    backgroundSubagentsTarget: args.backgroundSubagentsTarget,
   };
 
   return runInstall(config);

+ 5 - 0
src/cli/types.ts

@@ -1,4 +1,5 @@
 export type BooleanArg = 'yes' | 'no';
+export type BackgroundSubagentsArg = 'ask' | 'yes' | 'no';
 
 export interface InstallArgs {
   tui: boolean;
@@ -6,6 +7,8 @@ export interface InstallArgs {
   preset?: string;
   dryRun?: boolean;
   reset?: boolean;
+  backgroundSubagents?: BackgroundSubagentsArg;
+  backgroundSubagentsTarget?: string;
 }
 
 export interface OpenCodeConfig {
@@ -22,6 +25,8 @@ export interface InstallConfig {
   promptForStar?: boolean;
   dryRun?: boolean;
   reset: boolean;
+  backgroundSubagents: BackgroundSubagentsArg;
+  backgroundSubagentsTarget?: string;
 }
 
 export interface ConfigMergeResult {