# opencode-copilot-account-switcher

[![npm version](https://img.shields.io/npm/v/opencode-copilot-account-switcher.svg)](https://www.npmjs.com/package/opencode-copilot-account-switcher)
[![npm downloads](https://img.shields.io/npm/dw/opencode-copilot-account-switcher.svg)](https://www.npmjs.com/package/opencode-copilot-account-switcher)
[![License: MPL-2.0](https://img.shields.io/badge/License-MPL--2.0-brightgreen.svg)](LICENSE)
[![GitHub stars](https://img.shields.io/github/stars/jiwangyihao/opencode-copilot-account-switcher?style=social)](https://github.com/jiwangyihao/opencode-copilot-account-switcher/stargazers)

套件导航 / Suite: [OpenCode J Super Suite](https://github.com/jiwangyihao/opencode-j-super-suite)

> **Latest in v1.0.0 | v1.0.0 最近更新**
>
> - Stable Copilot-only release for account switching, quota, routing, and Copilot request enhancements | 面向账号切换、配额、routing 与 Copilot 请求增强的稳定版
> - Migration guidance for extracted plugins lives in the v1.0.0 Release Notes | 已拆分插件的迁移说明集中放在 v1.0.0 Release Notes
> - README now focuses on install, usage, and Copilot-specific optional switches | README 聚焦安装、使用和 Copilot 专属可选开关

[中文](#中文) | [English](#english)

---

<a name="中文"></a>

## 中文

在 **OpenCode** 中管理并切换多个 **GitHub Copilot** 账号。本插件基于官方 `github-copilot` provider，补充账号管理、配额查看和几项 Copilot 工作流增强能力，**无需修改模型配置**。

默认能力与开关：

- **Copilot Network Retry** — 默认关闭；用于处理可重试的网络或证书类失败
- **Synthetic Agent Initiator** — 默认关闭；实验性开关，会偏离 upstream 当前稳定行为，发送或覆盖 `x-initiator=agent`，不保证平台一定不计费，且存在滥用判定与意外计费风险
- **Copilot Status Slash Command** — 默认开启；实验性 `/copilot-status` workaround，只把 TUI 作为主支持面，Web/App 不承诺一致体验

## 功能一览

- **多账号管理** — 添加多个 Copilot 账号，随时切换
- **配额查询** — 查看每个账号的剩余额度
- **导入认证** — 可从 OpenCode 认证存储导入
- **Copilot Network Retry** — 默认关闭；把可重试的 Copilot 网络或 TLS 失败归一化成 OpenCode 原生重试链路可识别的形态
- **Synthetic Agent Initiator** — 默认关闭；实验性开关，会偏离 upstream 稳定行为，发送或覆盖 `x-initiator=agent`，并伴随计费/滥用风险
- **`/copilot-status`** — 默认开启；实验性 slash command，会先弹出“正在拉取”toast，再弹出 quota 结果或错误 toast
- **无需模型配置** — 使用官方 provider，无需改模型

## 安装

<details open>
<summary><b>面向人类用户</b></summary>

**选项 A：让 LLM 帮你安装**

把下面这段话丢给任意 LLM（OpenCode / Claude Code / Cursor 等）：

```
请先查看 opencode-copilot-account-switcher 最新 GitHub Release 正文里的“升级方式”，然后严格执行其中带明确版本号的安装/升级命令。默认应使用带 `-g/--global` 的全局命令来更新你平时实际在用的 OpenCode 实例；只有你明确想改当前项目目录下的 `.opencode` 时，才省略 `-g`。不要手动编辑 OpenCode 配置，也不要使用裸包名或 latest。参考说明：https://raw.githubusercontent.com/jiwangyihao/opencode-copilot-account-switcher/master/README.md
```

**选项 B：手动安装**

1. **先查看最新 GitHub Release** 的 `## 升级方式` 小节。

2. **执行其中带明确版本号的全局命令**。例如当前版本是：

   ```bash
   opencode plugin opencode-copilot-account-switcher@1.0.0 --force -g
   ```

3. **如果你是刻意只想改当前项目目录下的 `.opencode`**，才使用不带 `-g` 的局部命令；否则默认不要省略 `-g`。

4. **如果是在升级且看起来没有更新**，先清理 OpenCode 插件缓存，再重新执行上面的带版本号命令。

   ```bash
   rm -rf ~/.cache/opencode/packages/opencode-copilot-account-switcher@*
   ```

5. **如果 OpenCode 已在运行，重启后再验证**。

6. **登录 GitHub Copilot**：

   ```bash
   opencode auth login --provider github-copilot
   ```

</details>

<details>
<summary><b>面向 LLM 智能体</b></summary>

### 步骤指引

1. 先读取本仓库**最新 GitHub Release 正文**，提取其中 `## 升级方式` 给出的**带明确版本号**命令。

2. 直接执行那条命令。默认应使用带 `-g/--global` 的全局命令来更新你平时实际在用的 OpenCode 实例；如果你明确只想改当前项目目录下的 `.opencode`，才省略 `-g`。例如当前版本：

   ```bash
   opencode plugin opencode-copilot-account-switcher@1.0.0 --force -g
   ```

3. 不要手动编辑 OpenCode 配置来安装或升级这个插件，也不要使用裸包名或 `latest`。

4. 如果执行后版本看起来仍然没更新，先清理 OpenCode 插件缓存，再重新执行同一条带版本号命令：

   ```bash
   rm -rf ~/.cache/opencode/packages/opencode-copilot-account-switcher@*
   ```

5. 如果 OpenCode 已在运行，重启后再验证。

### 验证

```bash
opencode auth login --provider github-copilot
```

> **说明**：最新 OpenCode 当前不会主动刷新已缓存的 npm 插件。升级时优先以最新 GitHub Release 正文里的 `## 升级方式` 为准；默认应走带 `-g` 的全局升级，只有明确想改当前项目 `.opencode` 时才省略 `-g`。

</details>

---

## 使用方式

在 Copilot 认证流程中运行：

```bash
opencode auth login --provider github-copilot
```

会出现交互式菜单（方向键 + 回车）：

- **添加账号**
- **从 auth.json 导入**
- **检查配额**
- **Copilot Network Retry 开关** — 默认关闭；仅影响 Copilot 请求的 `fetch` 路径，只处理可重试的网络/证书类失败
- **Synthetic Agent Initiator 开关** — 默认关闭；实验性开关，发送或覆盖 `x-initiator=agent`，会偏离 upstream 稳定行为，且不保证平台一定不计费
- **`/copilot-status`** — 默认开启；实验性 slash command，会先弹出“正在拉取”toast，再弹出 quota 结果或错误 toast
- **切换账号**
- **删除账号**
- **全部删除**

## 实验性 `/copilot-status`

- 默认：**开启**
- 性质：**实验特性 / workaround**，不是稳定公开 API
- 主支持面：**TUI-first**；Web/App 只保留风险说明，不承诺一致体验
- 触发方式：在正常对话里输入 `/copilot-status`
- 预期反馈：先显示“正在拉取 Copilot quota...” toast，再显示成功或失败结果 toast

如果你想关闭这个实验特性，可编辑账号存储文件 `~/.config/opencode/copilot-accounts.json`，加入或修改：

```json
{
  "experimentalStatusSlashCommandEnabled": false
}
```

关闭后：

- OpenCode 配置里不再注入 `/copilot-status`
- 即使手动输入 `/copilot-status`，插件也不会再进入该 workaround 执行链

## Copilot Network Retry

- 默认：**关闭**
- 作用范围：仅影响 `auth.loader` 返回的官方 Copilot 请求 `fetch` 路径
- 用途：有限处理 `failed to fetch`、`ECONNRESET`、`unknown certificate`、`self signed certificate` 等可重试网络/证书类失败
- 实现策略：尽量保留官方 loader 行为，再把可重试失败归一化给 OpenCode 原生重试链路判断是否重试
- 风险提示：因为插件仍然包裹了官方 fetch 路径，若 upstream 后续内部实现变化，仍可能产生行为漂移

## Synthetic Agent Initiator

- 默认：**关闭**
- 作用：发送或覆盖 `x-initiator=agent`，用于提前启用 upstream 开发中的 synthetic initiator 语义
- 与 upstream 当前稳定代码的关系：开启后，请求行为会与 upstream 当前稳定代码不一致；这是基于上游开发中语义的提前启用方案，不是 upstream 稳定默认行为
- 计费相关说明：平台可能更倾向于把压缩后继续工作、以及其他自动生成的 synthetic 提示消息排除在 premium request 计费范围之外，但这不是保证；实际是否计费、如何计费，始终由平台决定，请不要把它理解为“必然不计费”
- 风险提示：该行为可能更容易被平台判定为滥用；也可能因为上游实现、平台策略或服务端校验变化而失效，甚至产生意外计费
- 上游参考：
  - Issue: https://github.com/anomalyco/opencode/issues/8700
  - PR: https://github.com/anomalyco/opencode/pull/8721
  - Issue: https://github.com/anomalyco/opencode/issues/8766
  - Commit: https://github.com/anomalyco/opencode/commit/88226f30610d6038a431796a8ae5917199d49c74

## Upstream 同步机制

仓库中提交了一份 upstream 快照 `src/upstream/copilot-plugin.snapshot.ts`，并提供同步/校验脚本 `scripts/sync-copilot-upstream.mjs`。

常用命令：

```bash
npm run sync:copilot-snapshot -- --source <file-or-url> --upstream-commit <sha> --sync-date <YYYY-MM-DD>
npm run check:copilot-sync -- --source <file-or-url> --upstream-commit <sha> --sync-date <YYYY-MM-DD>
```

该脚本会生成或校验仓库中提交的 snapshot，并要求在更新正式 snapshot 时显式提供 upstream commit 与同步日期，用来尽早发现与官方 `opencode` `copilot.ts` 的行为漂移。

---

## 存储位置

账号信息保存于：

```
~/.config/opencode/copilot-accounts.json
```

---

## 常见问题

**需要改模型配置吗？**
不需要。本插件只做账号管理，继续使用官方 `github-copilot` provider。

**会替换官方 provider 吗？**
不会。它只是在官方 provider 基础上增加账号切换和配额查询。

**Copilot Network Retry 会替代 OpenCode 自己的重试逻辑吗？**
不会。插件的目标是把可重试的 Copilot 网络/TLS 失败归一化成 OpenCode 已识别的可重试错误形态，真正的是否重试与如何退避仍由 OpenCode 原生链路决定。

---

<a name="english"></a>

## English

Manage and switch between multiple **GitHub Copilot** accounts in **OpenCode**. The plugin builds on the official `github-copilot` provider to add account management, quota visibility, and a few Copilot workflow enhancements, with **no model reconfiguration required**.

Default behavior and optional switches:

- **Copilot Network Retry** — optional and off by default; handles retryable network or certificate-style failures
- **Synthetic Agent Initiator** — optional and off by default; experimental switch that diverges from stable upstream behavior, sends or overrides `x-initiator=agent`, does not guarantee non-billable treatment, and carries abuse or unexpected-billing risk
- **Copilot Status Slash Command** — enabled by default; experimental `/copilot-status` workaround with TUI-first support and no cross-client UX guarantee

## What You Get

- **Multi-account support** — add multiple Copilot accounts and switch anytime
- **Quota check** — view remaining quota per account
- **Auth import** — import Copilot tokens from OpenCode auth storage
- **Copilot Network Retry** — optional and off by default; normalizes retryable Copilot network or TLS failures so OpenCode's native retry path can handle them
- **Synthetic Agent Initiator** — optional and off by default; experimental switch that diverges from stable upstream behavior, sends or overrides `x-initiator=agent`, and carries billing/abuse risk
- **`/copilot-status`** — enabled by default; experimental slash command that shows a loading toast first and then a quota result or error toast
- **Zero model config** — no model changes required (official provider only)

## Installation

<details open>
<summary><b>For Humans</b></summary>

**Option A: Let an LLM do it**

Paste this into any LLM agent (OpenCode, Claude Code, Cursor, etc.):

```
First read the latest GitHub Release for opencode-copilot-account-switcher and execute the exact versioned install/upgrade command from its "Upgrade" section. By default, use the global command with `-g/--global` so you update the OpenCode instances you actually run; omit `-g` only if you intentionally want to change the current project's `.opencode`. Do not manually edit the OpenCode config, and do not use a bare package name or latest. Reference: https://raw.githubusercontent.com/jiwangyihao/opencode-copilot-account-switcher/master/README.md
```

**Option B: Manual setup**

1. **Read the latest GitHub Release** and look for the `## Upgrade` section.

2. **Run the exact versioned global command** from that section. For the current version, the command is:

   ```bash
   opencode plugin opencode-copilot-account-switcher@1.0.0 --force -g
   ```

3. **Only omit `-g` if you intentionally want to update the current project's `.opencode` instead of the global OpenCode config.**

4. **If an upgrade still looks stale**, clear the OpenCode plugin cache and rerun the same versioned command:

   ```bash
   rm -rf ~/.cache/opencode/packages/opencode-copilot-account-switcher@*
   ```

5. **If OpenCode is already running, restart it before verification**.

6. **Login** to GitHub Copilot:

   ```bash
   opencode auth login --provider github-copilot
   ```

</details>

<details>
<summary><b>For LLM Agents</b></summary>

### Step-by-Step Instructions

1. Read the **latest GitHub Release body** for this repository and extract the exact versioned command from `## Upgrade`.

2. Execute that command directly. By default, use the global command with `-g/--global`; only omit `-g` if you intentionally want to update the current project's `.opencode`. For the current version, the command is:

   ```bash
   opencode plugin opencode-copilot-account-switcher@1.0.0 --force -g
   ```

3. Do not install or upgrade this plugin by hand-editing the OpenCode config, and do not use a bare package name or `latest`.

4. If the installed version still does not change, clear the OpenCode plugin cache and rerun the same versioned command:

   ```bash
   rm -rf ~/.cache/opencode/packages/opencode-copilot-account-switcher@*
   ```

5. If OpenCode is already running, restart it before verification.

### Verification

```bash
opencode auth login --provider github-copilot
```

> **Note**: Current OpenCode does not reliably refresh cached npm plugins automatically. Prefer the exact versioned command from the latest GitHub Release. By default, that command should include `-g`; without `-g`, you are only changing the current project's `.opencode`.

</details>

---

## Usage

Run inside the GitHub Copilot auth flow:

```bash
opencode auth login --provider github-copilot
```

You will see an interactive menu. Use the built-in language switch action if you want to swap between Chinese and English labels.

- **Add account**
- **Import from auth.json**
- **Check quota**
- **Copilot Network Retry toggle** — off by default; only affects the Copilot `fetch` path for retryable network/certificate failures
- **Synthetic Agent Initiator toggle** — off by default; experimental switch that sends or overrides `x-initiator=agent`, diverges from stable upstream behavior, and does not guarantee non-billable treatment
- **`/copilot-status`** — enabled by default; experimental slash command workaround that shows a loading toast first and then a quota result or error toast
- **Switch account**
- **Delete account**
- **Delete all**

## Experimental `/copilot-status`

- Default: **enabled**
- Nature: **experimental / workaround**, not a stable public plugin command API
- Support scope: **TUI-first**; Web/App behavior is explicitly not guaranteed to match
- Trigger: enter `/copilot-status` in a normal chat session
- Expected feedback: first a `Fetching Copilot quota...` toast, then a success or error toast

To disable this experimental feature, edit `~/.config/opencode/copilot-accounts.json` and add or set:

```json
{
  "experimentalStatusSlashCommandEnabled": false
}
```

After disabling it:

- OpenCode config injection no longer includes `/copilot-status`
- Even manual `/copilot-status` input will no longer enter the plugin workaround execution chain

## Copilot Network Retry

- Default: **disabled**
- Scope: only the official Copilot request `fetch` path returned by `auth.loader`
- Purpose: limited handling for retryable network and certificate-style failures such as `failed to fetch`, `ECONNRESET`, `unknown certificate`, or `self signed certificate`
- Strategy: preserve official loader behavior, then normalize retryable failures so OpenCode's native retry pipeline can decide whether and when to retry
- Risk: because the plugin still wraps the official fetch path, upstream internal behavior may change over time and drift is possible

## Synthetic Agent Initiator

- Default: **disabled**
- Effect: sends or overrides `x-initiator=agent` to enable upstream's in-progress synthetic initiator semantics early
- Relation to stable upstream: when enabled, request behavior intentionally differs from the current stable upstream code path; this is an early-adoption path based on upstream work in progress, not the stable upstream default
- Billing note: compressed continue-working flows and other automatically generated synthetic prompt messages may be more likely to fall outside premium request billing, but that is not guaranteed; the platform decides whether and how billing applies, so do not treat this as "guaranteed non-billable"
- Risk: this behavior may be more likely to be treated as abuse, may stop working as upstream/platform behavior changes, and may also lead to unexpected billing
- Upstream references:
  - Issue: https://github.com/anomalyco/opencode/issues/8700
  - PR: https://github.com/anomalyco/opencode/pull/8721
  - Issue: https://github.com/anomalyco/opencode/issues/8766
  - Commit: https://github.com/anomalyco/opencode/commit/88226f30610d6038a431796a8ae5917199d49c74

## Upstream Sync

The repository includes a committed upstream snapshot at `src/upstream/copilot-plugin.snapshot.ts` plus a sync/check script at `scripts/sync-copilot-upstream.mjs`.

Useful commands:

```bash
npm run sync:copilot-snapshot -- --source <file-or-url> --upstream-commit <sha> --sync-date <YYYY-MM-DD>
npm run check:copilot-sync -- --source <file-or-url> --upstream-commit <sha> --sync-date <YYYY-MM-DD>
```

The script generates or checks the committed snapshot, requires upstream metadata for repository snapshot updates, and helps catch drift from the official `opencode` `copilot.ts` implementation.

---

## Storage

Accounts are stored in:

```
~/.config/opencode/copilot-accounts.json
```

---

## FAQ

**Do I need to change model configurations?**
No. This plugin only manages accounts and works with the official `github-copilot` provider.

**Does it replace the official provider?**
No. It uses the official provider and only adds account switching + quota checks.

**Does Copilot Network Retry replace OpenCode's retry logic?**
No. The plugin keeps retry policy inside OpenCode by normalizing retryable Copilot network/TLS failures into a shape that OpenCode already recognizes as retryable.

---

## License

MPL-2.0 License. See [LICENSE](LICENSE) for details.

